diff options
Diffstat (limited to 'erts')
174 files changed, 20740 insertions, 23120 deletions
diff --git a/erts/configure.in b/erts/configure.in index ba735fe921..021780ecc2 100644 --- a/erts/configure.in +++ b/erts/configure.in @@ -474,7 +474,7 @@ case $host_os in win32) # The ethread library requires _WIN32_WINNT of at least 0x0403. # -D_WIN32_WINNT=* from CPPFLAGS is saved in ETHR_DEFS. - CPPFLAGS="$CPPFLAGS -D_WIN32_WINNT=0x0501 -DWINVER=0x0501" + CPPFLAGS="$CPPFLAGS -D_WIN32_WINNT=0x0600 -DWINVER=0x0600" ;; darwin*) CPPFLAGS="$CPPFLAGS -D_XOPEN_SOURCE" @@ -584,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" diff --git a/erts/doc/src/absform.xml b/erts/doc/src/absform.xml index ccdecf44ec..13756ddfdc 100644 --- a/erts/doc/src/absform.xml +++ b/erts/doc/src/absform.xml @@ -182,7 +182,7 @@ <p>Individual patterns are represented as follows:</p> <list type="bulleted"> <item>If P is an atomic literal <c>L</c>, then Rep(P) = Rep(L).</item> - <item>If P is a binary pattern + <item>If P is a bit string pattern <c><<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 @@ -241,12 +241,13 @@ <p>An expression E is one of the following alternatives:</p> <list type="bulleted"> <item>If E is an atomic literal <c>L</c>, then Rep(E) = Rep(L).</item> - <item>If E is a binary comprehension + <item>If E is a bit string comprehension <c><<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 binary constructor <c><<E_1:Size_1/TSL_1, ..., E_k:Size_k/TSL_k>></c>, + <item>If E is a bit string constructor + <c><<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>. @@ -386,16 +387,17 @@ <item>If Q is a generator <c>P <- E</c>, where <c>P</c> is a pattern and <c>E</c> is an expression, then Rep(Q) = <c>{generate,LINE,Rep(P),Rep(E)}</c>.</item> - <item>If Q is a generator <c>P <= E</c>, where <c>P</c> is + <item>If Q is a bit string generator + <c>P <= E</c>, where <c>P</c> is a pattern and <c>E</c> is an expression, then 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>, and + <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> <list type="bulleted"> <item>If TS is a type specifier <c>A</c>, where <c>A</c> is an atom, @@ -473,7 +475,7 @@ <p>A guard test <c>Gt</c> is one of the following alternatives:</p> <list type="bulleted"> <item>If Gt is an atomic literal <c>L</c>, then Rep(Gt) = Rep(L).</item> - <item>If Gt is a binary constructor + <item>If Gt is a bit string constructor <c><<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 @@ -540,7 +542,7 @@ <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 a bitstring type <c><<_:M,_:_*N>></c>, + <item>If T is a bit string type <c><<_: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) = diff --git a/erts/doc/src/epmd.xml b/erts/doc/src/epmd.xml index 28fcc8f7af..7f61804bea 100644 --- a/erts/doc/src/epmd.xml +++ b/erts/doc/src/epmd.xml @@ -37,7 +37,7 @@ <comsummary> <p>Erlang Port Mapper Daemon</p> <taglist> - <tag><c><![CDATA[epmd [-d|-debug] [DbgExtra...] [-port No] [-daemon] [-relaxed_command_check]]]></c></tag> + <tag><c><![CDATA[epmd [-d|-debug] [DbgExtra...] [-address Addresses] [-port No] [-daemon] [-relaxed_command_check]]]></c></tag> <item> <p>Starts the port mapper daemon</p> </item> diff --git a/erts/doc/src/erl.xml b/erts/doc/src/erl.xml index 1c4a0056a7..096af096dc 100644 --- a/erts/doc/src/erl.xml +++ b/erts/doc/src/erl.xml @@ -387,6 +387,28 @@ <p>Replaces the path specified in the boot script. See <seealso marker="sasl:script">script(4)</seealso>.</p> </item> + <tag><c><![CDATA[-proto_dist Proto]]></c></tag> + <item> + <p>Specify a protocol for Erlang distribution.</p> + <taglist> + <tag><c>inet_tcp</c></tag> + <item> + <p>TCP over IPv4 (the default)</p> + </item> + <tag><c>inet_tls</c></tag> + <item> + <p>distribution over TLS/SSL</p> + </item> + <tag><c>inet6_tcp</c></tag> + <item> + <p>TCP over IPv6</p> + </item> + </taglist> + <p>For example, to start up IPv6 distributed nodes:</p> +<pre> +% <input>erl -name [email protected] -proto_dist inet6_tcp</input> +</pre> + </item> <tag><c><![CDATA[-remsh Node]]></c></tag> <item> <p>Starts Erlang with a remote shell connected to <c><![CDATA[Node]]></c>.</p> diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml index 803da382ed..350a8506f5 100644 --- a/erts/doc/src/erlang.xml +++ b/erts/doc/src/erlang.xml @@ -1811,7 +1811,8 @@ os_prompt% </pre> </item> </taglist> <note><p>On many platforms, the OS supports only status - codes 0-255.</p></note> + codes 0-255. A too large status code will be truncated by clearing + the high bits.</p></note> <p>For integer <c><anno>Status</anno></c>, the Erlang runtime system closes all ports and allows async threads to finish their operations before exiting. To exit without such flushing, use @@ -6468,32 +6469,44 @@ ok <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> @@ -7328,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, @@ -7347,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> @@ -7358,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> @@ -7373,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> @@ -7389,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> @@ -7398,15 +7433,23 @@ ok used by the runtime system. It is on the form "<major ver>.<minor ver>".</p> </item> - <tag><marker id="system_info_message_queue_data"><c>message_queue_data</c></marker></tag> + <tag><c>normal_multi_scheduling_blockers</c></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> + <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> @@ -7649,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/emulator/beam/atom.names b/erts/emulator/beam/atom.names index dca8b503bf..169b071cd7 100644 --- a/erts/emulator/beam/atom.names +++ b/erts/emulator/beam/atom.names @@ -125,7 +125,9 @@ atom binary_longest_suffix_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 @@ -190,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 @@ -305,6 +309,7 @@ atom index atom infinity atom info atom info_msg +atom init atom initial_call atom input atom internal @@ -612,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_catches.c b/erts/emulator/beam/beam_catches.c index c1fd17c65d..7a1f4901aa 100644 --- a/erts/emulator/beam/beam_catches.c +++ b/erts/emulator/beam/beam_catches.c @@ -143,7 +143,7 @@ BeamInstr *beam_catches_car(unsigned i) struct bc_pool* p = &bccix[erts_active_code_ix()]; if (i >= p->tabsize ) { - erl_exit(1, "beam_catches_delmod: index %#x is out of range\r\n", i); + erts_exit(ERTS_ERROR_EXIT, "beam_catches_delmod: index %#x is out of range\r\n", i); } return p->beam_catches[i].cp; } @@ -157,10 +157,10 @@ void beam_catches_delmod(unsigned head, BeamInstr *code, unsigned code_bytes, ASSERT((code_ix == erts_active_code_ix()) != bccix[erts_staging_code_ix()].is_staging); for(i = head; i != (unsigned)-1;) { if (i >= p->tabsize) { - erl_exit(1, "beam_catches_delmod: index %#x is out of range\r\n", i); + erts_exit(ERTS_ERROR_EXIT, "beam_catches_delmod: index %#x is out of range\r\n", i); } if( (char*)p->beam_catches[i].cp - (char*)code >= code_bytes ) { - erl_exit(1, + erts_exit(ERTS_ERROR_EXIT, "beam_catches_delmod: item %#x has cp %p which is not " "in module's range [%p,%p[\r\n", i, p->beam_catches[i].cp, code, ((char*)code + code_bytes)); diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c index 10f132abfc..a390422040 100644 --- a/erts/emulator/beam/beam_emu.c +++ b/erts/emulator/beam/beam_emu.c @@ -4730,7 +4730,7 @@ do { \ #ifdef NO_FPE_SIGNALS OpCase(fclearerror): OpCase(i_fcheckerror): - erl_exit(1, "fclearerror/i_fcheckerror without fpe signals (beam_emu)"); + erts_exit(ERTS_ERROR_EXIT, "fclearerror/i_fcheckerror without fpe signals (beam_emu)"); # define ERTS_NO_FPE_CHECK_INIT ERTS_FP_CHECK_INIT # define ERTS_NO_FPE_ERROR ERTS_FP_ERROR #else @@ -4885,7 +4885,7 @@ do { \ I = handle_error(c_p, I, reg, NULL); goto post_error_handling; default: - erl_exit(1, "hipe_mode_switch: result %u\n", c_p->def_arg_reg[3]); + erts_exit(ERTS_ERROR_EXIT, "hipe_mode_switch: result %u\n", c_p->def_arg_reg[3]); } } OpCase(hipe_call_count): { @@ -4997,7 +4997,7 @@ do { \ OpCase(label_L): OpCase(on_load): OpCase(line_I): - erl_exit(1, "meta op\n"); + erts_exit(ERTS_ERROR_EXIT, "meta op\n"); /* * One-time initialization of Beam emulator. @@ -5051,7 +5051,7 @@ do { \ } #ifdef NO_JUMP_TABLE default: - erl_exit(1, "unexpected op code %d\n",Go); + erts_exit(ERTS_ERROR_EXIT, "unexpected op code %d\n",Go); } #endif return; /* Never executed */ @@ -5096,7 +5096,7 @@ translate_gc_bif(void* gcf) } else if (gcf == erts_gc_binary_part_3) { return binary_part_3; } else { - erl_exit(1, "bad gc bif"); + erts_exit(ERTS_ERROR_EXIT, "bad gc bif"); } } @@ -5161,7 +5161,7 @@ handle_error(Process* c_p, BeamInstr* pc, Eterm* reg, BifFunction bf) Eterm* hp; Eterm Value = c_p->fvalue; Eterm Args = am_true; - c_p->i = pc; /* In case we call erl_exit(). */ + c_p->i = pc; /* In case we call erts_exit(). */ ASSERT(c_p->freason != TRAP); /* Should have been handled earlier. */ @@ -5225,7 +5225,7 @@ handle_error(Process* c_p, BeamInstr* pc, Eterm* reg, BifFunction bf) c_p->cp = 0; /* To avoid keeping stale references. */ return new_pc; } - if (c_p->catches > 0) erl_exit(1, "Catch not found"); + if (c_p->catches > 0) erts_exit(ERTS_ERROR_EXIT, "Catch not found"); } ERTS_SMP_UNREQ_PROC_MAIN_LOCK(c_p); terminate_proc(c_p, Value); diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c index 2654785ffc..37bb28c6f8 100644 --- a/erts/emulator/beam/bif.c +++ b/erts/emulator/beam/bif.c @@ -2242,7 +2242,7 @@ BIF_RETTYPE send_3(BIF_ALIST_3) erts_dsend_export_trap_context(p, ctx)); break; default: - erl_exit(ERTS_ABORT_EXIT, "send_3 invalid result %d\n", (int)result); + erts_exit(ERTS_ABORT_EXIT, "send_3 invalid result %d\n", (int)result); break; } @@ -2286,7 +2286,7 @@ static BIF_RETTYPE dsend_continue_trap_1(BIF_ALIST_1) BIF_TRAP1(&dsend_continue_trap_export, BIF_P, BIF_ARG_1); } default: - erl_exit(ERTS_ABORT_EXIT, "dsend_continue_trap invalid result %d\n", (int)result); + erts_exit(ERTS_ABORT_EXIT, "dsend_continue_trap invalid result %d\n", (int)result); break; } ASSERT(! "Can not arrive here"); @@ -2360,7 +2360,7 @@ Eterm erl_send(Process *p, Eterm to, Eterm msg) erts_dsend_export_trap_context(p, ctx)); break; default: - erl_exit(ERTS_ABORT_EXIT, "invalid send result %d\n", (int)result); + erts_exit(ERTS_ABORT_EXIT, "invalid send result %d\n", (int)result); break; } @@ -3738,7 +3738,7 @@ BIF_RETTYPE erts_debug_display_1(BIF_ALIST_1) erts_dsprintf_buf_t *dsbufp = erts_create_tmp_dsbuf(64); pres = erts_dsprintf(dsbufp, "%.*T\n", INT_MAX, BIF_ARG_1); if (pres < 0) - erl_exit(1, "Failed to convert term to string: %d (%s)\n", + erts_exit(ERTS_ERROR_EXIT, "Failed to convert term to string: %d (%s)\n", -pres, erl_errno_id(-pres)); hp = HAlloc(BIF_P, 2*dsbufp->str_len); /* we need length * 2 heap words */ res = buf_to_intlist(&hp, dsbufp->str, dsbufp->str_len, NIL); @@ -3760,7 +3760,7 @@ BIF_RETTYPE display_string_1(BIF_ALIST_1) } str = (char *) erts_alloc(ERTS_ALC_T_TMP, sizeof(char)*(len + 1)); if (intlist_to_buf(string, str, len) != len) - erl_exit(1, "%s:%d: Internal error\n", __FILE__, __LINE__); + erts_exit(ERTS_ERROR_EXIT, "%s:%d: Internal error\n", __FILE__, __LINE__); str[len] = '\0'; erts_fprintf(stderr, "%s", str); erts_free(ERTS_ALC_T_TMP, (void *) str); @@ -3780,7 +3780,7 @@ BIF_RETTYPE display_nl_0(BIF_ALIST_0) BIF_RETTYPE halt_0(BIF_ALIST_0) { VERBOSE(DEBUG_SYSTEM,("System halted by BIF halt()\n")); - erl_halt(0); + erts_halt(0); ERTS_BIF_YIELD1(bif_export[BIF_halt_1], BIF_P, am_undefined); } @@ -3793,17 +3793,18 @@ static char halt_msg[HALT_MSG_SIZE]; /* ARGSUSED */ BIF_RETTYPE halt_1(BIF_ALIST_1) { - Sint code; + Uint code; - if (is_small(BIF_ARG_1) && (code = signed_val(BIF_ARG_1)) >= 0) { + if (term_to_Uint_mask(BIF_ARG_1, &code)) { + int pos_int_code = (int) (code & INT_MAX); VERBOSE(DEBUG_SYSTEM,("System halted by BIF halt(%T)\n", BIF_ARG_1)); - erl_halt((int)(- code)); + erts_halt(pos_int_code); ERTS_BIF_YIELD1(bif_export[BIF_halt_1], BIF_P, am_undefined); } else if (ERTS_IS_ATOM_STR("abort", BIF_ARG_1)) { VERBOSE(DEBUG_SYSTEM,("System halted by BIF halt(%T)\n", BIF_ARG_1)); erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN); - erl_exit(ERTS_ABORT_EXIT, ""); + erts_exit(ERTS_ABORT_EXIT, ""); } else if (is_string(BIF_ARG_1) || BIF_ARG_1 == NIL) { Sint i; @@ -3814,11 +3815,11 @@ BIF_RETTYPE halt_1(BIF_ALIST_1) halt_msg[i] = '\0'; VERBOSE(DEBUG_SYSTEM,("System halted by BIF halt(%T)\n", BIF_ARG_1)); erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN); - erl_exit(ERTS_DUMP_EXIT, "%s\n", halt_msg); + erts_exit(ERTS_DUMP_EXIT, "%s\n", halt_msg); } else goto error; - return NIL; /* Pedantic (lint does not know about erl_exit) */ + return NIL; /* Pedantic (lint does not know about erts_exit) */ error: BIF_ERROR(BIF_P, BADARG); } @@ -3829,7 +3830,7 @@ BIF_RETTYPE halt_1(BIF_ALIST_1) /* ARGSUSED */ BIF_RETTYPE halt_2(BIF_ALIST_2) { - Sint code; + Uint code; Eterm optlist = BIF_ARG_2; int flush = 1; @@ -3856,23 +3857,24 @@ BIF_RETTYPE halt_2(BIF_ALIST_2) if (is_not_nil(optlist)) goto error; - if (is_small(BIF_ARG_1) && (code = signed_val(BIF_ARG_1)) >= 0) { + if (term_to_Uint_mask(BIF_ARG_1, &code)) { + int pos_int_code = (int) (code & INT_MAX); VERBOSE(DEBUG_SYSTEM, ("System halted by BIF halt(%T, %T)\n", BIF_ARG_1, BIF_ARG_2)); if (flush) { - erl_halt((int)(- code)); + erts_halt(pos_int_code); ERTS_BIF_YIELD1(bif_export[BIF_halt_1], BIF_P, am_undefined); } else { erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN); - erl_exit((int)(- code), ""); + erts_exit(pos_int_code, ""); } } else if (ERTS_IS_ATOM_STR("abort", BIF_ARG_1)) { VERBOSE(DEBUG_SYSTEM, ("System halted by BIF halt(%T, %T)\n", BIF_ARG_1, BIF_ARG_2)); erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN); - erl_exit(ERTS_ABORT_EXIT, ""); + erts_exit(ERTS_ABORT_EXIT, ""); } else if (is_string(BIF_ARG_1) || BIF_ARG_1 == NIL) { Sint i; @@ -3884,11 +3886,11 @@ BIF_RETTYPE halt_2(BIF_ALIST_2) VERBOSE(DEBUG_SYSTEM, ("System halted by BIF halt(%T, %T)\n", BIF_ARG_1, BIF_ARG_2)); erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN); - erl_exit(ERTS_DUMP_EXIT, "%s\n", halt_msg); + erts_exit(ERTS_DUMP_EXIT, "%s\n", halt_msg); } else goto error; - return NIL; /* Pedantic (lint does not know about erl_exit) */ + return NIL; /* Pedantic (lint does not know about erts_exit) */ error: BIF_ERROR(BIF_P, BADARG); } @@ -3944,7 +3946,7 @@ term2list_dsprintf(Process *p, Eterm term) erts_dsprintf_buf_t *dsbufp = erts_create_tmp_dsbuf(64); pres = erts_dsprintf(dsbufp, "%T", term); if (pres < 0) - erl_exit(1, "Failed to convert term to list: %d (%s)\n", + erts_exit(ERTS_ERROR_EXIT, "Failed to convert term to list: %d (%s)\n", -pres, erl_errno_id(-pres)); hp = HAlloc(p, 2*dsbufp->str_len); /* we need length * 2 heap words */ res = buf_to_intlist(&hp, dsbufp->str, dsbufp->str_len, NIL); @@ -4195,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: @@ -4243,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: @@ -4617,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); } /* @@ -4744,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, diff --git a/erts/emulator/beam/bif.h b/erts/emulator/beam/bif.h index a62eddf36b..46af552b39 100644 --- a/erts/emulator/beam/bif.h +++ b/erts/emulator/beam/bif.h @@ -338,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) \ +#define ERTS_BIF_PREP_YIELD_RETURN_X(RET, P, VAL, OP) \ do { \ ERTS_VBUMP_ALL_REDS(P); \ - ERTS_BIF_PREP_TRAP2(RET, &bif_return_trap_export, (P), (VAL), \ - (DEBUG_VAL)); \ + ERTS_BIF_PREP_TRAP2(RET, &bif_return_trap_export, (P), (VAL), (OP));\ } while (0) -#else -#define ERTS_BIF_PREP_YIELD_RETURN_X(RET, P, VAL, DEBUG_VAL) \ -do { \ - ERTS_VBUMP_ALL_REDS(P); \ - ERTS_BIF_PREP_TRAP1(RET, &bif_return_trap_export, (P), (VAL)); \ -} 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/big.c b/erts/emulator/beam/big.c index 11838e24ef..c738a9ecf5 100644 --- a/erts/emulator/beam/big.c +++ b/erts/emulator/beam/big.c @@ -2035,6 +2035,32 @@ term_to_Uint(Eterm term, Uint *up) } } +/* same as term_to_Uint() + but also accept larger bignums by masking + */ +int +term_to_Uint_mask(Eterm term, Uint *up) +{ + if (is_small(term)) { + Sint i = signed_val(term); + if (i < 0) { + *up = BADARG; + return 0; + } + *up = (Uint) i; + return 1; + } else if (is_big(term) && !big_sign(term)) { + ErtsDigit* xr = big_v(term); + + ERTS_CT_ASSERT(sizeof(ErtsDigit) == sizeof(Uint)); + *up = (Uint)*xr; /* just pick first word */ + return 1; + } else { + *up = BADARG; + return 0; + } +} + int term_to_UWord(Eterm term, UWord *up) { diff --git a/erts/emulator/beam/big.h b/erts/emulator/beam/big.h index 9c92de6b55..ee51e5d313 100644 --- a/erts/emulator/beam/big.h +++ b/erts/emulator/beam/big.h @@ -154,6 +154,7 @@ Eterm bytes_to_big(byte*, dsize_t, int, Eterm*); byte* big_to_bytes(Eterm, byte*); int term_to_Uint(Eterm, Uint*); +int term_to_Uint_mask(Eterm, Uint*); int term_to_UWord(Eterm, UWord*); int term_to_Sint(Eterm, Sint*); #if HAVE_INT64 diff --git a/erts/emulator/beam/binary.c b/erts/emulator/beam/binary.c index d3e481c7f9..3fd284b589 100644 --- a/erts/emulator/beam/binary.c +++ b/erts/emulator/beam/binary.c @@ -50,7 +50,7 @@ erts_init_binary(void) if ((((UWord) &((Binary *) 0)->orig_bytes[0]) % ((UWord) 8)) != 0) { /* I assume that any compiler should be able to optimize this away. If not, this test is not very expensive... */ - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "Internal error: Address of orig_bytes[0] of a Binary" " is *not* 8-byte aligned\n"); } diff --git a/erts/emulator/beam/break.c b/erts/emulator/beam/break.c index 2c8ecf04be..8c039ef132 100644 --- a/erts/emulator/beam/break.c +++ b/erts/emulator/beam/break.c @@ -104,7 +104,7 @@ process_killer(void) erts_printf("(k)ill (n)ext (r)eturn:\n"); while(1) { if ((j = sys_get_key(0)) <= 0) - erl_exit(0, ""); + erts_exit(0, ""); switch(j) { case 'k': { ErtsProcLocks rp_locks = ERTS_PROC_LOCKS_XSIG_SEND; @@ -493,7 +493,7 @@ do_break(void) halt immediately if break is called */ mode = erts_read_env("ERL_CONSOLE_MODE"); if (mode && strcmp(mode, "window") != 0) - erl_exit(0, ""); + erts_exit(0, ""); erts_free_read_env(mode); #endif /* __WIN32__ */ @@ -503,7 +503,7 @@ do_break(void) while (1) { if ((i = sys_get_key(0)) <= 0) - erl_exit(0, ""); + erts_exit(0, ""); switch (i) { case 'q': case 'a': @@ -513,9 +513,9 @@ do_break(void) * The usual reason for a read error is Ctrl-C. Treat this as * 'a' to avoid infinite loop. */ - erl_exit(0, ""); + erts_exit(0, ""); case 'A': /* Halt generating crash dump */ - erl_exit(1, "Crash dump requested by user"); + erts_exit(ERTS_ERROR_EXIT, "Crash dump requested by user"); case 'c': return; case 'p': @@ -785,7 +785,7 @@ erl_crash_dump_v(char *file, int line, char* fmt, va_list args) erts_fdprintf(fd, "Atoms: %d\n", atom_table_size()); #ifdef USE_THREADS - /* We want to note which thread it was that called erl_exit */ + /* We want to note which thread it was that called erts_exit */ if (erts_get_scheduler_data()) { erts_fdprintf(fd, "Calling Thread: scheduler:%d\n", erts_get_scheduler_data()->no); diff --git a/erts/emulator/beam/copy.c b/erts/emulator/beam/copy.c index 67a96f6442..b38ebe066b 100644 --- a/erts/emulator/beam/copy.c +++ b/erts/emulator/beam/copy.c @@ -58,7 +58,7 @@ Eterm copy_object_x(Eterm obj, Process* to, Uint extra) { res = copy_struct(obj, size, &hp, &to->off_heap); #ifdef DEBUG if (eq(obj, res) == 0) { - erl_exit(ERTS_ABORT_EXIT, "copy not equal to source\n"); + erts_exit(ERTS_ABORT_EXIT, "copy not equal to source\n"); } #endif return res; @@ -174,7 +174,7 @@ Uint size_object(Eterm obj) } break; default: - erl_exit(ERTS_ABORT_EXIT, "size_object: bad hashmap type %d\n", MAP_HEADER_TYPE(hdr)); + erts_exit(ERTS_ABORT_EXIT, "size_object: bad hashmap type %d\n", MAP_HEADER_TYPE(hdr)); } break; case SUB_BINARY_SUBTAG: @@ -205,7 +205,7 @@ Uint size_object(Eterm obj) } break; case BIN_MATCHSTATE_SUBTAG: - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "size_object: matchstate term not allowed"); default: sum += thing_arityval(hdr) + 1; @@ -223,7 +223,7 @@ Uint size_object(Eterm obj) obj = ESTACK_POP(s); break; default: - erl_exit(ERTS_ABORT_EXIT, "size_object: bad tag for %#x\n", obj); + erts_exit(ERTS_ABORT_EXIT, "size_object: bad tag for %#x\n", obj); } } } @@ -438,10 +438,10 @@ Uint size_shared(Eterm obj) goto pop_next; } default: - erl_exit(ERTS_ABORT_EXIT, "size_shared: bad hashmap type %d\n", MAP_HEADER_TYPE(hdr)); + erts_exit(ERTS_ABORT_EXIT, "size_shared: bad hashmap type %d\n", MAP_HEADER_TYPE(hdr)); } case BIN_MATCHSTATE_SUBTAG: - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "size_shared: matchstate term not allowed"); default: sum += thing_arityval(hdr) + 1; @@ -457,7 +457,7 @@ Uint size_shared(Eterm obj) obj = EQUEUE_GET(s); break; default: - erl_exit(ERTS_ABORT_EXIT, "size_shared: bad tag for %#x\n", obj); + erts_exit(ERTS_ABORT_EXIT, "size_shared: bad tag for %#x\n", obj); } } @@ -569,7 +569,7 @@ cleanup: goto cleanup_next; } default: - erl_exit(ERTS_ABORT_EXIT, "size_shared: bad hashmap type %d\n", MAP_HEADER_TYPE(hdr)); + erts_exit(ERTS_ABORT_EXIT, "size_shared: bad hashmap type %d\n", MAP_HEADER_TYPE(hdr)); } default: goto cleanup_next; @@ -584,7 +584,7 @@ cleanup: obj = EQUEUE_GET(s); break; default: - erl_exit(ERTS_ABORT_EXIT, "size_shared: bad tag for %#x\n", obj); + erts_exit(ERTS_ABORT_EXIT, "size_shared: bad tag for %#x\n", obj); } } @@ -643,7 +643,7 @@ Eterm copy_struct_x(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap, Uint goto L_copy_list; case TAG_PRIMARY_BOXED: argp = &res; goto L_copy_boxed; default: - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "%s, line %d: Internal error in copy_struct: 0x%08x\n", __FILE__, __LINE__,obj); } @@ -691,7 +691,7 @@ Eterm copy_struct_x(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap, Uint case TAG_PRIMARY_IMMED1: *tailp = obj; goto L_copy; case TAG_PRIMARY_BOXED: argp = tailp; goto L_copy_boxed; default: - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "%s, line %d: Internal error in copy_struct: 0x%08x\n", __FILE__, __LINE__,obj); } @@ -869,11 +869,11 @@ Eterm copy_struct_x(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap, Uint *argp = make_hashmap(tp); break; default: - erl_exit(ERTS_ABORT_EXIT, "copy_struct: bad hashmap type %d\n", MAP_HEADER_TYPE(hdr)); + erts_exit(ERTS_ABORT_EXIT, "copy_struct: bad hashmap type %d\n", MAP_HEADER_TYPE(hdr)); } break; case BIN_MATCHSTATE_SUBTAG: - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "copy_struct: matchstate term not allowed"); default: i = thing_arityval(hdr)+1; @@ -901,13 +901,13 @@ Eterm copy_struct_x(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap, Uint } else { #ifdef DEBUG if (htop != hbot) - erl_exit(ERTS_ABORT_EXIT, + 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) { - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "Internal error in copy_struct(): htop, hbot overrun\n"); } #endif @@ -1246,10 +1246,10 @@ Uint copy_shared_calculate(Eterm obj, erts_shcopy_t *info) goto pop_next; } default: - erl_exit(ERTS_ABORT_EXIT, "copy_shared_calculate: bad hashmap type %d\n", MAP_HEADER_TYPE(hdr)); + erts_exit(ERTS_ABORT_EXIT, "copy_shared_calculate: bad hashmap type %d\n", MAP_HEADER_TYPE(hdr)); } case BIN_MATCHSTATE_SUBTAG: - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "size_shared: matchstate term not allowed"); default: sum += thing_arityval(hdr) + 1; @@ -1278,7 +1278,7 @@ Uint copy_shared_calculate(Eterm obj, erts_shcopy_t *info) obj = EQUEUE_GET(s); break; default: - erl_exit(ERTS_ABORT_EXIT, "[pid=%T] size_shared: bad tag for %#x\n", obj); + erts_exit(ERTS_ABORT_EXIT, "[pid=%T] size_shared: bad tag for %#x\n", obj); } } } @@ -1530,7 +1530,7 @@ Uint copy_shared_perform(Eterm obj, Uint size, erts_shcopy_t *info, goto cleanup_next; } default: - erl_exit(ERTS_ABORT_EXIT, "copy_shared_perform: bad hashmap type %d\n", MAP_HEADER_TYPE(hdr)); + 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; @@ -1682,7 +1682,7 @@ Uint copy_shared_perform(Eterm obj, Uint size, erts_shcopy_t *info, hscan += MAP_HEADER_ARITY(*hscan) + 1; break; default: - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "copy_shared_perform: bad hashmap type %d\n", MAP_HEADER_TYPE(*hscan)); } @@ -1711,7 +1711,7 @@ Uint copy_shared_perform(Eterm obj, Uint size, erts_shcopy_t *info, ASSERT(resp < hp); break; default: - erl_exit(ERTS_ABORT_EXIT, "size_shared: bad tag for %#x\n", obj); + erts_exit(ERTS_ABORT_EXIT, "size_shared: bad tag for %#x\n", obj); } } @@ -1744,7 +1744,7 @@ all_clean: if (eq(saved_obj, result) == 0) { erts_fprintf(stderr, "original = %T\n", saved_obj); erts_fprintf(stderr, "copy = %T\n", result); - erl_exit(ERTS_ABORT_EXIT, "copy (shared) not equal to source\n"); + erts_exit(ERTS_ABORT_EXIT, "copy (shared) not equal to source\n"); } #endif diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c index e31ef29562..fa385f105d 100644 --- a/erts/emulator/beam/dist.c +++ b/erts/emulator/beam/dist.c @@ -1942,7 +1942,7 @@ erts_dsig_send(ErtsDSigData *dsdp, struct erts_dsig_send_context* ctx) goto done; } default: - erl_exit(ERTS_ABORT_EXIT, "dsig_send invalid phase (%d)\n", (int)ctx->phase); + erts_exit(ERTS_ABORT_EXIT, "dsig_send invalid phase (%d)\n", (int)ctx->phase); } } @@ -1963,7 +1963,7 @@ dist_port_command(Port *prt, ErtsDistOutputBuf *obuf) ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt)); if (size > (Uint) INT_MAX) - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "Absurdly large distribution output data buffer " "(%beu bytes) passed.\n", size); @@ -2003,7 +2003,7 @@ dist_port_commandv(Port *prt, ErtsDistOutputBuf *obuf) ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(prt)); if (size > (Uint) INT_MAX) - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "Absurdly large distribution output data buffer " "(%beu bytes) passed.\n", size); @@ -3370,7 +3370,7 @@ send_nodes_mon_msgs(Process *c_p, Eterm what, Eterm node, Eterm type, Eterm reas continue; break; default: - erl_exit(ERTS_ABORT_EXIT, "Bad node type found\n"); + erts_exit(ERTS_ABORT_EXIT, "Bad node type found\n"); } } @@ -3679,7 +3679,7 @@ erts_processes_monitoring_nodes(Process *c_p) case ERTS_NODES_MON_OPT_TYPES: type = am_all; break; case ERTS_NODES_MON_OPT_TYPE_VISIBLE: type = am_visible; break; case ERTS_NODES_MON_OPT_TYPE_HIDDEN: type = am_hidden; break; - default: erl_exit(ERTS_ABORT_EXIT, "Bad node type found\n"); + default: erts_exit(ERTS_ABORT_EXIT, "Bad node type found\n"); } olist = erts_bld_cons(hpp, szp, erts_bld_tuple(hpp, szp, 2, diff --git a/erts/emulator/beam/erl_afit_alloc.c b/erts/emulator/beam/erl_afit_alloc.c index 47dafa53c0..4b0541c10e 100644 --- a/erts/emulator/beam/erl_afit_alloc.c +++ b/erts/emulator/beam/erl_afit_alloc.c @@ -241,7 +241,7 @@ info_options(Allctr_t *allctr, if (hpp || szp) { if (!atoms_initialized) - erl_exit(1, "%s:%d: Internal error: Atoms not initialized", + erts_exit(ERTS_ERROR_EXIT, "%s:%d: Internal error: Atoms not initialized", __FILE__, __LINE__);; res = NIL; diff --git a/erts/emulator/beam/erl_alloc.c b/erts/emulator/beam/erl_alloc.c index 806f569c38..490e0c0915 100644 --- a/erts/emulator/beam/erl_alloc.c +++ b/erts/emulator/beam/erl_alloc.c @@ -165,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 { @@ -217,7 +219,7 @@ typedef struct { 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 { \ @@ -294,6 +296,9 @@ 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; @@ -665,11 +670,11 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop) if (mlockall(MCL_CURRENT|MCL_FUTURE) != 0) { int err = errno; char *errstr = err ? strerror(err) : "unknown"; - erl_exit(-1, "Failed to lock physical memory: %s (%d)\n", + erts_exit(1, "Failed to lock physical memory: %s (%d)\n", errstr, err); } #else - erl_exit(-1, "Failed to lock physical memory: Not supported\n"); + erts_exit(1, "Failed to lock physical memory: Not supported\n"); #endif } @@ -769,9 +774,6 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop) #if HAVE_ERTS_MSEG init.mseg.nos = erts_no_schedulers; erts_mseg_init(&init.mseg); -# if defined(ARCH_64) && defined(ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION) - erts_mmap_init(&erts_literal_mmapper, &init.mseg.literal_mmap); -# endif #endif erts_alcu_init(&init.alloc_util); @@ -810,13 +812,13 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop) for (i = ERTS_ALC_A_MIN; i <= ERTS_ALC_A_MAX; i++) { if (!erts_allctrs[i].alloc) - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "Missing alloc function for %s\n", ERTS_ALC_A2AD(i)); if (!erts_allctrs[i].realloc) - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "Missing realloc function for %s\n", ERTS_ALC_A2AD(i)); if (!erts_allctrs[i].free) - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "Missing free function for %s\n", ERTS_ALC_A2AD(i)); } @@ -887,7 +889,7 @@ erts_alloc_late_init(void) static void * erts_realloc_fixed_size(ErtsAlcType_t type, void *extra, void *p, Uint size) { - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "Attempt to reallocate a block of the fixed size type %s\n", ERTS_ALC_T2TD(type)); } @@ -969,7 +971,7 @@ set_au_allocator(ErtsAlcType_t alctr_n, struct au_init *init, int ncpu) #endif { #ifdef ERTS_SMP - erl_exit(ERTS_ABORT_EXIT, "%salloc is not thread safe\n", + erts_exit(ERTS_ABORT_EXIT, "%salloc is not thread safe\n", init->init.util.name_prefix); #else af->alloc = erts_alcu_alloc; @@ -1014,7 +1016,7 @@ start_au_allocator(ErtsAlcType_t alctr_n, * tspec->size) + ERTS_CACHE_LINE_SIZE - 1)); if (!states) - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "Failed to allocate allocator states for %salloc\n", init->init.util.name_prefix); tspec->allctr = (Allctr_t **) states; @@ -1042,7 +1044,7 @@ start_au_allocator(ErtsAlcType_t alctr_n, (tot_fix_list_size + ERTS_CACHE_LINE_SIZE - 1)); if (!fix_lists) - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "Failed to allocate fix lists for %salloc\n", init->init.util.name_prefix); @@ -1116,7 +1118,7 @@ start_au_allocator(ErtsAlcType_t alctr_n, } if (!as) - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "Failed to start %salloc\n", init->init.util.name_prefix); ASSERT(as == (void *) as0); @@ -1352,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; @@ -1423,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) { @@ -1472,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; @@ -1908,7 +1935,7 @@ erts_alc_fatal_error(int error, int func, ErtsAlcType_t n, ...) case ERTS_ALC_O_FREE: op_str = "free"; break; default: op_str = "UNKNOWN"; break; } - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "%s: %s operation not supported (memory type: \"%s\")\n", allctr_str, op_str, t_str); break; @@ -1922,18 +1949,18 @@ erts_alc_fatal_error(int error, int func, ErtsAlcType_t n, ...) va_start(argp, n); size = va_arg(argp, Uint); va_end(argp); - erl_exit(-1, + erts_exit(1, "%s: Cannot %s %lu bytes of memory (of type \"%s\").\n", allctr_str, op, size, t_str); break; } case ERTS_ALC_E_NOALLCTR: - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "erts_alloc: Unknown allocator type: %d\n", ERTS_ALC_T2A(ERTS_ALC_N2T(n))); break; default: - erl_exit(ERTS_ABORT_EXIT, "erts_alloc: Unknown error: %d\n", error); + erts_exit(ERTS_ABORT_EXIT, "erts_alloc: Unknown error: %d\n", error); break; } } @@ -3120,7 +3147,7 @@ reply_alloc_info(void *vair) make_small(0), ainfo); } else { - erl_exit(ERTS_ABORT_EXIT, "%s:%d: internal error\n", + erts_exit(ERTS_ABORT_EXIT, "%s:%d: internal error\n", __FILE__, __LINE__); } } @@ -3354,7 +3381,7 @@ void *safe_realloc(void *ptr, Uint sz) * Keep alloc_SUITE_data/allocator_test.h updated if changes are made * * to erts_alc_test() * \* */ -#define ERTS_ALC_TEST_ABORT erl_exit(ERTS_ABORT_EXIT, "%s:%d: Internal error\n") +#define ERTS_ALC_TEST_ABORT erts_exit(ERTS_ABORT_EXIT, "%s:%d: Internal error\n") UWord erts_alc_test(UWord op, UWord a1, UWord a2, UWord a3) { @@ -3819,7 +3846,7 @@ check_memory_fence(void *ptr, Uint *size, ErtsAlcType_t n, int func) found_type = GET_TYPE_OF_PATTERN(pre_pattern); if (pre_pattern != MK_PATTERN(n)) { if ((FIXED_FENCE_PATTERN_MASK & pre_pattern) != FIXED_FENCE_PATTERN) - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "ERROR: Fence at beginning of memory block (p=0x%u) " "clobbered.\n", (UWord) ptr); @@ -3836,12 +3863,12 @@ check_memory_fence(void *ptr, Uint *size, ErtsAlcType_t n, int func) char *op_str; if ((FIXED_FENCE_PATTERN_MASK & post_pattern) != FIXED_FENCE_PATTERN) - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "ERROR: Fence at end of memory block (p=0x%u, sz=%u) " "clobbered.\n", (UWord) ptr, (UWord) sz); if (found_type != GET_TYPE_OF_PATTERN(post_pattern)) - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "ERROR: Fence around memory block (p=0x%u, sz=%u) " "clobbered.\n", (UWord) ptr, (UWord) sz); @@ -3864,7 +3891,7 @@ check_memory_fence(void *ptr, Uint *size, ErtsAlcType_t n, int func) default: op_str = "???"; break; } - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "ERROR: Memory block (p=0x%u, sz=%u) allocated as type \"%s\"," " but %s as type \"%s\".\n", (UWord) ptr, (UWord) sz, ftype, op_str, otype); diff --git a/erts/emulator/beam/erl_alloc_util.c b/erts/emulator/beam/erl_alloc_util.c index 3230b6ef34..5e7dd7cce8 100644 --- a/erts/emulator/beam/erl_alloc_util.c +++ b/erts/emulator/beam/erl_alloc_util.c @@ -4718,7 +4718,7 @@ make_name_atoms(Allctr_t *allctr) size_t prefix_len = strlen(allctr->name_prefix); if (prefix_len > MAX_ATOM_CHARACTERS + sizeof(realloc) - 1) - erl_exit(1,"Too long allocator name: %salloc\n",allctr->name_prefix); + erts_exit(ERTS_ERROR_EXIT,"Too long allocator name: %salloc\n",allctr->name_prefix); memcpy((void *) buf, (void *) allctr->name_prefix, prefix_len); @@ -5912,7 +5912,7 @@ erts_alcu_start(Allctr_t *allctr, AllctrInit_t *init) /* erts_alcu_start assumes that allctr has been zeroed */ if (((UWord)allctr & ERTS_CRR_ALCTR_FLG_MASK) != 0) { - erl_exit(ERTS_ABORT_EXIT, "%s:%d:erts_alcu_start: Alignment error\n", + erts_exit(ERTS_ABORT_EXIT, "%s:%d:erts_alcu_start: Alignment error\n", __FILE__, __LINE__); } @@ -6128,7 +6128,7 @@ erts_alcu_start(Allctr_t *allctr, AllctrInit_t *init) if (allctr->thread_safe) erts_mtx_destroy(&allctr->mutex); #endif - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "Failed to create main carrier for %salloc\n", init->name_prefix); } @@ -6273,7 +6273,7 @@ erts_alcu_test(UWord op, UWord a1, UWord a2) case 0x019: return (UWord) PREV_BLK((Block_t *) a1); case 0x01a: return (UWord) IS_MBC_FIRST_BLK((Allctr_t*)a1, (Block_t *) a2); case 0x01b: return (UWord) sizeof(Unit_t); - case 0x01c: return (unsigned long) BLK_TO_MBC((Block_t*) a1); + case 0x01c: return (UWord) BLK_TO_MBC((Block_t*) a1); case 0x01d: ((Allctr_t*) a1)->add_mbc((Allctr_t*)a1, (Carrier_t*)a2); break; case 0x01e: ((Allctr_t*) a1)->remove_mbc((Allctr_t*)a1, (Carrier_t*)a2); break; #ifdef ERTS_SMP @@ -6344,7 +6344,7 @@ erts_alcu_verify_unused(Allctr_t *allctr) if (no) { UWord sz = allctr->sbcs.blocks.curr.size; sz += allctr->mbcs.blocks.curr.size; - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "%salloc() used when expected to be unused!\n" "Total amount of blocks allocated: %bpu\n" "Total amount of bytes allocated: %bpu\n", diff --git a/erts/emulator/beam/erl_ao_firstfit_alloc.c b/erts/emulator/beam/erl_ao_firstfit_alloc.c index 19420af8ab..5cd067ff54 100644 --- a/erts/emulator/beam/erl_ao_firstfit_alloc.c +++ b/erts/emulator/beam/erl_ao_firstfit_alloc.c @@ -1035,7 +1035,7 @@ info_options(Allctr_t *allctr, if (hpp || szp) { if (!atoms_initialized) - erl_exit(1, "%s:%d: Internal error: Atoms not initialized", + erts_exit(ERTS_ERROR_EXIT, "%s:%d: Internal error: Atoms not initialized", __FILE__, __LINE__);; res = NIL; diff --git a/erts/emulator/beam/erl_bestfit_alloc.c b/erts/emulator/beam/erl_bestfit_alloc.c index fb853b65ab..f39a18ac88 100644 --- a/erts/emulator/beam/erl_bestfit_alloc.c +++ b/erts/emulator/beam/erl_bestfit_alloc.c @@ -940,7 +940,7 @@ info_options(Allctr_t *allctr, if (hpp || szp) { if (!atoms_initialized) - erl_exit(1, "%s:%d: Internal error: Atoms not initialized", + erts_exit(ERTS_ERROR_EXIT, "%s:%d: Internal error: Atoms not initialized", __FILE__, __LINE__);; res = NIL; diff --git a/erts/emulator/beam/erl_bif_ddll.c b/erts/emulator/beam/erl_bif_ddll.c index 2b1d875bfe..f006856b6a 100644 --- a/erts/emulator/beam/erl_bif_ddll.c +++ b/erts/emulator/beam/erl_bif_ddll.c @@ -1309,7 +1309,7 @@ static Eterm notify_when_loaded(Process *p, Eterm name_term, char *name, ErtsPro case ERL_DE_FORCE_RELOAD: break; default: - erl_exit(1,"Internal error, unknown state %u in dynamic driver.", drv->handle->status); + erts_exit(ERTS_ERROR_EXIT,"Internal error, unknown state %u in dynamic driver.", drv->handle->status); } p->flags |= F_USING_DDLL; r = add_monitor(p, drv->handle, ERL_DE_PROC_AWAIT_LOAD); diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c index e4baff87f4..8c748c9bf7 100644 --- a/erts/emulator/beam/erl_bif_info.c +++ b/erts/emulator/beam/erl_bif_info.c @@ -320,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') @@ -932,7 +930,7 @@ BIF_RETTYPE process_info_1(BIF_ALIST_1) case ERTS_PI_FAIL_TYPE_AWAIT_EXIT: ERTS_BIF_AWAIT_X_DATA_TRAP(BIF_P, BIF_ARG_1, am_undefined); default: - erl_exit(ERTS_ABORT_EXIT, "%s:%d: Internal error", __FILE__, __LINE__); + erts_exit(ERTS_ABORT_EXIT, "%s:%d: Internal error", __FILE__, __LINE__); } } @@ -972,7 +970,7 @@ BIF_RETTYPE process_info_2(BIF_ALIST_2) case ERTS_PI_FAIL_TYPE_AWAIT_EXIT: ERTS_BIF_AWAIT_X_DATA_TRAP(BIF_P, BIF_ARG_1, am_undefined); default: - erl_exit(ERTS_ABORT_EXIT, "%s:%d: Internal error", + erts_exit(ERTS_ABORT_EXIT, "%s:%d: Internal error", __FILE__, __LINE__); } } @@ -1727,7 +1725,7 @@ info_1_tuple(Process* BIF_P, /* Pointer to current process. */ return res; buf = (char *) erts_alloc(ERTS_ALC_T_TMP, len+1); if (intlist_to_buf(*tp, buf, len) != len) - erl_exit(1, "%s:%d: Internal error\n", __FILE__, __LINE__); + erts_exit(ERTS_ERROR_EXIT, "%s:%d: Internal error\n", __FILE__, __LINE__); buf[len] = '\0'; res = erts_instr_dump_memory_map(buf) ? am_true : am_false; erts_free(ERTS_ALC_T_TMP, (void *) buf); @@ -1746,7 +1744,7 @@ info_1_tuple(Process* BIF_P, /* Pointer to current process. */ return res; buf = (char *) erts_alloc(ERTS_ALC_T_TMP, len+1); if (intlist_to_buf(tp[1], buf, len) != len) - erl_exit(1, "%s:%d: Internal error\n", __FILE__, __LINE__); + erts_exit(ERTS_ERROR_EXIT, "%s:%d: Internal error\n", __FILE__, __LINE__); buf[len] = '\0'; res = erts_instr_dump_stat(buf, 1) ? am_true : am_false; erts_free(ERTS_ALC_T_TMP, (void *) buf); @@ -2044,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) { @@ -2518,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)) { @@ -2642,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() @@ -3813,7 +3869,7 @@ static void broken_halt_test(Eterm bif_arg_2) #if defined(ERTS_HAVE_TRY_CATCH) erts_get_scheduler_data()->run_queue = NULL; #endif - erl_exit(ERTS_DUMP_EXIT, "%T", bif_arg_2); + erts_exit(ERTS_DUMP_EXIT, "%T", bif_arg_2); } @@ -4058,7 +4114,7 @@ BIF_RETTYPE erts_debug_set_internal_state_2(BIF_ALIST_2) BIF_RET(am_true); } else if (ERTS_IS_ATOM_STR("abort", BIF_ARG_1)) { - erl_exit(ERTS_ABORT_EXIT, "%T\n", BIF_ARG_2); + erts_exit(ERTS_ABORT_EXIT, "%T\n", BIF_ARG_2); } else if (ERTS_IS_ATOM_STR("kill_dist_connection", BIF_ARG_1)) { DistEntry *dep = erts_sysname_to_connected_dist_entry(BIF_ARG_2); diff --git a/erts/emulator/beam/erl_bif_port.c b/erts/emulator/beam/erl_bif_port.c index 3acc1d7bbd..86bcf43678 100644 --- a/erts/emulator/beam/erl_bif_port.c +++ b/erts/emulator/beam/erl_bif_port.c @@ -823,7 +823,7 @@ open_port(Process* p, Eterm name, Eterm settings, int *err_typep, int *err_nump) } else { name_buf = (char *) erts_alloc(ERTS_ALC_T_TMP, i + 1); if (intlist_to_buf(name, name_buf, i) != i) - erl_exit(1, "%s:%d: Internal error\n", __FILE__, __LINE__); + erts_exit(ERTS_ERROR_EXIT, "%s:%d: Internal error\n", __FILE__, __LINE__); name_buf[i] = '\0'; } driver = &vanilla_driver; @@ -1201,7 +1201,7 @@ static Eterm http_bld_uri(struct packet_callback_args* pca, return erts_bld_tuple(hpp, szp, 3, am_scheme, s1, s2); default: - erl_exit(1, "%s, line %d: type=%u\n", __FILE__, __LINE__, uri->type); + erts_exit(ERTS_ERROR_EXIT, "%s, line %d: type=%u\n", __FILE__, __LINE__, uri->type); } } diff --git a/erts/emulator/beam/erl_cpu_topology.c b/erts/emulator/beam/erl_cpu_topology.c index 8395f6ecc6..c263eebfcc 100644 --- a/erts/emulator/beam/erl_cpu_topology.c +++ b/erts/emulator/beam/erl_cpu_topology.c @@ -402,7 +402,7 @@ cpu_bind_order_sort(erts_cpu_topology_t *cpudata, break; default: cmp_func = NULL; - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "Bad cpu bind type: %d\n", (int) cpu_bind_order); break; @@ -1590,7 +1590,7 @@ get_cpu_topology_term(Process *c_p, int type) } break; default: - erl_exit(ERTS_ABORT_EXIT, "Bad cpu topology type: %d\n", type); + erts_exit(ERTS_ABORT_EXIT, "Bad cpu topology type: %d\n", type); break; } @@ -1967,7 +1967,7 @@ cpu_group_insert(erts_cpu_groups_map_t *map, ix = 0; } while (ix != start); - erl_exit(ERTS_ABORT_EXIT, "Reader groups map full\n"); + erts_exit(ERTS_ABORT_EXIT, "Reader groups map full\n"); } @@ -2290,7 +2290,7 @@ remove_cpu_groups(erts_cpu_groups_callback_t callback, void *arg) prev_cgm = cgm; } - erl_exit(ERTS_ABORT_EXIT, "Cpu groups not found\n"); + erts_exit(ERTS_ABORT_EXIT, "Cpu groups not found\n"); } static int @@ -2320,7 +2320,7 @@ cpu_groups_lookup(erts_cpu_groups_map_t *map, ix = 0; } while (ix != start); - erl_exit(ERTS_ABORT_EXIT, "Logical cpu id %d not found\n", logical); + erts_exit(ERTS_ABORT_EXIT, "Logical cpu id %d not found\n", logical); } static void diff --git a/erts/emulator/beam/erl_db.c b/erts/emulator/beam/erl_db.c index 55b8789e29..441dbdde4f 100644 --- a/erts/emulator/beam/erl_db.c +++ b/erts/emulator/beam/erl_db.c @@ -1295,7 +1295,7 @@ BIF_RETTYPE ets_rename_2(BIF_ALIST_2) goto badarg; if (!remove_named_tab(tb, 1)) - erl_exit(1,"Could not find named tab %s", tb->common.id); + erts_exit(ERTS_ERROR_EXIT,"Could not find named tab %s", tb->common.id); tb->common.id = tb->common.the_name = BIF_ARG_2; @@ -1580,7 +1580,7 @@ BIF_RETTYPE ets_new_2(BIF_ALIST_2) BIF_P->common.id, make_small(slot)), 0) != DB_ERROR_NONE) { - erl_exit(1,"Could not update ets metadata."); + erts_exit(ERTS_ERROR_EXIT,"Could not update ets metadata."); } db_meta_unlock(meta_pid_to_tab, LCK_WRITE_REC); @@ -2933,7 +2933,7 @@ void init_db(ErtsDbSpinCount db_spin_count) bits = erts_fit_in_bits_int32(db_max_tabs-1); if (bits > SMALL_BITS) { - erl_exit(1,"Max limit for ets tabled too high %u (max %u).", + erts_exit(ERTS_ERROR_EXIT,"Max limit for ets tabled too high %u (max %u).", db_max_tabs, ((Uint)1)<<SMALL_BITS); } meta_main_tab_slot_mask = (((Uint)1)<<bits) - 1; @@ -2994,7 +2994,7 @@ void init_db(ErtsDbSpinCount db_spin_count) db_init_lock(meta_pid_to_tab, "meta_pid_to_tab", "meta_pid_to_tab_FIX");*/ if (db_create_hash(NULL, meta_pid_to_tab) != DB_ERROR_NONE) { - erl_exit(1,"Unable to create ets metadata tables."); + erts_exit(ERTS_ERROR_EXIT,"Unable to create ets metadata tables."); } erts_smp_atomic_set_nob(&init_tb.common.memory_size, 0); @@ -3025,7 +3025,7 @@ void init_db(ErtsDbSpinCount db_spin_count) db_init_lock(meta_pid_to_fixed_tab, "meta_pid_to_fixed_tab", "meta_pid_to_fixed_tab_FIX");*/ if (db_create_hash(NULL, meta_pid_to_fixed_tab) != DB_ERROR_NONE) { - erl_exit(1,"Unable to create ets metadata tables."); + erts_exit(ERTS_ERROR_EXIT,"Unable to create ets metadata tables."); } /* Non visual BIF to trap to. */ @@ -3222,7 +3222,7 @@ retry: * yielding. */ #define ERTS_DB_INTERNAL_ERROR(LSTR) \ - erl_exit(ERTS_ABORT_EXIT, "%s:%d:erts_db_process_exiting(): " LSTR "\n", \ + erts_exit(ERTS_ABORT_EXIT, "%s:%d:erts_db_process_exiting(): " LSTR "\n", \ __FILE__, __LINE__) int @@ -3494,7 +3494,7 @@ static void fix_table_locked(Process* p, DbTable* tb) make_small(tb->common.slot)), 0) != DB_ERROR_NONE) { UnUseTmpHeap(3,p); - erl_exit(1,"Could not insert ets metadata in safe_fixtable."); + erts_exit(ERTS_ERROR_EXIT,"Could not insert ets metadata in safe_fixtable."); } UnUseTmpHeap(3,p); db_meta_unlock(meta_pid_to_fixed_tab, LCK_WRITE_REC); diff --git a/erts/emulator/beam/erl_db_hash.c b/erts/emulator/beam/erl_db_hash.c index cff65f244d..240b79fc60 100644 --- a/erts/emulator/beam/erl_db_hash.c +++ b/erts/emulator/beam/erl_db_hash.c @@ -3022,7 +3022,7 @@ void db_check_table_hash(DbTable *tbl) if ((list = BUCKET(tb,j)) != 0) { while (list != 0) { if (!is_tuple(make_tuple(list->dbterm.tpl))) { - erl_exit(1, "Bad term in slot %d of ets table", j); + erts_exit(ERTS_ERROR_EXIT, "Bad term in slot %d of ets table", j); } list = list->next; } diff --git a/erts/emulator/beam/erl_db_tree.c b/erts/emulator/beam/erl_db_tree.c index 311b69d114..0f642f0867 100644 --- a/erts/emulator/beam/erl_db_tree.c +++ b/erts/emulator/beam/erl_db_tree.c @@ -1204,7 +1204,7 @@ static int db_select_count_continue_tree(Process *p, tptr = tuple_val(continuation); if (arityval(*tptr) != 5) - erl_exit(1,"Internal error in ets:select_count/1"); + erts_exit(ERTS_ERROR_EXIT,"Internal error in ets:select_count/1"); lastkey = tptr[2]; end_condition = tptr[3]; diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c index 399be6058c..973be58420 100644 --- a/erts/emulator/beam/erl_db_util.c +++ b/erts/emulator/beam/erl_db_util.c @@ -1862,11 +1862,11 @@ restart: #ifdef DMC_DEBUG if (*heap_fence != FENCE_PATTERN) { - erl_exit(1, "Heap fence overwritten in db_prog_match after op " + erts_exit(ERTS_ERROR_EXIT, "Heap fence overwritten in db_prog_match after op " "0x%08x, overwritten with 0x%08x.", save_op, *heap_fence); } if (*stack_fence != FENCE_PATTERN) { - erl_exit(1, "Stack fence overwritten in db_prog_match after op " + erts_exit(ERTS_ERROR_EXIT, "Stack fence overwritten in db_prog_match after op " "0x%08x, overwritten with 0x%08x.", save_op, *stack_fence); } @@ -2495,7 +2495,7 @@ restart: case matchHalt: goto success; default: - erl_exit(1, "Internal error: unexpected opcode in match program."); + erts_exit(ERTS_ERROR_EXIT, "Internal error: unexpected opcode in match program."); } } fail: @@ -2512,11 +2512,11 @@ success: #ifdef DMC_DEBUG if (*heap_fence != FENCE_PATTERN) { - erl_exit(1, "Heap fence overwritten in db_prog_match after op " + erts_exit(ERTS_ERROR_EXIT, "Heap fence overwritten in db_prog_match after op " "0x%08x, overwritten with 0x%08x.", save_op, *heap_fence); } if (*stack_fence != FENCE_PATTERN) { - erl_exit(1, "Stack fence overwritten in db_prog_match after op " + erts_exit(ERTS_ERROR_EXIT, "Stack fence overwritten in db_prog_match after op " "0x%08x, overwritten with 0x%08x.", save_op, *stack_fence); } @@ -3448,7 +3448,7 @@ static DMCRet dmc_one_term(DMCContext *context, break; } default: - erl_exit(1, "db_match_compile: " + erts_exit(ERTS_ERROR_EXIT, "db_match_compile: " "Bad object on heap: 0x%bex\n", c); } return retOk; @@ -4679,7 +4679,7 @@ static DMCRet dmc_fun(DMCContext *context, DMC_PUSH(*text, matchCall3); break; default: - erl_exit(1,"ets:match() internal error, " + erts_exit(ERTS_ERROR_EXIT,"ets:match() internal error, " "guard with more than 3 arguments."); } DMC_PUSH(*text, (UWord) b->biff); @@ -4959,7 +4959,7 @@ static Uint my_size_object(Eterm t) tmp == am_const) { sum += size_object(tuple_val(t)[2]); } else { - erl_exit(1,"Internal error, sizing unrecognized object in " + erts_exit(ERTS_ERROR_EXIT,"Internal error, sizing unrecognized object in " "(d)ets:match compilation."); } break; @@ -5004,7 +5004,7 @@ static Eterm my_copy_struct(Eterm t, Eterm **hp, ErlOffHeap* off_heap) sz = size_object(b); ret = copy_struct(b,sz,hp,off_heap); } else { - erl_exit(1, "Trying to constant-copy non constant expression " + erts_exit(ERTS_ERROR_EXIT, "Trying to constant-copy non constant expression " "0x%bex in (d)ets:match compilation.", t); } } else { diff --git a/erts/emulator/beam/erl_debug.c b/erts/emulator/beam/erl_debug.c index 7b13cf2c83..2902c98864 100644 --- a/erts/emulator/beam/erl_debug.c +++ b/erts/emulator/beam/erl_debug.c @@ -255,14 +255,14 @@ void erts_check_stack(Process *p) Eterm *stack_end = p->htop; if (p->stop > stack_start) - erl_exit(1, + erts_exit(ERTS_ERROR_EXIT, "<%lu.%lu.%lu>: Stack underflow\n", internal_pid_channel_no(p->common.id), internal_pid_number(p->common.id), internal_pid_serial(p->common.id)); if (p->stop < stack_end) - erl_exit(1, + erts_exit(ERTS_ERROR_EXIT, "<%lu.%lu.%lu>: Stack overflow\n", internal_pid_channel_no(p->common.id), internal_pid_number(p->common.id), @@ -287,7 +287,7 @@ void erts_check_stack(Process *p) if (in_mbuf) continue; - erl_exit(1, + erts_exit(ERTS_ERROR_EXIT, "<%lu.%lu.%lu>: Wild stack pointer\n", internal_pid_channel_no(p->common.id), internal_pid_number(p->common.id), @@ -374,7 +374,7 @@ void erts_check_memory(Process *p, Eterm *start, Eterm *end) #ifdef DEBUG if (hval == DEBUG_BAD_WORD) { print_untagged_memory(start, end); - erl_exit(1, "Uninitialized HAlloc'ed memory found @ 0x%0*lx!\n", + erts_exit(ERTS_ERROR_EXIT, "Uninitialized HAlloc'ed memory found @ 0x%0*lx!\n", PTR_SIZE,(unsigned long)(pos - 1)); } #endif @@ -387,7 +387,7 @@ void erts_check_memory(Process *p, Eterm *start, Eterm *end) if (verify_eterm(p,hval)) continue; - erl_exit(1, "Wild pointer found @ 0x%0*lx!\n", + erts_exit(ERTS_ERROR_EXIT, "Wild pointer found @ 0x%0*lx!\n", PTR_SIZE,(unsigned long)(pos - 1)); } } @@ -397,11 +397,11 @@ void verify_process(Process *p) #define VERIFY_AREA(name,ptr,sz) { \ int n = (sz); \ while (n--) if(!verify_eterm(p,*(ptr+n))) \ - erl_exit(1,"Wild pointer found in " name " of %T!\n",p->common.id); } + erts_exit(ERTS_ERROR_EXIT,"Wild pointer found in " name " of %T!\n",p->common.id); } #define VERIFY_ETERM(name,eterm) { \ if(!verify_eterm(p,eterm)) \ - erl_exit(1,"Wild pointer found in " name " of %T!\n",p->common.id); } + erts_exit(ERTS_ERROR_EXIT,"Wild pointer found in " name " of %T!\n",p->common.id); } ErtsMessage* mp = p->msg.first; diff --git a/erts/emulator/beam/erl_drv_thread.c b/erts/emulator/beam/erl_drv_thread.c index e0404eb5c9..184f8e8931 100644 --- a/erts/emulator/beam/erl_drv_thread.c +++ b/erts/emulator/beam/erl_drv_thread.c @@ -43,7 +43,7 @@ fatal_error(int err, char *func) else estr = "Unknown error"; } - erl_exit(ERTS_ABORT_EXIT, "Fatal error in %s: %s [%d]\n", func, estr, err); + erts_exit(ERTS_ABORT_EXIT, "Fatal error in %s: %s [%d]\n", func, estr, err); } #define ERL_DRV_TSD_KEYS_INC 10 diff --git a/erts/emulator/beam/erl_fun.c b/erts/emulator/beam/erl_fun.c index cff476694c..ed555aa92f 100644 --- a/erts/emulator/beam/erl_fun.c +++ b/erts/emulator/beam/erl_fun.c @@ -188,7 +188,7 @@ erts_erase_fun_entry(ErlFunEntry* fe) #endif { if (fe->address != unloaded_fun) - erl_exit(1, + erts_exit(ERTS_ERROR_EXIT, "Internal error: " "Invalid reference count found on #Fun<%T.%d.%d>: " " About to erase fun still referred by code.\n", diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c index 21b03ae8bd..0d125c5598 100644 --- a/erts/emulator/beam/erl_gc.c +++ b/erts/emulator/beam/erl_gc.c @@ -70,7 +70,7 @@ erts_fprintf(stderr, "stop=%p\n", (p)->stop); \ erts_fprintf(stderr, "htop=%p\n", (p)->htop); \ erts_fprintf(stderr, "heap=%p\n", (p)->heap); \ - erl_exit(ERTS_ABORT_EXIT, "%s, line %d: %T: Overrun stack and heap\n", \ + erts_exit(ERTS_ABORT_EXIT, "%s, line %d: %T: Overrun stack and heap\n", \ __FILE__,__LINE__,(P)->common.id); \ } @@ -289,7 +289,7 @@ erts_next_heap_size(Uint size, Uint offset) low = mid + 1; } } - erl_exit(1, "no next heap size found: %beu, offset %beu\n", size, offset); + erts_exit(ERTS_ERROR_EXIT, "no next heap size found: %beu, offset %beu\n", size, offset); } return 0; } @@ -3067,7 +3067,7 @@ within(Eterm *ptr, Process *p) #define ERTS_CHK_OFFHEAP_ASSERT(EXP) \ do { \ if (!(EXP)) \ - erl_exit(ERTS_ABORT_EXIT, \ + erts_exit(ERTS_ABORT_EXIT, \ "%s:%d: Assertion failed: %s\n", \ __FILE__, __LINE__, #EXP); \ } while (0) diff --git a/erts/emulator/beam/erl_goodfit_alloc.c b/erts/emulator/beam/erl_goodfit_alloc.c index f89f8723d9..9b4aad9d91 100644 --- a/erts/emulator/beam/erl_goodfit_alloc.c +++ b/erts/emulator/beam/erl_goodfit_alloc.c @@ -571,8 +571,8 @@ info_options(Allctr_t *allctr, if (hpp || szp) { if (!atoms_initialized) - erl_exit(1, "%s:%d: Internal error: Atoms not initialized", - __FILE__, __LINE__);; + erts_exit(ERTS_ERROR_EXIT, "%s:%d: Internal error: Atoms not initialized", + __FILE__, __LINE__); res = NIL; add_2tup(hpp, szp, &res, am.as, am.gf); diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c index 67089df863..86c4eeb484 100644 --- a/erts/emulator/beam/erl_init.c +++ b/erts/emulator/beam/erl_init.c @@ -264,7 +264,7 @@ this_rel_num(void) i++; this_rel = atoi(&this_rel_str[i]); if (this_rel < 1) - erl_exit(-1, "Unexpected ERLANG_OTP_RELEASE format\n"); + erts_exit(1, "Unexpected ERLANG_OTP_RELEASE format\n"); } return this_rel; } @@ -412,7 +412,7 @@ erl_first_process_otp(char* modname, void* code, unsigned size, int argc, char** start_mod = erts_atom_put((byte *) modname, sys_strlen(modname), ERTS_ATOM_ENC_LATIN1, 1); if (erts_find_function(start_mod, am_start, 2, erts_active_code_ix()) == NULL) { - erl_exit(5, "No function %s:start/2\n", modname); + erts_exit(ERTS_ERROR_EXIT, "No function %s:start/2\n", modname); } /* @@ -451,7 +451,7 @@ erl_system_process_otp(Eterm parent_pid, char* modname) 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) { - erl_exit(5, "No function %s:start/0\n", modname); + erts_exit(ERTS_ERROR_EXIT, "No function %s:start/0\n", modname); } parent = erts_pid2proc(NULL, 0, parent_pid, ERTS_PROC_LOCK_MAIN); @@ -532,12 +532,12 @@ load_preloaded(void) length = preload_p[i].size; module_name = erts_atom_put((byte *) name, sys_strlen(name), ERTS_ATOM_ENC_LATIN1, 1); if ((code = sys_preload_begin(&preload_p[i])) == 0) - erl_exit(1, "Failed to find preloaded code for module %s\n", + erts_exit(ERTS_ERROR_EXIT, "Failed to find preloaded code for module %s\n", name); res = erts_preload_module(NULL, 0, NIL, &module_name, code, length); sys_preload_end(&preload_p[i]); if (res != NIL) - erl_exit(1,"Failed loading preloaded module %s (%T)\n", + erts_exit(ERTS_ERROR_EXIT,"Failed loading preloaded module %s (%T)\n", name, res); i++; } @@ -670,7 +670,7 @@ void erts_usage(void) erts_fprintf(stderr, "Note that if the emulator is started with erlexec (typically\n"); erts_fprintf(stderr, "from the erl script), these flags should be specified with +.\n"); erts_fprintf(stderr, "\n\n"); - erl_exit(-1, ""); + erts_exit(1, ""); } #ifdef USE_THREADS @@ -1472,7 +1472,7 @@ erl_start(int argc, char **argv) } erts_fprintf(stderr, "(" EMULATOR ") emulator version " ERLANG_VERSION "\n"); - erl_exit(0, ""); + erts_exit(0, ""); } break; @@ -2304,23 +2304,17 @@ system_cleanup(int flush_async) } static __decl_noreturn void __noreturn -erl_exit_vv(int n, int flush_async, char *fmt, va_list args1, va_list args2) +erts_exit_vv(int n, int flush_async, char *fmt, va_list args1, va_list args2) { - unsigned int an; - system_cleanup(flush_async); save_statistics(); - if (n < 0) - an = -(unsigned int)n; - else - an = n; if (erts_mtrace_enabled) - erts_mtrace_exit((Uint32) an); + erts_mtrace_exit((Uint32) n); /* Produce an Erlang core dump if error */ - if (((n > 0 && erts_no_crash_dump == 0) || n == ERTS_DUMP_EXIT) + if (((n == ERTS_ERROR_EXIT && erts_no_crash_dump == 0) || n == ERTS_DUMP_EXIT) && erts_initialized) { erl_crash_dump_v((char*) NULL, 0, fmt, args1); } @@ -2333,29 +2327,29 @@ erl_exit_vv(int n, int flush_async, char *fmt, va_list args1, va_list args2) exit(0); else if (n == ERTS_DUMP_EXIT) ERTS_EXIT_AFTER_DUMP(1); - else if (n > 0 || n == ERTS_ABORT_EXIT) + else if (n == ERTS_ERROR_EXIT || n == ERTS_ABORT_EXIT) abort(); - exit(an); + exit(n); } /* Exit without flushing async threads */ -__decl_noreturn void __noreturn erl_exit(int n, char *fmt, ...) +__decl_noreturn void __noreturn erts_exit(int n, char *fmt, ...) { va_list args1, args2; va_start(args1, fmt); va_start(args2, fmt); - erl_exit_vv(n, 0, fmt, args1, args2); + erts_exit_vv(n, 0, fmt, args1, args2); va_end(args2); va_end(args1); } /* Exit after flushing async threads */ -__decl_noreturn void __noreturn erl_exit_flush_async(int n, char *fmt, ...) +__decl_noreturn void __noreturn erts_flush_async_exit(int n, char *fmt, ...) { va_list args1, args2; va_start(args1, fmt); va_start(args2, fmt); - erl_exit_vv(n, 1, fmt, args1, args2); + erts_exit_vv(n, 1, fmt, args1, args2); va_end(args2); va_end(args1); } diff --git a/erts/emulator/beam/erl_map.c b/erts/emulator/beam/erl_map.c index d0ffb11e79..4b6931f848 100644 --- a/erts/emulator/beam/erl_map.c +++ b/erts/emulator/beam/erl_map.c @@ -1270,7 +1270,7 @@ recurse: break; } default: - erl_exit(ERTS_ABORT_EXIT, "bad header %ld\r\n", hdrA); + erts_exit(ERTS_ABORT_EXIT, "bad header %ld\r\n", hdrA); } } @@ -1297,7 +1297,7 @@ recurse: break; } default: - erl_exit(ERTS_ABORT_EXIT, "bad header %ld\r\n", hdrB); + erts_exit(ERTS_ABORT_EXIT, "bad header %ld\r\n", hdrB); } } } @@ -1387,7 +1387,7 @@ resume_from_trap: res = make_boxed(nhp); break; default: - erl_exit(ERTS_ABORT_EXIT, "strange mix %d\r\n", sp->mix); + erts_exit(ERTS_ABORT_EXIT, "strange mix %d\r\n", sp->mix); } } @@ -1882,7 +1882,7 @@ void hashmap_iterator_init(ErtsWStack* s, Eterm node, int reverse) { sz = hashmap_bitcount(MAP_HEADER_VAL(hdr)); break; default: - erl_exit(ERTS_ABORT_EXIT, "bad header"); + erts_exit(ERTS_ABORT_EXIT, "bad header"); } WSTACK_PUSH3((*s), (UWord)THE_NON_VALUE, /* end marker */ @@ -1919,7 +1919,7 @@ Eterm* hashmap_iterator_next(ErtsWStack* s) { ASSERT(sz < 17); break; default: - erl_exit(ERTS_ABORT_EXIT, "bad header"); + erts_exit(ERTS_ABORT_EXIT, "bad header"); } idx++; @@ -1969,7 +1969,7 @@ Eterm* hashmap_iterator_prev(ErtsWStack* s) { ASSERT(sz < 17); break; default: - erl_exit(1, "bad header"); + erts_exit(ERTS_ERROR_EXIT, "bad header"); } if (idx > sz) @@ -2153,12 +2153,12 @@ int erts_hashmap_insert_down(Uint32 hx, Eterm key, Eterm node, Uint *sz, size += HAMT_HEAD_BITMAP_SZ(n+1); goto unroll; default: - erl_exit(1, "bad header tag %ld\r\n", hdr & _HEADER_MAP_SUBTAG_MASK); + erts_exit(ERTS_ERROR_EXIT, "bad header tag %ld\r\n", hdr & _HEADER_MAP_SUBTAG_MASK); break; } break; default: - erl_exit(1, "bad primary tag %p\r\n", node); + erts_exit(ERTS_ERROR_EXIT, "bad primary tag %p\r\n", node); break; } } @@ -2273,12 +2273,12 @@ Eterm erts_hashmap_insert_up(Eterm *hp, Eterm key, Eterm value, res = make_hashmap(nhp); break; default: - erl_exit(1, "bad header tag %x\r\n", hdr & _HEADER_MAP_SUBTAG_MASK); + erts_exit(ERTS_ERROR_EXIT, "bad header tag %x\r\n", hdr & _HEADER_MAP_SUBTAG_MASK); break; } break; default: - erl_exit(1, "bad primary tag %x\r\n", primary_tag(node)); + erts_exit(ERTS_ERROR_EXIT, "bad primary tag %x\r\n", primary_tag(node)); break; } @@ -2396,12 +2396,12 @@ static Eterm hashmap_delete(Process *p, Uint32 hx, Eterm key, Eterm map) { /* not occupied */ goto not_found; default: - erl_exit(1, "bad header tag %ld\r\n", hdr & _HEADER_MAP_SUBTAG_MASK); + erts_exit(ERTS_ERROR_EXIT, "bad header tag %ld\r\n", hdr & _HEADER_MAP_SUBTAG_MASK); break; } break; default: - erl_exit(1, "bad primary tag %p\r\n", node); + erts_exit(ERTS_ERROR_EXIT, "bad primary tag %p\r\n", node); break; } } @@ -2578,7 +2578,7 @@ unroll: res = make_hashmap(nhp); break; default: - erl_exit(1, "bad header tag %x\r\n", hdr & _HEADER_MAP_SUBTAG_MASK); + erts_exit(ERTS_ERROR_EXIT, "bad header tag %x\r\n", hdr & _HEADER_MAP_SUBTAG_MASK); break; } } while(!ESTACK_ISEMPTY(stack)); @@ -2728,7 +2728,7 @@ BIF_RETTYPE erts_internal_term_type_1(BIF_ALIST_1) { case MAP_HEADER_TAG_HAMT_NODE_BITMAP : BIF_RET(ERTS_MAKE_AM("hashmap_node")); default: - erl_exit(ERTS_ABORT_EXIT, "term_type: bad map header type %d\n", MAP_HEADER_TYPE(hdr)); + 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")); @@ -2752,7 +2752,7 @@ BIF_RETTYPE erts_internal_term_type_1(BIF_ALIST_1) { case FLOAT_SUBTAG: BIF_RET(ERTS_MAKE_AM("hfloat")); default: - erl_exit(ERTS_ABORT_EXIT, "term_type: Invalid tag (0x%X)\n", hdr); + erts_exit(ERTS_ABORT_EXIT, "term_type: Invalid tag (0x%X)\n", hdr); } } case TAG_PRIMARY_IMMED1: @@ -2772,13 +2772,13 @@ BIF_RETTYPE erts_internal_term_type_1(BIF_ALIST_1) { case _TAG_IMMED2_NIL: BIF_RET(ERTS_MAKE_AM("nil")); default: - erl_exit(ERTS_ABORT_EXIT, "term_type: Invalid tag (0x%X)\n", obj); + erts_exit(ERTS_ABORT_EXIT, "term_type: Invalid tag (0x%X)\n", obj); } default: - erl_exit(ERTS_ABORT_EXIT, "term_type: Invalid tag (0x%X)\n", obj); + erts_exit(ERTS_ABORT_EXIT, "term_type: Invalid tag (0x%X)\n", obj); } default: - erl_exit(ERTS_ABORT_EXIT, "term_type: Invalid tag (0x%X)\n", obj); + erts_exit(ERTS_ABORT_EXIT, "term_type: Invalid tag (0x%X)\n", obj); } } @@ -2811,7 +2811,7 @@ BIF_RETTYPE erts_internal_map_hashmap_children_1(BIF_ALIST_1) { ptr += 2; break; default: - erl_exit(1, "bad header\r\n"); + erts_exit(ERTS_ERROR_EXIT, "bad header\r\n"); break; } ASSERT(sz < 17); @@ -2889,7 +2889,7 @@ static Eterm hashmap_info(Process *p, Eterm node) { } break; default: - erl_exit(1, "bad header\r\n"); + erts_exit(ERTS_ERROR_EXIT, "bad header\r\n"); break; } } diff --git a/erts/emulator/beam/erl_monitors.c b/erts/emulator/beam/erl_monitors.c index 7dfa01c8ac..bd899fa2f9 100644 --- a/erts/emulator/beam/erl_monitors.c +++ b/erts/emulator/beam/erl_monitors.c @@ -356,7 +356,7 @@ void erts_add_monitor(ErtsMonitor **root, Uint type, Eterm ref, Eterm pid, tstack[tpos++] = this; this = &((*this)->right); } else { /* Equal key is an error for monitors */ - erl_exit(1,"Insertion of already present monitor!"); + erts_exit(ERTS_ERROR_EXIT,"Insertion of already present monitor!"); break; } } diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index 2204231748..8580bc2689 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -331,7 +331,7 @@ int enif_send(ErlNifEnv* env, const ErlNifPid* to_pid, #ifdef ERTS_SMP c_p = NULL; #else - erl_exit(ERTS_ABORT_EXIT,"enif_send: env==NULL on non-SMP VM"); + erts_exit(ERTS_ABORT_EXIT,"enif_send: env==NULL on non-SMP VM"); #endif } diff --git a/erts/emulator/beam/erl_node_tables.c b/erts/emulator/beam/erl_node_tables.c index 13f14adbab..8617f42d7b 100644 --- a/erts/emulator/beam/erl_node_tables.c +++ b/erts/emulator/beam/erl_node_tables.c @@ -1053,7 +1053,7 @@ insert_dist_entry(DistEntry *dist, int type, Eterm id, Uint creation) } if(!rdp) - erl_exit(1, + erts_exit(ERTS_ERROR_EXIT, "Reference to non-existing distribution table entry found!\n"); insert_dist_referrer(rdp, type, id, creation); @@ -1114,7 +1114,7 @@ insert_node(ErlNode *node, int type, Eterm id) } if (!rnp) - erl_exit(1, "Reference to non-existing node table entry found!\n"); + erts_exit(ERTS_ERROR_EXIT, "Reference to non-existing node table entry found!\n"); insert_node_referrer(rnp, type, id); } diff --git a/erts/emulator/beam/erl_port_task.c b/erts/emulator/beam/erl_port_task.c index 197b328fe2..e85395e062 100644 --- a/erts/emulator/beam/erl_port_task.c +++ b/erts/emulator/beam/erl_port_task.c @@ -1786,7 +1786,7 @@ erts_port_task_execute(ErtsRunQueue *runq, Port **curr_port_pp) reds = erts_dist_command(pp, CONTEXT_REDS - pp->reds); break; default: - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "Invalid port task type: %d\n", (int) ptp->type); break; @@ -2051,7 +2051,7 @@ begin_port_cleanup(Port *pp, ErtsPortTask **execqp, int *processing_busy_q_p) break; } default: - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "Invalid port task type: %d\n", (int) ptp->type); } diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index e4584e7cc2..a706ebf595 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -153,10 +153,8 @@ 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); -#ifdef ERTS_DIRTY_SCHEDULERS -Uint ERTS_WRITE_UNLIKELY(erts_no_dirty_cpu_schedulers); -Uint ERTS_WRITE_UNLIKELY(erts_no_dirty_io_schedulers); -#endif +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; @@ -188,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; @@ -426,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; } \ @@ -505,7 +597,7 @@ dbg_chk_aux_work_val(erts_aint32_t value) valid |= ERTS_SSI_AUX_WORK_DEBUG_WAIT_COMPLETED; if (~valid & value) - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "Invalid aux_work value found: 0x%x\n", ~valid & value); } @@ -1188,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) { @@ -1195,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); @@ -1272,7 +1379,7 @@ erts_sched_finish_poke(ErtsSchedulerSleepInfo *ssi, erts_aint32_t flags) case 0: break; default: - erl_exit(ERTS_ABORT_EXIT, "%s:%d: Internal error\n", + erts_exit(ERTS_ABORT_EXIT, "%s:%d: Internal error\n", __FILE__, __LINE__); break; } @@ -2230,7 +2337,7 @@ handle_reap_ports(ErtsAuxWorkData *awdp, erts_aint32_t aux_work, int waiting) erts_port_release(prt); } if (erts_smp_atomic32_dec_read_nob(&erts_halt_progress) == 0) { - erl_exit_flush_async(erts_halt_code, ""); + erts_flush_async_exit(erts_halt_code, ""); } } return aux_work & ~ERTS_SSI_AUX_WORK_REAP_PORTS; @@ -2632,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) { @@ -3025,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); @@ -3333,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; @@ -3747,7 +3850,7 @@ immigrate(ErtsRunQueue *c_rq, ErtsMigrationPath *mp) prio = ERTS_PORT_PRIO_LEVEL; break; default: - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "%s:%d:%s(): Invalid immigrate queue mask", __FILE__, __LINE__, __func__); prio = 0; @@ -3771,7 +3874,7 @@ immigrate(ErtsRunQueue *c_rq, ErtsMigrationPath *mp) rq = erts_port_runq(prt); if (rq) { if (rq != c_rq) - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "%s:%d:%s(): Internal error", __FILE__, __LINE__, __func__); erts_enqueue_port(c_rq, prt); @@ -3836,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); @@ -3962,7 +4074,7 @@ evacuate_run_queue(ErtsRunQueue *rq, prt_rq = erts_port_runq(prt); if (prt_rq) { if (prt_rq != to_rq) - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "%s:%d:%s() internal error\n", __FILE__, __LINE__, __func__); erts_enqueue_port(to_rq, prt); @@ -4207,7 +4319,7 @@ no_procs: return 0; else { if (prt_rq != rq) - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "%s:%d:%s() internal error\n", __FILE__, __LINE__, __func__); *rq_lockedp = 1; @@ -5632,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(); @@ -5869,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"); @@ -5902,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(); @@ -5942,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); @@ -6705,19 +6833,6 @@ resume_process(Process *p, ErtsProcLocks locks) add2runq(enqueue, enq_prio, p, state, NULL); } -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 -} - #ifdef ERTS_SMP static void @@ -6820,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. @@ -6863,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) @@ -6897,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 (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 (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 (!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; @@ -7216,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); @@ -7227,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); @@ -7284,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 @@ -7315,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; } @@ -7323,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)); @@ -7938,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); @@ -8031,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; @@ -8176,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( @@ -8218,7 +8074,7 @@ sched_thread_func(void *vesdp) process_main(); /* No schedulers should *ever* terminate */ - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "Scheduler thread number %beu terminated\n", no); return NULL; @@ -8263,27 +8119,9 @@ 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 */ - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "Dirty CPU scheduler thread number %beu terminated\n", no); return NULL; @@ -8326,27 +8164,9 @@ 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 */ - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "Dirty I/O scheduler thread number %beu terminated\n", no); return NULL; @@ -8376,12 +8196,12 @@ erts_start_schedulers(void) erts_snprintf(opts.name, 16, "runq_supervisor"); erts_atomic_init_nob(&runq_supervisor_sleeping, 0); if (0 != ethr_event_init(&runq_supervision_event)) - erl_exit(1, "Failed to create run-queue supervision event\n"); + erts_exit(ERTS_ERROR_EXIT, "Failed to create run-queue supervision event\n"); if (0 != ethr_thr_create(&runq_supervisor_tid, runq_supervisor, NULL, &opts)) - erl_exit(1, "Failed to create run-queue supervision thread\n"); + erts_exit(ERTS_ERROR_EXIT, "Failed to create run-queue supervision thread\n"); } #endif @@ -8419,14 +8239,14 @@ erts_start_schedulers(void) erts_snprintf(opts.name, 16, "%d_dirty_cpu_scheduler", ix + 1); res = ethr_thr_create(&esdp->tid,sched_dirty_cpu_thread_func,(void*)esdp,&opts); if (res != 0) - erl_exit(1, "Failed to create dirty cpu scheduler thread %d\n", ix); + erts_exit(ERTS_ERROR_EXIT, "Failed to create dirty cpu scheduler thread %d\n", ix); } for (ix = 0; ix < erts_no_dirty_io_schedulers; ix++) { ErtsSchedulerData *esdp = ERTS_DIRTY_IO_SCHEDULER_IX(ix); erts_snprintf(opts.name, 16, "%d_dirty_io_scheduler", ix + 1); res = ethr_thr_create(&esdp->tid,sched_dirty_io_thread_func,(void*)esdp,&opts); if (res != 0) - erl_exit(1, "Failed to create dirty io scheduler thread %d\n", ix); + erts_exit(ERTS_ERROR_EXIT, "Failed to create dirty io scheduler thread %d\n", ix); } } #endif @@ -8438,10 +8258,10 @@ erts_start_schedulers(void) res = ethr_thr_create(&aux_tid, aux_thread, NULL, &opts); if (res != 0) - erl_exit(1, "Failed to create aux thread\n"); + erts_exit(ERTS_ERROR_EXIT, "Failed to create aux thread\n"); if (actual < 1) - erl_exit(1, + erts_exit(ERTS_ERROR_EXIT, "Failed to create any scheduler-threads: %s (%d)\n", erl_errno_id(res), res); @@ -9616,11 +9436,11 @@ Process *schedule(Process *p, int calls) 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); - } + 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); @@ -12392,7 +12212,7 @@ static void doit_exit_link(ErtsLink *lnk, void *vpcontext) break; default: - erl_exit(1, "bad type in link list\n"); + erts_exit(ERTS_ERROR_EXIT, "bad type in link list\n"); break; } erts_destroy_link(lnk); @@ -12433,7 +12253,7 @@ erts_do_exit_process(Process* p, Eterm reason) #endif if (p->static_flags & ERTS_STC_FLG_SYSTEM_PROC) - erl_exit(ERTS_DUMP_EXIT, "System process %T terminated: %T\n", + erts_exit(ERTS_DUMP_EXIT, "System process %T terminated: %T\n", p->common.id, reason); #ifdef ERTS_SMP @@ -12537,21 +12357,46 @@ 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; break; case ERTS_SCHDLR_SSPND_EINVAL: default: - erl_exit(ERTS_ABORT_EXIT, "%s:%d: Internal error: %d\n", + erts_exit(ERTS_ABORT_EXIT, "%s:%d: Internal error: %d\n", __FILE__, __LINE__, (int) ssr); } } @@ -13048,10 +12893,10 @@ erts_print_scheduler_info(int to, void *to_arg, ErtsSchedulerData *esdp) { * The same global atomic is used as refcount. * * A BIF that calls this should make sure to schedule out to never come back: - * erl_halt((int)(- code)); + * erts_halt(code); * ERTS_BIF_YIELD1(bif_export[BIF_erlang_halt_1], BIF_P, NIL); */ -void erl_halt(int code) +void erts_halt(int code) { if (-1 == erts_smp_atomic32_cmpxchg_acqb(&erts_halt_progress, erts_no_schedulers, diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h index 0c7ad74614..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, @@ -1339,6 +1339,8 @@ extern int erts_system_profile_ts_type; #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 @@ -1533,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 *); @@ -1718,28 +1721,21 @@ 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); @@ -2462,6 +2458,6 @@ erts_sched_poke(ErtsSchedulerSleepInfo *ssi) #endif -void erl_halt(int code); +void erts_halt(int code); extern erts_smp_atomic32_t erts_halt_progress; extern int erts_halt_code; diff --git a/erts/emulator/beam/erl_process_dict.c b/erts/emulator/beam/erl_process_dict.c index 36d16f7f42..487b944fc0 100644 --- a/erts/emulator/beam/erl_process_dict.c +++ b/erts/emulator/beam/erl_process_dict.c @@ -392,7 +392,7 @@ static void pd_hash_erase(Process *p, Eterm id, Eterm *ret) "display term found in line %d:\n" "%T\n", p->common.id, __LINE__, old); #endif - erl_exit(1, "Damaged process dictionary found during erase/1."); + erts_exit(ERTS_ERROR_EXIT, "Damaged process dictionary found during erase/1."); } if ((range = HASH_RANGE(p->dictionary)) > INITIAL_SIZE && range / 2 > (p->dictionary->numElements)) { @@ -452,7 +452,7 @@ Eterm pd_hash_get_with_hval(Process *p, Eterm bucket, Eterm id) "display term found in line %d:\n" "%T\n", p->common.id, __LINE__, bucket); #endif - erl_exit(1, "Damaged process dictionary found during get/1."); + erts_exit(ERTS_ERROR_EXIT, "Damaged process dictionary found during get/1."); } return am_undefined; } @@ -707,7 +707,7 @@ static Eterm pd_hash_put(Process *p, Eterm id, Eterm value) "%T\n", p->common.id, __LINE__, old); #endif - erl_exit(1, "Damaged process dictionary found during put/2."); + erts_exit(ERTS_ERROR_EXIT, "Damaged process dictionary found during put/2."); } if (HASH_RANGE(p->dictionary) <= p->dictionary->numElements) { grow(p); @@ -1061,7 +1061,7 @@ static void pd_check(ProcDict *pd) } continue; } else { - erl_exit(1, + erts_exit(ERTS_ERROR_EXIT, "Found tag 0x%08x in process dictionary at position %d", (unsigned long) t, (int) i); } diff --git a/erts/emulator/beam/erl_ptab.c b/erts/emulator/beam/erl_ptab.c index f7997df051..9ed175fe01 100644 --- a/erts/emulator/beam/erl_ptab.c +++ b/erts/emulator/beam/erl_ptab.c @@ -1255,7 +1255,7 @@ ptab_list_bif_engine(Process *c_p, Eterm *res_accp, Binary *mbp) return 1; default: - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "%s:%d:ptab_list_bif_engine(): Invalid state: %d\n", __FILE__, __LINE__, (int) ptlbdp->state); } diff --git a/erts/emulator/beam/erl_term.c b/erts/emulator/beam/erl_term.c index e31d3a951d..d2343912b4 100644 --- a/erts/emulator/beam/erl_term.c +++ b/erts/emulator/beam/erl_term.c @@ -72,7 +72,7 @@ et_abort(const char *expr, const char *file, unsigned line) * Prevent infinite loop. */ have_been_called = 1; - erl_exit(1, "TYPE ASSERTION FAILED, file %s, line %u: %s\n", file, line, expr); + erts_exit(ERTS_ERROR_EXIT, "TYPE ASSERTION FAILED, file %s, line %u: %s\n", file, line, expr); } #else erts_fprintf(stderr, "TYPE ASSERTION FAILED, file %s, line %u: %s\n", file, line, expr); diff --git a/erts/emulator/beam/erl_thr_progress.c b/erts/emulator/beam/erl_thr_progress.c index 7148b756e7..7b06fd840f 100644 --- a/erts/emulator/beam/erl_thr_progress.c +++ b/erts/emulator/beam/erl_thr_progress.c @@ -502,7 +502,7 @@ erts_thr_progress_register_unmanaged_thread(ErtsThrPrgrCallbacks *callbacks) if (tpd) { if (!tpd->is_temporary) - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "%s:%d:%s(): Double register of thread\n", __FILE__, __LINE__, __func__); is_blocking = tpd->is_blocking; @@ -524,7 +524,7 @@ erts_thr_progress_register_unmanaged_thread(ErtsThrPrgrCallbacks *callbacks) #endif ASSERT(tpd->id >= 0); if (tpd->id >= intrnl->unmanaged.no) - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "%s:%d:%s(): Too many unmanaged registered threads\n", __FILE__, __LINE__, __func__); @@ -547,7 +547,7 @@ erts_thr_progress_register_managed_thread(ErtsSchedulerData *esdp, if (tpd) { if (!tpd->is_temporary) - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "%s:%d:%s(): Double register of thread\n", __FILE__, __LINE__, __func__); is_blocking = tpd->is_blocking; @@ -568,7 +568,7 @@ erts_thr_progress_register_managed_thread(ErtsSchedulerData *esdp, tpd->id = erts_atomic32_inc_read_nob(&intrnl->misc.data.managed_id); ASSERT(tpd->id >= 0); if (tpd->id >= intrnl->managed.no) - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "%s:%d:%s(): Too many managed registered threads\n", __FILE__, __LINE__, __func__); @@ -1033,7 +1033,7 @@ has_reached_wakeup(ErtsThrPrgrVal wakeup) limit += 1; if (!erts_thr_progress_has_passed__(limit, wakeup)) - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "Invalid wakeup request value found:" " current=%b64u, wakeup=%b64u, limit=%b64u", current, wakeup, limit); @@ -1102,7 +1102,7 @@ request_wakeup_managed(ErtsThrPrgrData *tpd, ErtsThrPrgrVal value) ix = erts_atomic32_inc_read_nob(&mwd->len) - 1; #if ERTS_THR_PRGR_DBG_CHK_WAKEUP_REQUEST_VALUE if (ix >= intrnl->managed.no) - erl_exit(ERTS_ABORT_EXIT, "Internal error: Too many wakeup requests\n"); + erts_exit(ERTS_ABORT_EXIT, "Internal error: Too many wakeup requests\n"); #endif mwd->id[ix] = tpd->id; diff --git a/erts/emulator/beam/erl_thr_queue.c b/erts/emulator/beam/erl_thr_queue.c index 3a91ca9dbe..7ff456b915 100644 --- a/erts/emulator/beam/erl_thr_queue.c +++ b/erts/emulator/beam/erl_thr_queue.c @@ -224,7 +224,7 @@ ErtsThrQCleanState_t erts_thr_q_destroy(ErtsThrQ_t *q) { if (!q->q.blk) - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "Trying to destroy not created thread queue\n"); return erts_thr_q_finalize(q); } @@ -589,7 +589,7 @@ enqueue(ErtsThrQ_t *q, void *data, ErtsThrQElement_t *this) #if ERTS_THR_Q_DBG_CHK_DATA if (!data) - erl_exit(ERTS_ABORT_EXIT, "Missing data in enqueue\n"); + erts_exit(ERTS_ABORT_EXIT, "Missing data in enqueue\n"); #endif ASSERT(!q->q.finalizing); @@ -771,7 +771,7 @@ erts_thr_q_dequeue(ErtsThrQ_t *q) #if ERTS_THR_Q_DBG_CHK_DATA head->data.ptr = NULL; if (!res) - erl_exit(ERTS_ABORT_EXIT, "Missing data in dequeue\n"); + erts_exit(ERTS_ABORT_EXIT, "Missing data in dequeue\n"); #endif clean(q, (q->head.deq_fini.automatic diff --git a/erts/emulator/beam/erl_time_sup.c b/erts/emulator/beam/erl_time_sup.c index 98159fdf72..f3f528eaf6 100644 --- a/erts/emulator/beam/erl_time_sup.c +++ b/erts/emulator/beam/erl_time_sup.c @@ -289,7 +289,7 @@ read_corrected_time(int os_drift_corrected) ci = time_sup.inf.c.parmon.cdata.insts.curr; else { if (os_mtime < time_sup.inf.c.parmon.cdata.insts.prev.os_mtime) - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "OS monotonic time stepped backwards\n"); ci = time_sup.inf.c.parmon.cdata.insts.prev; } @@ -381,7 +381,7 @@ check_time_correction(void *vesdp) erts_smp_rwmtx_runlock(&time_sup.inf.c.parmon.rwmtx); if (os_mtime < ci.os_mtime) - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "OS monotonic time stepped backwards\n"); erl_mtime = calc_corrected_erl_mtime(os_mtime, &ci, &mdiff, @@ -798,7 +798,7 @@ finalize_corrected_time_offset(ErtsSystemTime *stimep) erts_smp_rwmtx_runlock(&time_sup.inf.c.parmon.rwmtx); if (os_mtime < ci.os_mtime) - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "OS monotonic time stepped backwards\n"); return calc_corrected_erl_mtime(os_mtime, &ci, NULL, diff --git a/erts/emulator/beam/erl_trace.c b/erts/emulator/beam/erl_trace.c index 25393369a7..41876b8c62 100644 --- a/erts/emulator/beam/erl_trace.c +++ b/erts/emulator/beam/erl_trace.c @@ -661,7 +661,7 @@ WRITE_SYS_MSG_TO_PORT(Eterm unused_to, erts_encode_ext(message, &ptr); if (!(ptr <= buffer+size)) { - erl_exit(1, "Internal error in do_send_to_port: %d\n", ptr-buffer); + erts_exit(ERTS_ERROR_EXIT, "Internal error in do_send_to_port: %d\n", ptr-buffer); } #ifndef ERTS_SMP @@ -1286,7 +1286,7 @@ seq_trace_output_generic(Eterm token, Eterm msg, Uint type, case SEQ_TRACE_PRINT: type_atom = am_print; break; case SEQ_TRACE_RECEIVE: type_atom = am_receive; break; default: - erl_exit(1, "invalid type in seq_trace_output_generic: %d:\n", type); + erts_exit(ERTS_ERROR_EXIT, "invalid type in seq_trace_output_generic: %d:\n", type); return; /* To avoid warning */ } diff --git a/erts/emulator/beam/erl_unicode.c b/erts/emulator/beam/erl_unicode.c index 551717139d..36d85b0a22 100644 --- a/erts/emulator/beam/erl_unicode.c +++ b/erts/emulator/beam/erl_unicode.c @@ -2507,7 +2507,7 @@ void erts_copy_utf8_to_utf16_little(byte *target, byte *bytes, int num_chars) ((Uint) (bytes[3] & ((byte) 0x3F))); bytes += 4; } else { - erl_exit(1,"Internal unicode error in prim_file:internal_name2native/1"); + erts_exit(ERTS_ERROR_EXIT,"Internal unicode error in prim_file:internal_name2native/1"); } *target++ = (byte) (unipoint & 0xFF); *target++ = (byte) ((unipoint >> 8) & 0xFF); diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c index 58010dcb72..aac1490f0c 100644 --- a/erts/emulator/beam/external.c +++ b/erts/emulator/beam/external.c @@ -570,7 +570,7 @@ void erts_encode_ext(Eterm term, byte **ext) *ep++ = VERSION_MAGIC; ep = enc_term(NULL, term, ep, TERM_TO_BINARY_DFLAGS, NULL); if (!ep) - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "%s:%d:erts_encode_ext(): Internal data structure error\n", __FILE__, __LINE__); *ext = ep; @@ -1559,7 +1559,7 @@ static BIF_RETTYPE binary_to_term_int(Process* p, Uint32 flags, Eterm bin, Binar b2t_destroy_context(ctx); if (ctx->u.dc.factory.hp > ctx->u.dc.factory.hp_end) { - erl_exit(1, ":%s, line %d: heap overrun by %d words(s)\n", + erts_exit(ERTS_ERROR_EXIT, ":%s, line %d: heap overrun by %d words(s)\n", __FILE__, __LINE__, ctx->u.dc.factory.hp - ctx->u.dc.factory.hp_end); } erts_factory_close(&ctx->u.dc.factory); @@ -1708,12 +1708,12 @@ erts_term_to_binary_simple(Process* p, Eterm Term, Uint size, int level, Uint fl if ((endp = enc_term(NULL, Term, bytes, flags, NULL)) == NULL) { - erl_exit(1, "%s, line %d: bad term: %x\n", + erts_exit(ERTS_ERROR_EXIT, "%s, line %d: bad term: %x\n", __FILE__, __LINE__, Term); } real_size = endp - bytes; if (real_size > size) { - erl_exit(1, "%s, line %d: buffer overflow: %d word(s)\n", + erts_exit(ERTS_ERROR_EXIT, "%s, line %d: buffer overflow: %d word(s)\n", __FILE__, __LINE__, real_size - size); } @@ -1753,12 +1753,12 @@ erts_term_to_binary_simple(Process* p, Eterm Term, Uint size, int level, Uint fl bytes[0] = VERSION_MAGIC; if ((endp = enc_term(NULL, Term, bytes+1, flags, NULL)) == NULL) { - erl_exit(1, "%s, line %d: bad term: %x\n", + erts_exit(ERTS_ERROR_EXIT, "%s, line %d: bad term: %x\n", __FILE__, __LINE__, Term); } real_size = endp - bytes; if (real_size > size) { - erl_exit(1, "%s, line %d: buffer overflow: %d word(s)\n", + erts_exit(ERTS_ERROR_EXIT, "%s, line %d: buffer overflow: %d word(s)\n", __FILE__, __LINE__, endp - (bytes + size)); } return erts_realloc_binary(bin, real_size); @@ -2631,7 +2631,7 @@ enc_term_int(TTBEncodeContext* ctx, ErtsAtomCacheMap *acmp, Eterm obj, byte* ep, ASSERT(node_sz < 17); break; default: - erl_exit(1, "bad header\r\n"); + erts_exit(ERTS_ERROR_EXIT, "bad header\r\n"); } ptr++; @@ -4086,7 +4086,7 @@ encode_size_struct_int(TTBSizeContext* ctx, ErtsAtomCacheMap *acmp, Eterm obj, ASSERT(node_sz < 17); break; default: - erl_exit(1, "bad header\r\n"); + erts_exit(ERTS_ERROR_EXIT, "bad header\r\n"); } ptr++; @@ -4174,7 +4174,7 @@ encode_size_struct_int(TTBSizeContext* ctx, ErtsAtomCacheMap *acmp, Eterm obj, break; default: - erl_exit(1,"Internal data structure error (in encode_size_struct2)%x\n", + erts_exit(ERTS_ERROR_EXIT,"Internal data structure error (in encode_size_struct2)%x\n", obj); } diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index 956efa5e36..d7edf451be 100644 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -425,7 +425,7 @@ void erl_grow_estack(ErtsEStack*, Uint need); #define ESTACK_CHANGE_ALLOCATOR(s,t) \ do { \ if ((s).start != ESTK_DEF_STACK(s)) { \ - erl_exit(1, "Internal error - trying to change allocator " \ + erts_exit(ERTS_ERROR_EXIT, "Internal error - trying to change allocator " \ "type of active estack\n"); \ } \ (s).alloc_type = (t); \ @@ -586,7 +586,7 @@ do { \ #define WSTACK_CHANGE_ALLOCATOR(s,t) \ do { \ if (s.wstart != WSTK_DEF_STACK(s)) { \ - erl_exit(1, "Internal error - trying to change allocator " \ + erts_exit(ERTS_ERROR_EXIT, "Internal error - trying to change allocator " \ "type of active wstack\n"); \ } \ s.alloc_type = (t); \ @@ -778,7 +778,7 @@ ErtsPStack s = { (byte*)PSTK_DEF_STACK(s), /* pstart */ \ #define PSTACK_CHANGE_ALLOCATOR(s,t) \ do { \ if (s.pstart != (byte*)PSTK_DEF_STACK(s)) { \ - erl_exit(1, "Internal error - trying to change allocator " \ + erts_exit(ERTS_ERROR_EXIT, "Internal error - trying to change allocator " \ "type of active pstack\n"); \ } \ s.alloc_type = (t); \ @@ -1048,8 +1048,8 @@ double erts_get_positive_zero_float(void); /* config.c */ -__decl_noreturn void __noreturn erl_exit(int n, char*, ...); -__decl_noreturn void __noreturn erl_exit_flush_async(int n, char*, ...); +__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); /* This controls whether sharing-preserving copy is used by Erlang */ diff --git a/erts/emulator/beam/index.c b/erts/emulator/beam/index.c index 06d0b5123d..5f6ea14732 100644 --- a/erts/emulator/beam/index.c +++ b/erts/emulator/beam/index.c @@ -84,7 +84,7 @@ index_put_entry(IndexTable* t, void* tmpl) Uint sz; if (ix >= t->limit) { /* A core dump is unnecessary */ - erl_exit(ERTS_DUMP_EXIT, "no more index entries in %s (max=%d)\n", + erts_exit(ERTS_DUMP_EXIT, "no more index entries in %s (max=%d)\n", t->htable.name, t->limit); } sz = INDEX_PAGE_SIZE*sizeof(IndexSlot*); @@ -123,7 +123,7 @@ void erts_index_merge(Hash* src, IndexTable* dst) ix = dst->entries++; if (ix >= dst->size) { if (ix >= dst->limit) { - erl_exit(1, "no more index entries in %s (max=%d)\n", + erts_exit(ERTS_ERROR_EXIT, "no more index entries in %s (max=%d)\n", dst->htable.name, dst->limit); } sz = INDEX_PAGE_SIZE*sizeof(IndexSlot*); diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c index 41b0fcdd1b..797e4cdadc 100644 --- a/erts/emulator/beam/io.c +++ b/erts/emulator/beam/io.c @@ -3587,7 +3587,7 @@ terminate_port(Port *prt) if ((state & ERTS_PORT_SFLG_HALT) && (erts_smp_atomic32_dec_read_nob(&erts_halt_progress) == 0)) { erts_port_release(prt); /* We will exit and never return */ - erl_exit_flush_async(erts_halt_code, ""); + erts_flush_async_exit(erts_halt_code, ""); } if (is_internal_port(send_closed_port_id)) deliver_result(send_closed_port_id, connected_id, am_closed); @@ -5018,7 +5018,7 @@ void erts_raw_port_command(Port* p, byte* buf, Uint len) ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(p)); if (len > (Uint) INT_MAX) - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "Absurdly large data buffer (%beu bytes) passed to" "output callback of %s driver.\n", len, @@ -7396,7 +7396,7 @@ driver_system_info(ErlDrvSysInfo *sip, size_t si_size) * of ErlDrvSysInfo (introduced in driver version 1.0). */ if (!sip || si_size < ERL_DRV_SYS_INFO_SIZE(smp_support)) - erl_exit(1, + erts_exit(ERTS_ERROR_EXIT, "driver_system_info(%p, %ld) called with invalid arguments\n", sip, si_size); diff --git a/erts/emulator/beam/register.c b/erts/emulator/beam/register.c index fdb6cbc813..ebc35b0c4d 100644 --- a/erts/emulator/beam/register.c +++ b/erts/emulator/beam/register.c @@ -125,7 +125,7 @@ static RegProc* reg_alloc(RegProc *tmpl) { RegProc* obj = (RegProc*) erts_alloc(ERTS_ALC_T_REG_PROC, sizeof(RegProc)); if (!obj) { - erl_exit(1, "Can't allocate %d bytes of memory\n", sizeof(RegProc)); + erts_exit(ERTS_ERROR_EXIT, "Can't allocate %d bytes of memory\n", sizeof(RegProc)); } obj->name = tmpl->name; obj->p = tmpl->p; diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h index 068d636a40..03b9088adc 100644 --- a/erts/emulator/beam/sys.h +++ b/erts/emulator/beam/sys.h @@ -580,15 +580,16 @@ static unsigned long zero_value = 0, one_value = 1; # endif /* !__WIN32__ */ #endif /* WANT_NONBLOCKING */ -__decl_noreturn void __noreturn erl_exit(int n, char*, ...); +__decl_noreturn void __noreturn erts_exit(int n, char*, ...); -/* Some special erl_exit() codes: */ -#define ERTS_INTR_EXIT INT_MIN /* called from signal handler */ -#define ERTS_ABORT_EXIT (INT_MIN + 1) /* no crash dump; only abort() */ -#define ERTS_DUMP_EXIT (INT_MIN + 2) /* crash dump; then exit() */ +/* Some special erts_exit() codes: */ +#define ERTS_INTR_EXIT -1 /* called from signal handler */ +#define ERTS_ABORT_EXIT -2 /* no crash dump; only abort() */ +#define ERTS_DUMP_EXIT -3 /* crash dump; then exit() */ +#define ERTS_ERROR_EXIT -4 /* crash dump; then abort() */ #define ERTS_INTERNAL_ERROR(What) \ - erl_exit(ERTS_ABORT_EXIT, "%s:%d:%s(): Internal error: %s\n", \ + erts_exit(ERTS_ABORT_EXIT, "%s:%d:%s(): Internal error: %s\n", \ __FILE__, __LINE__, __func__, What) Eterm erts_check_io_info(void *p); @@ -903,7 +904,7 @@ erts_refc_inc(erts_refc_t *refcp, erts_aint_t min_val) #ifdef ERTS_REFC_DEBUG erts_aint_t val = erts_smp_atomic_inc_read_nob((erts_smp_atomic_t *) refcp); if (val < min_val) - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "erts_refc_inc(): Bad refc found (refc=%ld < %ld)!\n", val, min_val); #else @@ -917,7 +918,7 @@ erts_refc_inctest(erts_refc_t *refcp, erts_aint_t min_val) erts_aint_t val = erts_smp_atomic_inc_read_nob((erts_smp_atomic_t *) refcp); #ifdef ERTS_REFC_DEBUG if (val < min_val) - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "erts_refc_inctest(): Bad refc found (refc=%ld < %ld)!\n", val, min_val); #endif @@ -930,7 +931,7 @@ erts_refc_dec(erts_refc_t *refcp, erts_aint_t min_val) #ifdef ERTS_REFC_DEBUG erts_aint_t val = erts_smp_atomic_dec_read_nob((erts_smp_atomic_t *) refcp); if (val < min_val) - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "erts_refc_dec(): Bad refc found (refc=%ld < %ld)!\n", val, min_val); #else @@ -944,7 +945,7 @@ erts_refc_dectest(erts_refc_t *refcp, erts_aint_t min_val) erts_aint_t val = erts_smp_atomic_dec_read_nob((erts_smp_atomic_t *) refcp); #ifdef ERTS_REFC_DEBUG if (val < min_val) - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "erts_refc_dectest(): Bad refc found (refc=%ld < %ld)!\n", val, min_val); #endif @@ -957,7 +958,7 @@ erts_refc_add(erts_refc_t *refcp, erts_aint_t diff, erts_aint_t min_val) #ifdef ERTS_REFC_DEBUG erts_aint_t val = erts_smp_atomic_add_read_nob((erts_smp_atomic_t *) refcp, diff); if (val < min_val) - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "erts_refc_add(%ld): Bad refc found (refc=%ld < %ld)!\n", diff, val, min_val); #else @@ -971,7 +972,7 @@ erts_refc_read(erts_refc_t *refcp, erts_aint_t min_val) erts_aint_t val = erts_smp_atomic_read_nob((erts_smp_atomic_t *) refcp); #ifdef ERTS_REFC_DEBUG if (val < min_val) - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "erts_refc_read(): Bad refc found (refc=%ld < %ld)!\n", val, min_val); #endif diff --git a/erts/emulator/beam/time.c b/erts/emulator/beam/time.c index 48cb39333a..0ce4f443f3 100644 --- a/erts/emulator/beam/time.c +++ b/erts/emulator/beam/time.c @@ -567,7 +567,7 @@ erts_init_time(int time_correction, ErtsTimeWarpMode time_warp_mode) itime = erts_init_time_sup(time_correction, time_warp_mode); #ifdef TIW_ITIME_IS_CONSTANT if (itime != TIW_ITIME) { - erl_exit(ERTS_ABORT_EXIT, "timer resolution mismatch %d != %d", itime, TIW_ITIME); + erts_exit(ERTS_ABORT_EXIT, "timer resolution mismatch %d != %d", itime, TIW_ITIME); } #else tiw_itime = itime; diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c index 3ba02023a1..66fcfcf6ce 100644 --- a/erts/emulator/beam/utils.c +++ b/erts/emulator/beam/utils.c @@ -1069,7 +1069,7 @@ tail_recur: } default: - erl_exit(1, "Invalid tag in make_hash(0x%X,0x%X)\n", term, op); + erts_exit(ERTS_ERROR_EXIT, "Invalid tag in make_hash(0x%X,0x%X)\n", term, op); return 0; } if (WSTACK_ISEMPTY(stack)) break; @@ -1342,7 +1342,7 @@ make_hash2(Eterm term) i = hashmap_bitcount(MAP_HEADER_VAL(hdr)); break; default: - erl_exit(1, "bad header"); + erts_exit(ERTS_ERROR_EXIT, "bad header"); } while (i) { if (is_list(*ptr)) { @@ -1505,7 +1505,7 @@ make_hash2(Eterm term) break; default: - erl_exit(1, "Invalid tag in make_hash2(0x%X)\n", term); + erts_exit(ERTS_ERROR_EXIT, "Invalid tag in make_hash2(0x%X)\n", term); } } break; @@ -1536,7 +1536,7 @@ make_hash2(Eterm term) UINT32_HASH(NIL_DEF, HCONST_2); goto hash2_common; default: - erl_exit(1, "Invalid tag in make_hash2(0x%X)\n", term); + erts_exit(ERTS_ERROR_EXIT, "Invalid tag in make_hash2(0x%X)\n", term); } case _TAG_IMMED1_SMALL: { @@ -1552,7 +1552,7 @@ make_hash2(Eterm term) } break; default: - erl_exit(1, "Invalid tag in make_hash2(0x%X)\n", term); + erts_exit(ERTS_ERROR_EXIT, "Invalid tag in make_hash2(0x%X)\n", term); hash2_common: /* Uint32 hash always has the hash value of the previous term, @@ -1747,7 +1747,7 @@ make_internal_hash(Eterm term) i = hashmap_bitcount(MAP_HEADER_VAL(hdr)); break; default: - erl_exit(1, "bad header"); + erts_exit(ERTS_ERROR_EXIT, "bad header"); } while (i) { if (is_list(*ptr)) { @@ -1923,7 +1923,7 @@ make_internal_hash(Eterm term) goto pop_next; } default: - erl_exit(1, "Invalid tag in make_hash2(0x%X)\n", term); + erts_exit(ERTS_ERROR_EXIT, "Invalid tag in make_hash2(0x%X)\n", term); } } break; @@ -1936,7 +1936,7 @@ make_internal_hash(Eterm term) goto pop_next; default: - erl_exit(1, "Invalid tag in make_hash2(0x%X)\n", term); + erts_exit(ERTS_ERROR_EXIT, "Invalid tag in make_hash2(0x%X)\n", term); pop_next: if (ESTACK_ISEMPTY(s)) { @@ -2219,7 +2219,7 @@ tail_recur: } default: - erl_exit(1, "Invalid tag in make_broken_hash\n"); + erts_exit(ERTS_ERROR_EXIT, "Invalid tag in make_broken_hash\n"); return 0; } if (WSTACK_ISEMPTY(stack)) break; @@ -2893,7 +2893,7 @@ tailrecur_ne: ASSERT(sz > 0 && sz < 17); break; default: - erl_exit(1, "Unknown hashmap subsubtag\n"); + erts_exit(ERTS_ERROR_EXIT, "Unknown hashmap subsubtag\n"); } goto term_array; } diff --git a/erts/emulator/drivers/common/efile_drv.c b/erts/emulator/drivers/common/efile_drv.c index c5c780dce5..3088dfd572 100644 --- a/erts/emulator/drivers/common/efile_drv.c +++ b/erts/emulator/drivers/common/efile_drv.c @@ -119,8 +119,6 @@ #include "dtrace-wrapper.h" -void erl_exit(int n, char *fmt, ...); - static ErlDrvSysInfo sys_info; /* For explanation of this var, see comment for same var in erl_async.c */ @@ -509,21 +507,10 @@ struct t_data static void *ef_safe_alloc(Uint s) { void *p = EF_ALLOC(s); - if (!p) erl_exit(1, "efile drv: Can't allocate %lu bytes of memory\n", (unsigned long)s); - return p; -} - -#if 0 /* Currently not used */ - -static void *ef_safe_realloc(void *op, Uint s) -{ - void *p = EF_REALLOC(op, s); - if (!p) erl_exit(1, "efile drv: Can't reallocate %lu bytes of memory\n", (unsigned long)s); + if (!p) erts_exit(ERTS_ERROR_EXIT, "efile drv: Can't allocate %lu bytes of memory\n", (unsigned long)s); return p; } -#endif - /********************************************************************* * ErlIOVec manipulation functions. */ diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c index f910b5955a..b219669ce5 100644 --- a/erts/emulator/drivers/common/inet_drv.c +++ b/erts/emulator/drivers/common/inet_drv.c @@ -1345,7 +1345,7 @@ static const struct in6_addr in6addr_loopback = #endif /* HAVE_IN6 */ /* XXX: is this a driver interface function ??? */ -void erl_exit(int n, char*, ...); +void erts_exit(int n, char*, ...); /* * Malloc wrapper, @@ -1358,7 +1358,7 @@ void erl_exit(int n, char*, ...); static void *alloc_wrapper(ErlDrvSizeT size){ void *ret = driver_alloc(size); if(ret == NULL) - erl_exit(1,"Out of virtual memory in malloc (%s)", __FILE__); + erts_exit(ERTS_ERROR_EXIT,"Out of virtual memory in malloc (%s)", __FILE__); return ret; } #define ALLOC(X) alloc_wrapper(X) @@ -1366,7 +1366,7 @@ static void *alloc_wrapper(ErlDrvSizeT size){ static void *realloc_wrapper(void *current, ErlDrvSizeT size){ void *ret = driver_realloc(current,size); if(ret == NULL) - erl_exit(1,"Out of virtual memory in realloc (%s)", __FILE__); + erts_exit(ERTS_ERROR_EXIT,"Out of virtual memory in realloc (%s)", __FILE__); return ret; } #define REALLOC(X,Y) realloc_wrapper(X,Y) @@ -1627,7 +1627,7 @@ check_double_release(InetDrvBufStk *bs, ErlDrvBinary* buf) int i; for (i = 0; i < bs->buf.pos; ++i) { if (bs->buf.stk[i] == buf) { - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "Multiple buffer release in inet_drv, this " "is a bug, save the core and send it to " "[email protected]!"); @@ -6803,7 +6803,7 @@ static ErlDrvSSizeT inet_fill_opts(inet_descriptor* desc, do { \ ErlDrvSizeT new_need = ((Ptr) - (*dest)) + (Size); \ if (new_need > dest_used) { \ - erl_exit(1,"Internal error in inet_drv, " \ + erts_exit(ERTS_ERROR_EXIT,"Internal error in inet_drv, " \ "miscalculated buffer size"); \ } \ dest_used = new_need; \ @@ -7180,7 +7180,7 @@ static ErlDrvSSizeT sctp_fill_opts(inet_descriptor* desc, do { \ int need; \ if ((Index) > spec_allocated) { \ - erl_exit(1,"Internal error in inet_drv, " \ + erts_exit(ERTS_ERROR_EXIT,"Internal error in inet_drv, " \ "miscalculated buffer size"); \ } \ need = (Index) + (N); \ 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/win32/win_con.c b/erts/emulator/drivers/win32/win_con.c index 0d63d46698..7fe708dc7b 100644 --- a/erts/emulator/drivers/win32/win_con.c +++ b/erts/emulator/drivers/win32/win_con.c @@ -279,7 +279,7 @@ ConInit(void) } /* - ConNormalExit() is called from erl_exit() when the emulator + ConNormalExit() is called from erts_exit() when the emulator is stopping. If the exit has not been initiated by this console thread (WM_DESTROY or ID_BREAK), the function must invoke the console thread to save the user preferences. @@ -529,7 +529,7 @@ ConThreadInit(LPVOID param) /* PostQuitMessage() results in WM_QUIT which makes GetMessage() return 0 (which stops the main loop). Before we return from - the console thread, the ctrl_handler is called to do erl_exit. + the console thread, the ctrl_handler is called to do erts_exit. */ (*ctrl_handler)(CTRL_CLOSE_EVENT); return msg.wParam; diff --git a/erts/emulator/hipe/hipe_bif0.c b/erts/emulator/hipe/hipe_bif0.c index 6f495b8825..70354aa9af 100644 --- a/erts/emulator/hipe/hipe_bif0.c +++ b/erts/emulator/hipe/hipe_bif0.c @@ -406,7 +406,7 @@ BIF_RETTYPE hipe_bifs_enter_code_2(BIF_ALIST_2) nrcallees = arityval(tuple_val(BIF_ARG_2)[0]); else nrcallees = 0; - erl_exit(1, "%s: failed to allocate %lu bytes and %lu trampolines\r\n", + erts_exit(ERTS_ERROR_EXIT, "%s: failed to allocate %lu bytes and %lu trampolines\r\n", __func__, (unsigned long)nrbytes, (unsigned long)nrcallees); } memcpy(address, bytes, nrbytes); @@ -1322,7 +1322,7 @@ static void *hipe_make_stub(Eterm m, Eterm f, unsigned int arity, int is_remote) export_entry = erts_export_get_or_make_stub(m, f, arity); StubAddress = hipe_make_native_stub(export_entry, arity); if (!StubAddress) - erl_exit(1, "hipe_make_stub: code allocation failed\r\n"); + erts_exit(ERTS_ERROR_EXIT, "hipe_make_stub: code allocation failed\r\n"); return StubAddress; } diff --git a/erts/emulator/hipe/hipe_mode_switch.c b/erts/emulator/hipe/hipe_mode_switch.c index 976180cc30..804c458b6c 100644 --- a/erts/emulator/hipe/hipe_mode_switch.c +++ b/erts/emulator/hipe/hipe_mode_switch.c @@ -108,7 +108,7 @@ static const char *code_str(unsigned code) static void __noreturn hipe_abort(const char *expr, const char *file, unsigned line) { - erl_exit(1, "ASSERTION FAILED, file %s, line %u: %s\r\n", file, line, expr); + erts_exit(ERTS_ERROR_EXIT, "ASSERTION FAILED, file %s, line %u: %s\r\n", file, line, expr); } #define HIPE_ASSERT3(expr, file, line) \ @@ -316,7 +316,7 @@ Process *hipe_mode_switch(Process *p, unsigned cmd, Eterm reg[]) break; } default: - erl_exit(1, "hipe_mode_switch: cmd %#x\r\n", cmd); + erts_exit(ERTS_ERROR_EXIT, "hipe_mode_switch: cmd %#x\r\n", cmd); } do_return_from_native: DPRINTF("result == %#x (%s)", result, code_str(result)); @@ -560,7 +560,7 @@ Process *hipe_mode_switch(Process *p, unsigned cmd, Eterm reg[]) goto do_throw_to_native; } default: - erl_exit(1, "hipe_mode_switch: result %#x\r\n", result); + erts_exit(ERTS_ERROR_EXIT, "hipe_mode_switch: result %#x\r\n", result); } HIPE_CHECK_PCB(p); p->def_arg_reg[3] = result; diff --git a/erts/emulator/hipe/hipe_native_bif.c b/erts/emulator/hipe/hipe_native_bif.c index 16cc70234d..0ec417999b 100644 --- a/erts/emulator/hipe/hipe_native_bif.c +++ b/erts/emulator/hipe/hipe_native_bif.c @@ -180,7 +180,7 @@ void hipe_fclearerror_error(Process *p) #if !defined(NO_FPE_SIGNALS) erts_fp_check_init_error(&p->fp_exception); #else - erl_exit(ERTS_ABORT_EXIT, "Emulated FPE not cleared by HiPE"); + erts_exit(ERTS_ABORT_EXIT, "Emulated FPE not cleared by HiPE"); #endif } diff --git a/erts/emulator/sys/common/erl_mmap.c b/erts/emulator/sys/common/erl_mmap.c index 03ca080c14..889d6f3868 100644 --- a/erts/emulator/sys/common/erl_mmap.c +++ b/erts/emulator/sys/common/erl_mmap.c @@ -1341,7 +1341,7 @@ os_unreserve_physical(char *ptr, UWord size) void *res = mmap((void *) ptr, (size_t) size, ERTS_MMAP_UNRESERVE_PROT, ERTS_MMAP_UNRESERVE_FLAGS, ERTS_MMAP_FD, 0); if (res == (void *) MAP_FAILED) - erl_exit(ERTS_ABORT_EXIT, "Failed to unreserve memory"); + erts_exit(ERTS_ABORT_EXIT, "Failed to unreserve memory"); } static void * @@ -2136,7 +2136,7 @@ erts_mmap_init(ErtsMemMapper* mm, ErtsMMapInit *init) #endif erts_page_inv_mask = pagesize - 1; if (pagesize & erts_page_inv_mask) - erl_exit(-1, "erts_mmap: Invalid pagesize: %bpu\n", + erts_exit(1, "erts_mmap: Invalid pagesize: %bpu\n", pagesize); ERTS_MMAP_OP_RINGBUF_INIT(); @@ -2148,7 +2148,7 @@ erts_mmap_init(ErtsMemMapper* mm, ErtsMMapInit *init) #if HAVE_MMAP && !defined(MAP_ANON) mm->mmap_fd = open("/dev/zero", O_RDWR); if (mm->mmap_fd < 0) - erl_exit(-1, "erts_mmap: Failed to open /dev/zero\n"); + erts_exit(1, "erts_mmap: Failed to open /dev/zero\n"); #endif erts_smp_mtx_init(&mm->mtx, "erts_mmap"); @@ -2165,7 +2165,7 @@ erts_mmap_init(ErtsMemMapper* mm, ErtsMMapInit *init) sz = end - ptr; start = os_mmap_virtual(ptr, sz); if (!start || start > ptr || start >= end) - erl_exit(-1, + erts_exit(1, "erts_mmap: Failed to create virtual range for super carrier\n"); sz = start - ptr; if (sz) @@ -2203,7 +2203,7 @@ erts_mmap_init(ErtsMemMapper* mm, ErtsMMapInit *init) start = os_mmap(NULL, sz, 1); } if (!start) - erl_exit(-1, + erts_exit(1, "erts_mmap: Failed to create super carrier of size %bpu MB\n", init->scs/1024/1024); end = start + sz; @@ -2250,7 +2250,7 @@ erts_mmap_init(ErtsMemMapper* mm, ErtsMMapInit *init) if ((desc_size + ERTS_SUPERALIGNED_SIZE + ERTS_PAGEALIGNED_SIZE) > end - start) - erl_exit(-1, "erts_mmap: No space for segments in super carrier\n"); + erts_exit(1, "erts_mmap: No space for segments in super carrier\n"); mm->sa.bot = start; mm->sa.bot += desc_size; @@ -2288,7 +2288,7 @@ erts_mmap_init(ErtsMemMapper* mm, ErtsMMapInit *init) */ #ifdef ERTS_HAVE_OS_PHYSICAL_MEMORY_RESERVATION if (virtual_map && !os_reserve_physical(start, mm->sa.bot - start)) - erl_exit(-1, "erts_mmap: Failed to reserve physical memory for descriptors\n"); + erts_exit(1, "erts_mmap: Failed to reserve physical memory for descriptors\n"); #endif mm->desc.unused_start = start; mm->desc.unused_end = mm->sa.bot; diff --git a/erts/emulator/sys/common/erl_mmap.h b/erts/emulator/sys/common/erl_mmap.h index 61d912fd28..67e131b53e 100644 --- a/erts/emulator/sys/common/erl_mmap.h +++ b/erts/emulator/sys/common/erl_mmap.h @@ -50,8 +50,10 @@ typedef struct { #define ERTS_MMAP_INIT_DEFAULT_INITER \ {{NULL, NULL}, {NULL, NULL}, 0, 1, (1 << 16), 1} +#define ERTS_LITERAL_VIRTUAL_AREA_SIZE (UWORD_CONSTANT(1)*1024*1024*1024) + #define ERTS_MMAP_INIT_LITERAL_INITER \ - {{NULL, NULL}, {NULL, NULL}, 1024*1024*1024, 1, (1 << 16), 0} + {{NULL, NULL}, {NULL, NULL}, ERTS_LITERAL_VIRTUAL_AREA_SIZE, 1, (1 << 16), 0} typedef struct ErtsMemMapper_ ErtsMemMapper; diff --git a/erts/emulator/sys/common/erl_mseg.c b/erts/emulator/sys/common/erl_mseg.c index 20695899eb..286130bece 100644 --- a/erts/emulator/sys/common/erl_mseg.c +++ b/erts/emulator/sys/common/erl_mseg.c @@ -1403,9 +1403,12 @@ erts_mseg_init(ErtsMsegInit_t *init) erts_mtx_init(&init_atoms_mutex, "mseg_init_atoms"); 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 if (!IS_2POW(GET_PAGE_SIZE)) - erl_exit(ERTS_ABORT_EXIT, "erts_mseg: Unexpected page_size %beu\n", GET_PAGE_SIZE); + erts_exit(ERTS_ABORT_EXIT, "erts_mseg: Unexpected page_size %beu\n", GET_PAGE_SIZE); ASSERT((MSEG_ALIGNED_SIZE % GET_PAGE_SIZE) == 0); diff --git a/erts/emulator/sys/common/erl_os_monotonic_time_extender.c b/erts/emulator/sys/common/erl_os_monotonic_time_extender.c index b79485241f..367b22d989 100644 --- a/erts/emulator/sys/common/erl_os_monotonic_time_extender.c +++ b/erts/emulator/sys/common/erl_os_monotonic_time_extender.c @@ -44,7 +44,7 @@ static void *os_monotonic_time_extender(void *vstatep) erts_milli_sleep(sleep_time); } - erl_exit(ERTS_ABORT_EXIT, "os_monotonic_time_extender thread terminating"); + erts_exit(ERTS_ABORT_EXIT, "os_monotonic_time_extender thread terminating"); return NULL; } diff --git a/erts/emulator/sys/unix/erl_child_setup.c b/erts/emulator/sys/unix/erl_child_setup.c index 4e61530cf1..8dd14bbac6 100644 --- a/erts/emulator/sys/unix/erl_child_setup.c +++ b/erts/emulator/sys/unix/erl_child_setup.c @@ -61,6 +61,7 @@ #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) diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c index 2ad5f3b4d5..0a18e54389 100644 --- a/erts/emulator/sys/unix/sys.c +++ b/erts/emulator/sys/unix/sys.c @@ -631,7 +631,7 @@ break_requested(void) fprintf(stderr,"break!\n"); #endif if (ERTS_BREAK_REQUESTED) - erl_exit(ERTS_INTR_EXIT, ""); + erts_exit(ERTS_INTR_EXIT, ""); ERTS_SET_BREAK_REQUESTED; ERTS_CHK_IO_AS_INTR(); /* Make sure we don't sleep in poll */ @@ -670,7 +670,7 @@ sigusr1_exit(void) } prepare_crash_dump(secs); - erl_exit(1, "Received SIGUSR1\n"); + erts_exit(ERTS_ERROR_EXIT, "Received SIGUSR1\n"); } #ifdef ETHR_UNUSABLE_SIGUSRX @@ -726,7 +726,7 @@ static RETSIGTYPE suspend_signal(int signum) static void quit_requested(void) { - erl_exit(ERTS_INTR_EXIT, ""); + erts_exit(ERTS_INTR_EXIT, ""); } #if (defined(SIG_SIGSET) || defined(SIG_SIGNAL)) @@ -1252,7 +1252,7 @@ signal_dispatcher_thread_func(void *unused) if (res < 0) { if (errno == EINTR) continue; - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "signal-dispatcher thread got unexpected error: %s (%d)\n", erl_errno_id(errno), errno); @@ -1289,7 +1289,7 @@ signal_dispatcher_thread_func(void *unused) sigusr1_exit(); break; default: - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "signal-dispatcher thread received unknown " "signal notification: '%c'\n", buf[i]); @@ -1308,7 +1308,7 @@ init_smp_sig_notify(void) thr_opts.name = "sys_sig_dispatcher"; if (pipe(sig_notify_fds) < 0) { - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "Failed to create signal-dispatcher pipe: %s (%d)\n", erl_errno_id(errno), errno); @@ -1324,7 +1324,7 @@ init_smp_sig_notify(void) static void init_smp_sig_suspend(void) { if (pipe(sig_suspend_fds) < 0) { - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "Failed to create sig_suspend pipe: %s (%d)\n", erl_errno_id(errno), errno); @@ -1340,7 +1340,7 @@ static void initialize_darwin_main_thread_pipes(void) { if (pipe(erts_darwin_main_thread_pipe) < 0 || pipe(erts_darwin_main_thread_result_pipe) < 0) { - erl_exit(1,"Fatal error initializing Darwin main thread stealing"); + erts_exit(ERTS_ERROR_EXIT,"Fatal error initializing Darwin main thread stealing"); } } diff --git a/erts/emulator/sys/unix/sys_drivers.c b/erts/emulator/sys/unix/sys_drivers.c index 2a7cd91265..82fea1b330 100644 --- a/erts/emulator/sys/unix/sys_drivers.c +++ b/erts/emulator/sys/unix/sys_drivers.c @@ -1665,14 +1665,14 @@ static ErlDrvData forker_start(ErlDrvPort port_num, char* name, res = erts_sys_getenv_raw("BINDIR", bindir, &bindirsz); if (res != 0) { if (res < 0) - erl_exit(-1, + erts_exit(1, "Environment variable BINDIR is not set\n"); if (res > 0) - erl_exit(-1, + erts_exit(1, "Value of environment variable BINDIR is too large\n"); } if (bindir[0] != DIR_SEPARATOR_CHAR) - erl_exit(-1, + erts_exit(1, "Environment variable BINDIR does not contain an" " absolute path\n"); csp_path_sz = (strlen(bindir) @@ -1686,7 +1686,7 @@ static ErlDrvData forker_start(ErlDrvPort port_num, char* name, DIR_SEPARATOR_CHAR, CHILD_SETUP_PROG_NAME); if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "Could not open unix domain socket in spawn_init: %d\n", errno); } @@ -1754,11 +1754,11 @@ static void forker_ready_input(ErlDrvData e, ErlDrvEvent fd) if ((res = read(fd, proto, sizeof(*proto))) < 0) { if (errno == ERRNO_BLOCK) return; - erl_exit(ERTS_DUMP_EXIT, "Failed to read from erl_child_setup: %d\n", errno); + erts_exit(ERTS_DUMP_EXIT, "Failed to read from erl_child_setup: %d\n", errno); } if (res == 0) - erl_exit(ERTS_DUMP_EXIT, "erl_child_setup closed\n"); + erts_exit(ERTS_DUMP_EXIT, "erl_child_setup closed\n"); ASSERT(res == sizeof(*proto)); @@ -1814,7 +1814,7 @@ static void forker_ready_output(ErlDrvData e, ErlDrvEvent fd) proto->u.start.fds, 3, 0) < 0) { if (errno == ERRNO_BLOCK) return; - erl_exit(ERTS_DUMP_EXIT, "Failed to write to erl_child_setup: %d\n", errno); + 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]); @@ -1846,7 +1846,7 @@ static ErlDrvSSizeT forker_control(ErlDrvData e, unsigned int cmd, char *buf, driver_select(port_num, forker_fd, ERL_DRV_WRITE|ERL_DRV_USE, 1); return 0; } - erl_exit(ERTS_DUMP_EXIT, "Failed to write to erl_child_setup: %d\n", errno); + erts_exit(ERTS_DUMP_EXIT, "Failed to write to erl_child_setup: %d\n", errno); } #ifndef FORKER_PROTO_START_ACK diff --git a/erts/emulator/sys/unix/sys_float.c b/erts/emulator/sys/unix/sys_float.c index 1ef9e5eef7..8fe7e599e5 100644 --- a/erts/emulator/sys/unix/sys_float.c +++ b/erts/emulator/sys/unix/sys_float.c @@ -90,7 +90,7 @@ void erts_fp_check_init_error(volatile unsigned long *fpexnp) 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) - erl_exit(ERTS_ABORT_EXIT, "%s", buf); + erts_exit(ERTS_ABORT_EXIT, "%s", buf); *fpexnp = 0; #if defined(__i386__) || defined(__x86_64__) erts_restore_fpu(); diff --git a/erts/emulator/sys/unix/sys_time.c b/erts/emulator/sys/unix/sys_time.c index 03d39c7ce6..8ce02506ab 100644 --- a/erts/emulator/sys/unix/sys_time.c +++ b/erts/emulator/sys/unix/sys_time.c @@ -344,7 +344,7 @@ sys_init_time(ErtsSysInitTimeResult *init_resp) * times() (CLK_TCK), the resolution is always one millisecond.. */ if ((erts_sys_time_data__.r.o.ticks_per_sec = TICKS_PER_SEC()) < 0) - erl_exit(ERTS_ABORT_EXIT, "Can't get clock ticks/sec\n"); + erts_exit(ERTS_ABORT_EXIT, "Can't get clock ticks/sec\n"); #if defined(OS_MONOTONIC_TIME_USING_TIMES) #if ERTS_COMPILE_TIME_MONOTONIC_TIME_UNIT @@ -454,7 +454,7 @@ posix_clock_gettime(clockid_t id, char *name) if (clock_gettime(id, &ts) != 0) { int err = errno; char *errstr = err ? strerror(err) : "unknown"; - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "clock_gettime(%s, _) failed: %s (%d)\n", name, errstr, err); } @@ -499,13 +499,13 @@ posix_clock_gettime_times(clockid_t mid, char *mname, if (mres != 0) { char *errstr = merr ? strerror(merr) : "unknown"; - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "clock_gettime(%s, _) failed: %s (%d)\n", mname, errstr, merr); } if (sres != 0) { char *errstr = serr ? strerror(serr) : "unknown"; - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "clock_gettime(%s, _) failed: %s (%d)\n", sname, errstr, serr); } @@ -678,7 +678,7 @@ mach_clocks_init(void) clck_srv_p = &internal_state.r.o.mach.clock.monotonic.srv; kret = host_get_clock_service(host, id, clck_srv_p); if (kret != KERN_SUCCESS) { - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "host_get_clock_service(_, %s, _) failed\n", name); } @@ -690,7 +690,7 @@ mach_clocks_init(void) clck_srv_p = &internal_state.r.o.mach.clock.wall.srv; kret = host_get_clock_service(host, id, clck_srv_p); if (kret != KERN_SUCCESS) { - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "host_get_clock_service(_, %s, _) failed\n", name); } @@ -699,7 +699,7 @@ mach_clocks_init(void) if (atexit(mach_clocks_fini) != 0) { int err = errno; char *errstr = err ? strerror(err) : "unknown"; - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "Failed to register mach_clocks_fini() " "for call at exit: %s (%d)\n", errstr, err); @@ -721,7 +721,7 @@ mach_clock_getres(ErtsMachClock *clk) (clock_attr_t) attr, &cnt); if (kret != KERN_SUCCESS || cnt != 1) { - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "clock_get_attributes(%s, _) failed\n", clk->name); } @@ -739,7 +739,7 @@ mach_clock_get_time(ErtsMachClock *clk) kret = clock_get_time(clk->srv, &time_spec); if (kret != KERN_SUCCESS) - erl_exit(ERTS_ABORT_EXIT, "clock_get_time(%s, _) failed\n", clk->name); + erts_exit(ERTS_ABORT_EXIT, "clock_get_time(%s, _) failed\n", clk->name); return ERTS_TimeSpec2Sint64(&time_spec); } @@ -785,11 +785,11 @@ erts_os_times(ErtsMonotonicTime *mtimep, ErtsSystemTime *stimep) &sys_time_spec); if (mkret != KERN_SUCCESS) - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "clock_get_time(%s, _) failed\n", internal_state.r.o.mach.clock.monotonic.name); if (skret != KERN_SUCCESS) - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "clock_get_time(%s, _) failed\n", internal_state.r.o.mach.clock.wall.name); @@ -854,7 +854,7 @@ erts_os_system_time(void) if (gettimeofday(&tv, NULL) != 0) { int err = errno; char *errstr = err ? strerror(err) : "unknown"; - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "gettimeofday(_, NULL) failed: %s (%d)\n", errstr, err); } diff --git a/erts/emulator/sys/win32/erl_poll.c b/erts/emulator/sys/win32/erl_poll.c index 660ded297a..9c1bef5f4f 100644 --- a/erts/emulator/sys/win32/erl_poll.c +++ b/erts/emulator/sys/win32/erl_poll.c @@ -437,7 +437,7 @@ wakeup_cause(ErtsPollSet ps) break; default: res = 0; - erl_exit(ERTS_ABORT_EXIT, + erts_exit(ERTS_ABORT_EXIT, "%s:%d: Internal error: Invalid wakeup_state=%d\n", __FILE__, __LINE__, (int) wakeup_state); } @@ -577,7 +577,7 @@ static void signal_standby(ErtsPollSet ps) --(ps->standby_wait_counter); if (ps->standby_wait_counter < 0) { LeaveCriticalSection(&(ps->standby_crit)); - erl_exit(1,"Standby signalled by more threads than expected"); + erts_exit(ERTS_ERROR_EXIT,"Standby signalled by more threads than expected"); } if (!(ps->standby_wait_counter)) { SetEvent(ps->standby_wait_event); @@ -739,7 +739,7 @@ static void *break_waiter(void *param) erts_mtx_unlock(&break_waiter_lock); break; default: - erl_exit(1,"Unexpected event in break_waiter"); + erts_exit(ERTS_ERROR_EXIT,"Unexpected event in break_waiter"); } } } @@ -1158,7 +1158,7 @@ int erts_poll_wait(ErtsPollSet ps, HARDDEBUGF(("Oups!")); /* Oups, got signalled before we took the lock, can't reset */ if(!is_io_ready(ps)) { - erl_exit(1,"Internal error: " + erts_exit(ERTS_ERROR_EXIT,"Internal error: " "Inconsistent io structures in erl_poll.\n"); } START_WAITER(ps,w); @@ -1219,7 +1219,7 @@ int erts_poll_wait(ErtsPollSet ps, ERTS_SET_BREAK_REQUESTED; break; case BREAK_WAITER_GOT_HALT: - erl_exit(0,""); + erts_exit(0,""); break; default: break; diff --git a/erts/emulator/sys/win32/sys.c b/erts/emulator/sys/win32/sys.c index 76ce25916a..ea7523ddc2 100644 --- a/erts/emulator/sys/win32/sys.c +++ b/erts/emulator/sys/win32/sys.c @@ -38,7 +38,7 @@ void erts_sys_init_float(void); void erl_start(int, char**); -void erl_exit(int n, char*, ...); +void erts_exit(int n, char*, ...); void erl_error(char*, va_list); void erl_crash_dump(char*, int, char*, ...); @@ -200,7 +200,7 @@ erts_sys_misc_mem_sz(void) */ void sys_tty_reset(int exit_code) { - if (exit_code > 0) + if (exit_code == ERTS_ERROR_EXIT) ConWaitForExit(); else ConNormalExit(); @@ -3108,13 +3108,13 @@ check_supported_os_version(void) || int_os_version.dwMajorVersion < major || (int_os_version.dwMajorVersion == major && int_os_version.dwMinorVersion < minor)) - erl_exit(-1, + erts_exit(1, "Windows version not supported " "(min required: winnt %d.%d)\n", major, minor); } #else - erl_exit(-1, + erts_exit(1, "Windows version not supported " "(min required: win %d.%d)\n", nt_major, nt_minor); diff --git a/erts/emulator/sys/win32/sys_interrupt.c b/erts/emulator/sys/win32/sys_interrupt.c index d6178de03c..a89211fa8e 100644 --- a/erts/emulator/sys/win32/sys_interrupt.c +++ b/erts/emulator/sys/win32/sys_interrupt.c @@ -81,7 +81,7 @@ BOOL WINAPI ctrl_handler_ignore_break(DWORD dwCtrlType) return TRUE; /* else pour through... */ case CTRL_CLOSE_EVENT: - erl_exit(0, ""); + erts_exit(0, ""); break; } return TRUE; @@ -106,7 +106,7 @@ BOOL WINAPI ctrl_handler_replace_intr(DWORD dwCtrlType) /* else pour through... */ case CTRL_CLOSE_EVENT: case CTRL_SHUTDOWN_EVENT: - erl_exit(0, ""); + erts_exit(0, ""); break; } return TRUE; @@ -133,7 +133,7 @@ BOOL WINAPI ctrl_handler(DWORD dwCtrlType) return TRUE; /* else pour through... */ case CTRL_CLOSE_EVENT: - erl_exit(0, ""); + erts_exit(0, ""); break; } return TRUE; diff --git a/erts/emulator/sys/win32/sys_time.c b/erts/emulator/sys/win32/sys_time.c index 3b4fd26d63..9a9d90610d 100644 --- a/erts/emulator/sys/win32/sys_time.c +++ b/erts/emulator/sys/win32/sys_time.c @@ -147,7 +147,7 @@ os_monotonic_time_qpc(void) LARGE_INTEGER pc; if (!(*internal_state.r.o.pQueryPerformanceCounter)(&pc)) - erl_exit(ERTS_ABORT_EXIT, "QueryPerformanceCounter() failed\n"); + erts_exit(ERTS_ABORT_EXIT, "QueryPerformanceCounter() failed\n"); return (ErtsMonotonicTime) pc.QuadPart; } @@ -164,7 +164,7 @@ os_times_qpc(ErtsMonotonicTime *mtimep, ErtsSystemTime *stimep) GetSystemTime(&st); if (!qpcr) - erl_exit(ERTS_ABORT_EXIT, "QueryPerformanceCounter() failed\n"); + erts_exit(ERTS_ABORT_EXIT, "QueryPerformanceCounter() failed\n"); *mtimep = (ErtsMonotonicTime) pc.QuadPart; @@ -251,7 +251,7 @@ sys_hrtime_qpc(void) LARGE_INTEGER pc; if (!(*internal_state.r.o.pQueryPerformanceCounter)(&pc)) - erl_exit(ERTS_ABORT_EXIT, "QueryPerformanceCounter() failed\n"); + erts_exit(ERTS_ABORT_EXIT, "QueryPerformanceCounter() failed\n"); ASSERT(pc.QuadPart > 0); diff --git a/erts/emulator/test/a_SUITE.erl b/erts/emulator/test/a_SUITE.erl index a9bba9548b..5b3a213154 100644 --- a/erts/emulator/test/a_SUITE.erl +++ b/erts/emulator/test/a_SUITE.erl @@ -29,66 +29,41 @@ -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 879fb03927..a72cd8deea 100644 --- a/erts/emulator/test/after_SUITE.erl +++ b/erts/emulator/test/after_SUITE.erl @@ -24,90 +24,64 @@ -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 332e2ad67d..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"). --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,12 +81,12 @@ migration(Cfg) -> end. erts_mmap(Config) when is_list(Config) -> - case ?t:os_type() of + case test_server:os_type() of {unix, _} -> [erts_mmap_do(Config, SCO, SCRPM, SCRFSD) || SCO <-[true,false], SCRFSD <-[1234,0], SCRPM <- [true,false]]; {SkipOs,_} -> - ?line {skipped, + {skipped, lists:flatten(["Not run on " | io_lib:format("~p",[SkipOs])])} end. @@ -185,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), @@ -266,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) -> @@ -338,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 @@ -348,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. @@ -373,16 +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). + test_server:stop_node(Node). free_memory() -> %% Free memory in MB. @@ -401,6 +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/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 499b05d658..07dfeb6633 100644 --- a/erts/emulator/test/beam_SUITE.erl +++ b/erts/emulator/test/beam_SUITE.erl @@ -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 29c6a5c7ac..b013ff5fbb 100644 --- a/erts/emulator/test/beam_literals_SUITE.erl +++ b/erts/emulator/test/beam_literals_SUITE.erl @@ -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 9bba5387fa..43d00e699a 100644 --- a/erts/emulator/test/bif_SUITE.erl +++ b/erts/emulator/test/bif_SUITE.erl @@ -23,9 +23,7 @@ -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, @@ -35,7 +33,9 @@ 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, @@ -45,35 +45,7 @@ all() -> atom_to_binary, binary_to_atom, binary_to_existing_atom, 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, @@ -118,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) -> @@ -142,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) -> @@ -163,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) -> @@ -203,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 @@ -217,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) -> @@ -239,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. @@ -277,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}) -> @@ -337,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]. @@ -356,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), @@ -397,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). @@ -424,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) -> @@ -456,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) -> @@ -519,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. @@ -574,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) -> @@ -608,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), diff --git a/erts/emulator/test/big_SUITE.erl b/erts/emulator/test/big_SUITE.erl index bb77235253..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("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 c5e3226a13..fcd49e43d3 100644 --- a/erts/emulator/test/binary_SUITE.erl +++ b/erts/emulator/test/binary_SUITE.erl @@ -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}])). @@ -582,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) -> @@ -617,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>>)), @@ -668,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 @@ -676,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, @@ -724,7 +714,7 @@ otp_5484(Config) when is_list(Config) -> 255, 106>>)), - ?line {'EXIT',_} = + {'EXIT',_} = (catch binary_to_term_stress( <<131, @@ -736,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. @@ -754,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. @@ -765,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. @@ -777,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. @@ -791,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 @@ -839,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) -> @@ -862,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) -> @@ -883,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 @@ -903,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 = @@ -911,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) -> @@ -936,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)], @@ -946,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]), @@ -971,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. @@ -1031,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. @@ -1217,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. @@ -1236,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) -> @@ -1278,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. @@ -1311,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. @@ -1517,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}]}]), @@ -1559,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. diff --git a/erts/emulator/test/bs_bit_binaries_SUITE.erl b/erts/emulator/test/bs_bit_binaries_SUITE.erl index 0896fad8ed..dd056d10af 100644 --- a/erts/emulator/test/bs_bit_binaries_SUITE.erl +++ b/erts/emulator/test/bs_bit_binaries_SUITE.erl @@ -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 1fa7353252..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, @@ -33,7 +32,9 @@ -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 2185e43498..6f7abf8c4e 100644 --- a/erts/emulator/test/bs_match_bin_SUITE.erl +++ b/erts/emulator/test/bs_match_bin_SUITE.erl @@ -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 48c2b4644e..42d692c1ba 100644 --- a/erts/emulator/test/bs_match_int_SUITE.erl +++ b/erts/emulator/test/bs_match_int_SUITE.erl @@ -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 b161d9544e..114d7ecb36 100644 --- a/erts/emulator/test/bs_match_misc_SUITE.erl +++ b/erts/emulator/test/bs_match_misc_SUITE.erl @@ -19,8 +19,7 @@ %% -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, @@ -29,7 +28,9 @@ -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 baa86e6d4a..8392a0df47 100644 --- a/erts/emulator/test/bs_match_tail_SUITE.erl +++ b/erts/emulator/test/bs_match_tail_SUITE.erl @@ -21,8 +21,8 @@ -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("common_test/include/ct.hrl"). @@ -31,51 +31,36 @@ 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 91e4e30dd2..f1c09bfbb0 100644 --- a/erts/emulator/test/bs_utf_SUITE.erl +++ b/erts/emulator/test/bs_utf_SUITE.erl @@ -20,9 +20,7 @@ -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, @@ -30,42 +28,20 @@ -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 0e81141907..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, @@ -34,7 +33,9 @@ %% 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 b9f8fe52f3..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("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 3d2cc000a8..db285a3977 100644 --- a/erts/emulator/test/code_SUITE.erl +++ b/erts/emulator/test/code_SUITE.erl @@ -19,14 +19,13 @@ %% -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). @@ -41,9 +40,6 @@ all() -> constant_pools, constant_refc_binaries, false_dependency, coverage, fun_confusion, t_copy_literals]. -groups() -> - []. - init_per_suite(Config) -> erts_debug:set_internal_state(available_internal_state, true), Config. @@ -52,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), @@ -78,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), @@ -89,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, []). @@ -174,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() -> @@ -239,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) -> @@ -303,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), - ?line false = erlang:check_old_code(my_code_test), + false = 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), + {ok,my_code_test,Code} = compile:file(File, [binary]), + {module,my_code_test} = code:load_binary(my_code_test, File, Code), - ?line true = erlang:purge_module(my_code_test), - ?line true = erlang:delete_module(my_code_test), - ?line true = erlang:purge_module(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), + + true = erlang:purge_module(my_code_test), + true = erlang:delete_module(my_code_test), + 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. @@ -393,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) -> @@ -501,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) -> @@ -512,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) -> @@ -530,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]), @@ -555,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; @@ -587,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. @@ -607,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. @@ -626,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, @@ -757,7 +746,7 @@ compile_load(Mod, Src, Ver) -> t_copy_literals(Config) when is_list(Config) -> %% 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]), {module,literals} = erlang:load_module(literals, Code), diff --git a/erts/emulator/test/code_parallel_load_SUITE.erl b/erts/emulator/test/code_parallel_load_SUITE.erl index 3998d27d04..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"). -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 41fe6a226c..6212997272 100644 --- a/erts/emulator/test/crypto_SUITE.erl +++ b/erts/emulator/test/crypto_SUITE.erl @@ -22,63 +22,42 @@ -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 7ff727bcf5..6982178827 100644 --- a/erts/emulator/test/ddll_SUITE.erl +++ b/erts/emulator/test/ddll_SUITE.erl @@ -31,21 +31,20 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --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]). @@ -54,7 +53,9 @@ -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 58a8d390f0..ad592f7147 100644 --- a/erts/emulator/test/decode_packet_SUITE.erl +++ b/erts/emulator/test/decode_packet_SUITE.erl @@ -24,13 +24,14 @@ -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,66 +40,49 @@ 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) -> rand:seed(exsplus), io:format("*** SEED: ~p ***\n", [rand:export_seed()]), - Dog=?t:timetrap(?t:minutes(1)), - [{watchdog, Dog}|Config]. + Config. -end_per_testcase(_Func, Config) -> - Dog=?config(watchdog, Config), - ?t:timetrap_cancel(Dog). +end_per_testcase(_Func, _Config) -> + ok. -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)). @@ -107,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), @@ -149,28 +133,28 @@ pack(4,Bin) -> {<<Psz:32,Bin/binary>>, Bin}; pack(asn1,Bin) -> 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, + 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 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, + 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">>, @@ -179,9 +163,9 @@ pack(cdr,Bin) -> MType = rand:uniform(256) - 1, Psz = byte_size(Bin), 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, + 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, @@ -191,10 +175,10 @@ pack(fcgi,Bin) -> Psz = byte_size(Bin), Reserv = rand:uniform(256) - 1, Padd = case PaddSz of - 0 -> <<>>; - _ -> list_to_binary([rand: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) -> @@ -205,155 +189,149 @@ pack(tpkt,Bin) -> {Res, Res}; pack(ssl_tls,Bin) -> Content = case (rand:uniform(256) - 1) of - C when C<128 -> C; - _ -> v2hello - end, + 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) -> @@ -364,8 +342,8 @@ 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 = rand:uniform(64), @@ -375,77 +353,77 @@ http_do({Bin,[{_Line,PL,PB}|Tail]}, Type) -> 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}. @@ -486,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, @@ -547,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. @@ -568,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">>, []), @@ -584,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: /", @@ -593,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 7a33dbbb36..f116ec979b 100644 --- a/erts/emulator/test/distribution_SUITE.erl +++ b/erts/emulator/test/distribution_SUITE.erl @@ -35,39 +35,38 @@ -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, - 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]). +-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,81 +89,55 @@ 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), - {comment, integer_to_list(trunc(Size/1024/Elapsed+0.5)) ++ " K/s"}. + 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) -> {Rate1, MonitorCount1} = bulk_sendsend2(Terms, BinSize, 5), @@ -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 8eb555a5b7..c589470f5b 100644 --- a/erts/emulator/test/driver_SUITE.erl +++ b/erts/emulator/test/driver_SUITE.erl @@ -29,60 +29,60 @@ -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]). @@ -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. @@ -225,94 +225,93 @@ outputv_errors_1(Term) -> build_iolist(N, Base) when N < 16 -> case rand:uniform(3) of - 1 -> - <<Bin:N/binary,_/binary>> = Base, - Bin; - _ -> - lists:seq(1, N) + 1 -> + <<Bin:N/binary,_/binary>> = Base, + Bin; + _ -> + lists:seq(1, N) end; build_iolist(N, Base) when N =< byte_size(Base) -> 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 + 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 = 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,716 +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 = "all memory", - ?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. + [{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. 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) -> @@ -2140,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}]), @@ -2150,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, @@ -2172,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, @@ -2194,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), @@ -2215,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), @@ -2238,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]), @@ -2282,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]), @@ -2329,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() -> @@ -2354,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. @@ -2367,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(). @@ -2396,7 +2293,7 @@ z_test(Config) when is_list(Config) -> check_io_debug() -> get_stable_check_io_info(), {NoErrorFds, NoUsedFds, NoDrvSelStructs, NoDrvEvStructs} = CheckIoDebug - = erts_debug:get_internal_state(check_io_debug), + = erts_debug:get_internal_state(check_io_debug), HasGetHost = has_gethost(), ct:log("check_io_debug: ~p~n" "HasGetHost: ~p",[CheckIoDebug, HasGetHost]), @@ -2438,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) -> @@ -2488,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. @@ -2534,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 @@ -2542,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() -> @@ -2581,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 cb26e8e736..cefa35a3ee 100644 --- a/erts/emulator/test/efile_SUITE.erl +++ b/erts/emulator/test/efile_SUITE.erl @@ -18,8 +18,7 @@ %% %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]). @@ -31,21 +30,6 @@ 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/erl_drv_thread_SUITE.erl b/erts/emulator/test/erl_drv_thread_SUITE.erl index 26d00db7c0..41a761229c 100644 --- a/erts/emulator/test/erl_drv_thread_SUITE.erl +++ b/erts/emulator/test/erl_drv_thread_SUITE.erl @@ -20,8 +20,7 @@ -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]). @@ -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 56b2c9c6ee..56fdfc35c0 100644 --- a/erts/emulator/test/erl_link_SUITE.erl +++ b/erts/emulator/test/erl_link_SUITE.erl @@ -31,22 +31,21 @@ %-define(line_trace, 1). -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 440a7950a6..e757ebdb3d 100644 --- a/erts/emulator/test/erts_debug_SUITE.erl +++ b/erts/emulator/test/erts_debug_SUITE.erl @@ -21,41 +21,17 @@ -module(erts_debug_SUITE). -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, 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, term_type]. -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(Config) when is_list(Config) -> ConsCell1 = id([a|b]), ConsCell2 = id(ConsCell1), @@ -181,7 +157,7 @@ term_type(Config) when is_list(Config) -> 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 7be55eca8d..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, @@ -49,9 +48,6 @@ -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, @@ -382,11 +354,11 @@ apply_micro(M) -> {weight_percentage, M#micro.weight}, {loops, M#micro.loops}, {microsecs,MicroSecs}, - {estones, (M#micro.weight * M#micro.weight * ?STONEFACTOR) div MicroSecs}, + {estones, (M#micro.weight * M#micro.weight * ?STONEFACTOR) div max(1,MicroSecs)}, {gcs, GC1 - GC0}, {kilo_word_reclaimed, (Words1 - Words0) div 1000}, {kilo_reductions, Reds div 1000}, - {gc_intensity, gci(Elapsed, GC1 - GC0, Words1 - Words0)}]. + {gc_intensity, gci(max(1,Elapsed), GC1 - GC0, Words1 - Words0)}]. monotonic_time() -> try erlang:monotonic_time() catch error:undef -> erlang:now() end. @@ -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 77ee2128b6..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 - ]). +-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]}]. +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,7 +353,7 @@ my_appender_1(N, T0) -> U = rnd_term(), T = [U|T0], my_appender_1(N-1, T). - + seed() -> rand:seed(exsplus, {3172,9815,20129}). @@ -388,4 +361,3 @@ rnd_term() -> 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 57ce8fb879..1cad7e7920 100644 --- a/erts/emulator/test/exception_SUITE.erl +++ b/erts/emulator/test/exception_SUITE.erl @@ -20,11 +20,10 @@ -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]). @@ -32,55 +31,41 @@ -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 bf557f2bca..78dec8c725 100644 --- a/erts/emulator/test/float_SUITE.erl +++ b/erts/emulator/test/float_SUITE.erl @@ -22,64 +22,38 @@ -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, +-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]). + 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 - ]. + ,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, @@ -87,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. @@ -103,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) -> @@ -174,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. @@ -187,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; @@ -240,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 @@ -318,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) -> @@ -354,17 +328,15 @@ arith(_Config) -> 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"} - ], + 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). @@ -375,21 +347,21 @@ foreach_pair(F, 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, + 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]). + [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 + _ when A + B =:= element(1,R) -> ok; + {{'EXIT',badarith}, Info} -> ok end. op_sub(A, B) -> @@ -397,8 +369,8 @@ op_sub(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 + _ when A - B =:= element(1,R) -> ok; + {{'EXIT',badarith}, Info} -> ok end. op_mul(A, B) -> @@ -406,8 +378,8 @@ op_mul(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 + _ when A * B =:= element(1,R) -> ok; + {{'EXIT',badarith}, Info} -> ok end. op_div(A, B) -> @@ -415,8 +387,8 @@ op_div(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 + _ when A / B =:= element(1,R) -> ok; + {{'EXIT',badarith}, Info} -> ok end. my_apply(M, F, A) -> @@ -433,7 +405,7 @@ unify(Other, Info) -> -define(epsilon, 1.0e-20). check_epsilon(R,Val) -> if erlang:abs(R-Val) < ?epsilon -> ok; - true -> ?t:fail({R,Val}) + true -> ct:fail({R,Val}) end. t_mul_add_ops(Config) when is_list(Config) -> diff --git a/erts/emulator/test/fun_SUITE.erl b/erts/emulator/test/fun_SUITE.erl index 6697a86fc5..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, @@ -37,7 +33,10 @@ -include_lib("common_test/include/ct.hrl"). -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap, {minutes, 1}}]. + 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 39e8b3c324..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("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 cb000fd45f..8e5f0b05a1 100644 --- a/erts/emulator/test/gc_SUITE.erl +++ b/erts/emulator/test/gc_SUITE.erl @@ -23,44 +23,26 @@ -module(gc_SUITE). -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]). - --define(default_timeout, ?t:minutes(10)). +-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 2e03983c4f..6ad4456e6b 100644 --- a/erts/emulator/test/guard_SUITE.erl +++ b/erts/emulator/test/guard_SUITE.erl @@ -20,8 +20,8 @@ -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]). @@ -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 31b10158fb..be254f5543 100644 --- a/erts/emulator/test/hash_SUITE.erl +++ b/erts/emulator/test/hash_SUITE.erl @@ -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(). diff --git a/erts/emulator/test/hibernate_SUITE.erl b/erts/emulator/test/hibernate_SUITE.erl index 5138a6ee05..45f0bdc4da 100644 --- a/erts/emulator/test/hibernate_SUITE.erl +++ b/erts/emulator/test/hibernate_SUITE.erl @@ -22,45 +22,23 @@ -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 e40b91392c..7373303a39 100644 --- a/erts/emulator/test/ignore_cores.erl +++ b/erts/emulator/test/ignore_cores.erl @@ -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 544f9c9c1f..1f64a6a8e5 100644 --- a/erts/emulator/test/list_bif_SUITE.erl +++ b/erts/emulator/test/list_bif_SUITE.erl @@ -21,147 +21,106 @@ -module(list_bif_SUITE). -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 5e9814be60..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 @@ -1707,7 +1694,6 @@ term_gen_recursive(Leafs, Flags, Depth) -> {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()}, @@ -1735,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) -> @@ -2993,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), @@ -3013,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() @@ -3031,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 9e724bdd8c..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, @@ -41,18 +40,9 @@ -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 index 96c41a57b5..12c42d24aa 100644 --- a/erts/emulator/test/message_queue_data_SUITE.erl +++ b/erts/emulator/test/message_queue_data_SUITE.erl @@ -20,46 +20,20 @@ -module(message_queue_data_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([basic/1, process_info_messages/1]). -export([basic_test/1]). -include_lib("common_test/include/ct.hrl"). -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, 2}}]. all() -> [basic, process_info_messages]. -groups() -> - []. - -init_per_suite(Config) -> -%% erts_debug:set_internal_state(available_internal_state, true), - Config. - -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. - %% %% %% Test cases @@ -228,12 +202,12 @@ 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(?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) -> - ?t: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 c622a2d8d7..f8208c5866 100644 --- a/erts/emulator/test/module_info_SUITE.erl +++ b/erts/emulator/test/module_info_SUITE.erl @@ -22,9 +22,7 @@ -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 8101908df1..82e3a36c1e 100644 --- a/erts/emulator/test/monitor_SUITE.erl +++ b/erts/emulator/test/monitor_SUITE.erl @@ -22,19 +22,18 @@ -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/nested_SUITE.erl b/erts/emulator/test/nested_SUITE.erl index ee6bbf6a55..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("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 7ce37b04b3..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("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,7 +1151,7 @@ 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 @@ -1196,10 +1159,10 @@ send3(Config) when is_list(Config) -> 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). @@ -1233,7 +1196,7 @@ send3_controller(SpawnCnt0, Mons0, Pids0, Tick) -> 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; @@ -1259,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); @@ -1344,98 +1307,98 @@ send3_new_state(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, [1,2|3]). + 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(), @@ -1445,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) -> @@ -1470,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 @@ -1539,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), @@ -1596,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) -> @@ -1637,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 @@ -1650,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 @@ -1674,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 @@ -1689,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. @@ -1711,7 +1673,9 @@ tmpmem() -> false -> undefined; MemInfo -> MSBCS = lists:foldl( - fun ({instance, _, L}, Acc) -> + fun ({instance, 0, _}, Acc) -> + Acc; % Ignore instance 0 + ({instance, _, L}, Acc) -> {value,{_,MBCS}} = lists:keysearch(mbcs, 1, L), {value,{_,SBCS}} = lists:keysearch(sbcs, 1, L), [MBCS,SBCS | Acc] @@ -1739,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) -> @@ -1769,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]). @@ -1805,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). @@ -1825,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). @@ -1852,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) -> @@ -1918,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. diff --git a/erts/emulator/test/nif_SUITE_data/nif_mod.erl b/erts/emulator/test/nif_SUITE_data/nif_mod.erl index aa3c90fe9d..b6de046388 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_mod.erl +++ b/erts/emulator/test/nif_SUITE_data/nif_mod.erl @@ -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 32b9ef1826..f955f99c9a 100644 --- a/erts/emulator/test/nif_SUITE_data/tester.erl +++ b/erts/emulator/test/nif_SUITE_data/tester.erl @@ -4,9 +4,8 @@ -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 dcd0428e65..71400142af 100644 --- a/erts/emulator/test/node_container_SUITE.erl +++ b/erts/emulator/test/node_container_SUITE.erl @@ -32,33 +32,32 @@ -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 caa2d30a6c..9cc851f9cf 100644 --- a/erts/emulator/test/nofrag_SUITE.erl +++ b/erts/emulator/test/nofrag_SUITE.erl @@ -22,55 +22,31 @@ -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/old_mod.erl b/erts/emulator/test/old_mod.erl index e714a75954..0da40ec430 100644 --- a/erts/emulator/test/old_mod.erl +++ b/erts/emulator/test/old_mod.erl @@ -30,19 +30,19 @@ sorter(Receiver, Ref, 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 272131cb46..9d40417d0a 100644 --- a/erts/emulator/test/old_scheduler_SUITE.erl +++ b/erts/emulator/test/old_scheduler_SUITE.erl @@ -22,41 +22,25 @@ -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 4e15b27231..562cf1c92d 100644 --- a/erts/emulator/test/op_SUITE.erl +++ b/erts/emulator/test/op_SUITE.erl @@ -22,66 +22,42 @@ -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,52 +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), + 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), + 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), @@ -146,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. @@ -155,35 +131,35 @@ cmp_emu(A,B) -> A > B -> +1; true -> 0 end. - + make_rand_term(1) -> make_rand_term_single(); make_rand_term(Arity) -> 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)] + 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 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 -> [] + 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) -> @@ -196,7 +172,7 @@ 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}; @@ -219,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. @@ -318,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), @@ -356,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}, @@ -367,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 5274da301a..328641f5b9 100644 --- a/erts/emulator/test/port_SUITE.erl +++ b/erts/emulator/test/port_SUITE.erl @@ -74,26 +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, +-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]). + 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]). @@ -105,7 +105,9 @@ -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, @@ -127,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]. @@ -155,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). @@ -225,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 @@ -248,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), @@ -266,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) -> []; @@ -288,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), @@ -296,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 @@ -315,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]), @@ -326,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}, []), @@ -348,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]), @@ -366,26 +339,24 @@ 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"), @@ -399,8 +370,6 @@ output_only(Config) when is_list(Config) -> %% Then we test that any writes to stdout from %% the port program is not sent to erlang output_and_verify(Config, ["-h0"], Data), - - test_server:timetrap_cancel(Dog), ok. output_and_verify(Config, Options, Data) -> @@ -421,11 +390,10 @@ output_and_verify(Config, 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 @@ -434,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 @@ -444,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([]) -> @@ -472,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), @@ -504,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) -> @@ -530,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), @@ -553,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", @@ -567,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. @@ -585,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. @@ -613,12 +570,9 @@ 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(suite) -> []; count_fds(Config) when is_list(Config) -> case os:type() of {unix, _} -> @@ -637,9 +591,9 @@ count_fds(Config) when is_list(Config) -> {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]), + <<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]), @@ -654,7 +608,6 @@ count_fds(Config) when is_list(Config) -> %% 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 @@ -663,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 -> @@ -711,8 +663,8 @@ max_ports(Command) -> close_ports([P|Ps]) -> P ! {self(), close}, receive - {P,closed} -> - ok + {P,closed} -> + ok end, close_ports(Ps); close_ports([]) -> @@ -730,36 +682,35 @@ open_ports(Name, Settings) -> 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) -> @@ -768,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", @@ -889,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) -> @@ -926,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(). @@ -968,23 +903,24 @@ 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; - _ -> + {win32,_} -> 500; + _ -> %% We create a huge environment, %% 20000 variables is about 25MB %% which seems to be the limit on Linux. 20000 - end, + 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], + $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 @@ -998,9 +934,9 @@ huge_env(Config) when is_list(Config) -> 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]) + %% 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. @@ -1008,56 +944,52 @@ huge_env(Config) when is_list(Config) -> %% '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([], []) -> @@ -1068,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 -> @@ -1079,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). @@ -1102,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 - "<" -> "<" ++ otp_3906_htmlize(Cs); - ">" -> ">" ++ otp_3906_htmlize(Cs); - _ -> [C | otp_3906_htmlize(Cs)] + "<" -> "<" ++ otp_3906_htmlize(Cs); + ">" -> ">" ++ otp_3906_htmlize(Cs); + _ -> [C | otp_3906_htmlize(Cs)] end. otp_3906_make_prog(CC, PrivDir) -> @@ -1186,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. @@ -1199,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([], _) -> @@ -1223,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) -> @@ -1252,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), @@ -1272,185 +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; - 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,[]))), - 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,[]), @@ -1460,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])), @@ -1489,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])), @@ -1524,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) -> @@ -1566,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. @@ -1596,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) -> @@ -1638,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). @@ -1646,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}, @@ -1662,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; @@ -1677,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) -> @@ -1733,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(). @@ -1866,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) -> %% @@ -1898,133 +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; - Err == enomem -> - noop; - {'EXIT', Err} when Err == eagain; - Err == emfile; - Err == enomem -> - 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) -> @@ -2033,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) @@ -2058,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]); @@ -2081,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), @@ -2100,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(_, [], _) -> @@ -2132,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, []) -> @@ -2174,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); @@ -2208,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)]); @@ -2238,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(), []). @@ -2270,11 +2154,11 @@ random_char(Chars) -> uniform(N) -> case rand:export_seed() of - undefined -> - rand:seed(exsplus), - io:format("Random seed = ~p\n", [rand:export_seed()]); - _ -> - ok + undefined -> + rand:seed(exsplus), + io:format("Random seed = ~p\n", [rand:export_seed()]); + _ -> + ok end, rand:uniform(N). @@ -2285,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 @@ -2318,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), @@ -2330,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!?!?"), @@ -2410,7 +2291,6 @@ 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, _) -> @@ -2418,75 +2298,75 @@ close_deaf_port_1(200, _) -> close_deaf_port_1(N, Cmd) -> 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 = 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_bif_SUITE.erl b/erts/emulator/test/port_bif_SUITE.erl index 9215d7f720..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"). -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"). diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl index 862fe78b85..5bb216ff79 100644 --- a/erts/emulator/test/process_SUITE.erl +++ b/erts/emulator/test/process_SUITE.erl @@ -67,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}, @@ -116,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. @@ -128,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, []]). @@ -158,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. @@ -176,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. @@ -194,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. @@ -240,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 @@ -251,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. @@ -260,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. @@ -288,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) -> @@ -320,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() -> @@ -332,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. @@ -345,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. @@ -364,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) -> @@ -397,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) -> @@ -412,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() -> @@ -669,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()), @@ -705,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. @@ -741,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) -> @@ -750,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 () -> @@ -809,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. @@ -843,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) -> @@ -987,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 @@ -1077,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) -> @@ -1119,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() -> @@ -1156,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(), @@ -1208,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), @@ -1249,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(), @@ -1289,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. @@ -1350,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), @@ -1371,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 () -> @@ -1439,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). @@ -1470,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, @@ -1488,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). @@ -1506,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, []), @@ -1518,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 @@ -1535,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, @@ -1546,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" @@ -1587,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 @@ -1597,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 @@ -1606,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 @@ -1711,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, @@ -1753,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 -> @@ -1774,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(), @@ -1829,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. @@ -1860,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() -> @@ -1868,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 -> @@ -1884,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, @@ -1910,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), @@ -1928,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(), @@ -1970,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 @@ -1985,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 @@ -1999,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), @@ -2152,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). @@ -2238,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. @@ -2326,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, @@ -2435,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, @@ -2505,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/receive_SUITE.erl b/erts/emulator/test/receive_SUITE.erl index 635c3d27c5..6097e54219 100644 --- a/erts/emulator/test/receive_SUITE.erl +++ b/erts/emulator/test/receive_SUITE.erl @@ -24,13 +24,12 @@ -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 6d4a998094..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("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 53bf02e085..ad8a9c29f3 100644 --- a/erts/emulator/test/register_SUITE.erl +++ b/erts/emulator/test/register_SUITE.erl @@ -26,44 +26,17 @@ -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 b40a5f0a56..bbdc2e6688 100644 --- a/erts/emulator/test/save_calls_SUITE.erl +++ b/erts/emulator/test/save_calls_SUITE.erl @@ -22,10 +22,7 @@ -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. @@ -196,18 +175,18 @@ 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 -> @@ -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 1f284228db..64c280b198 100644 --- a/erts/emulator/test/scheduler_SUITE.erl +++ b/erts/emulator/test/scheduler_SUITE.erl @@ -34,9 +34,9 @@ -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,24 @@ 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, + equal_with_high_max, + bound_process, + {group, scheduler_bind}, scheduler_threads, + scheduler_suspend_basic, scheduler_suspend, dirty_scheduler_threads, dirty_scheduler_exit, reader_groups]. @@ -86,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 -> @@ -103,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)). @@ -131,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, _) -> @@ -488,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, @@ -569,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 @@ -837,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)]) @@ -884,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 @@ -928,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}, @@ -966,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 -> @@ -989,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, @@ -1006,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), @@ -1131,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, @@ -1139,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. @@ -1180,7 +1175,7 @@ dirty_scheduler_exit_test(Config) -> {ok, Node} = start_node(Config, "+SDio 1"), [ok] = mcall(Node, [fun() -> - Path = ?config(data_dir, Config), + 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() @@ -1214,49 +1209,161 @@ wait_dse([Pid|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) -> @@ -1320,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) -> @@ -1598,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}. @@ -1616,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". @@ -1654,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, []) -> []; @@ -1759,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 @@ -1884,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; @@ -1955,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() -> @@ -2079,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() -> @@ -2099,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). @@ -2111,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/send_term_SUITE.erl b/erts/emulator/test/send_term_SUITE.erl index 63c11519b8..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("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 29517cdcb8..e2236774a7 100644 --- a/erts/emulator/test/sensitive_SUITE.erl +++ b/erts/emulator/test/sensitive_SUITE.erl @@ -22,26 +22,18 @@ -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 e176fe52d6..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("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]). +-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 2df19cd20b..900dd124c0 100644 --- a/erts/emulator/test/smoke_test_SUITE.erl +++ b/erts/emulator/test/smoke_test_SUITE.erl @@ -23,35 +23,18 @@ -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 df96b018a1..7d5b07f21f 100644 --- a/erts/emulator/test/statistics_SUITE.erl +++ b/erts/emulator/test/statistics_SUITE.erl @@ -22,10 +22,7 @@ %% 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, @@ -40,16 +37,9 @@ -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, @@ -65,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. @@ -128,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. @@ -203,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), @@ -219,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. @@ -234,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() -> @@ -367,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), @@ -465,15 +425,14 @@ 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. -msacc(doc) -> - "Tests that statistics(microstate_statistics) works."; +%% Tests that statistics(microstate_statistics) works. msacc(Config) -> %% Test if crypto nif is available @@ -499,9 +458,9 @@ msacc(Config) -> end, maps:to_list(msacc_sum_states())) ), if Sum > 0 -> - ok; + ok; true -> - ct:fail({no_states_triggered, MsaccStats}) + ct:fail({no_states_triggered, MsaccStats}) end; _ -> @@ -517,7 +476,7 @@ msacc(Config) -> %% 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 + erlang:system_info(thread_pool_size) > 0 of false -> ok; @@ -581,4 +540,4 @@ msacc_sum_states() -> NewValue = Value+maps:get(Key,Acc), maps:update(Key, NewValue, Acc) end, Cnt, Counters) - end,InitialCounters,Stats). + end,InitialCounters,Stats). diff --git a/erts/emulator/test/system_info_SUITE.erl b/erts/emulator/test/system_info_SUITE.erl index ae18b280cf..ffea5bc15b 100644 --- a/erts/emulator/test/system_info_SUITE.erl +++ b/erts/emulator/test/system_info_SUITE.erl @@ -33,53 +33,23 @@ -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,43 +113,34 @@ 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"}; @@ -189,7 +150,7 @@ wordsize(Config) when is_list(Config) -> 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 @@ -244,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), @@ -253,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, @@ -277,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, @@ -289,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"), @@ -299,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, @@ -308,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, @@ -317,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, @@ -341,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"), @@ -350,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, @@ -359,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"), @@ -371,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) -> @@ -390,8 +338,7 @@ memory_test(_Config) -> receive {'DOWN', Mon, _, _, _} -> ok end - end, - MWs), + end, MWs), ok. mem_worker() -> @@ -406,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)). @@ -434,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; @@ -502,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. @@ -529,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)), @@ -565,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 c63a119f9d..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("common_test/include/ct.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. - -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. diff --git a/erts/emulator/test/time_SUITE.erl b/erts/emulator/test/time_SUITE.erl index f6f99a0c81..e6da5e89fa 100644 --- a/erts/emulator/test/time_SUITE.erl +++ b/erts/emulator/test/time_SUITE.erl @@ -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. @@ -781,15 +772,15 @@ chk_random_values(FR, TR) -> 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 -> - ?t:fail({Failure, CV, V, FR, TR}) - end - end, + 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). @@ -801,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 -> @@ -811,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) -> @@ -845,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) -> @@ -874,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. @@ -921,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). @@ -935,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([], _) -> []. @@ -952,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([], _) -> []. @@ -1045,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 f4615d6810..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, @@ -40,16 +39,13 @@ -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 02c2c7a93a..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, @@ -43,7 +43,9 @@ %%% 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)), + ct:timetrap({minutes, 2}), rand:seed(exsplus, {4711,17,4711}), - ?line do_suspend_exit(5000), - ?line test_server:timetrap_cancel(Dog), - ?line ok. + do_suspend_exit(5000), + ok. do_suspend_exit(0) -> - ?line ok; + ok; do_suspend_exit(N) -> Work = rand: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). - - - - + 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 ae98cc7189..b774210456 100644 --- a/erts/emulator/test/trace_bif_SUITE.erl +++ b/erts/emulator/test/trace_bif_SUITE.erl @@ -22,8 +22,7 @@ -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 e358791f1f..c849668e84 100644 --- a/erts/emulator/test/trace_call_count_SUITE.erl +++ b/erts/emulator/test/trace_call_count_SUITE.erl @@ -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 a802aa12b8..38972c9c02 100644 --- a/erts/emulator/test/trace_call_time_SUITE.erl +++ b/erts/emulator/test/trace_call_time_SUITE.erl @@ -61,29 +61,27 @@ -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 503a773545..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("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 8f732f0a5f..dcc2cc807b 100644 --- a/erts/emulator/test/trace_meta_SUITE.erl +++ b/erts/emulator/test/trace_meta_SUITE.erl @@ -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 3ac891b1dd..49757a414d 100644 --- a/erts/emulator/test/trace_nif_SUITE.erl +++ b/erts/emulator/test/trace_nif_SUITE.erl @@ -22,8 +22,7 @@ -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 b169a264be..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, @@ -40,7 +38,11 @@ -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 2c2f93e7ee..d59d7d12d3 100644 --- a/erts/emulator/test/tuple_SUITE.erl +++ b/erts/emulator/test/tuple_SUITE.erl @@ -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 bbbcf3fa2a..e8537e6152 100644 --- a/erts/emulator/test/unique_SUITE.erl +++ b/erts/emulator/test/unique_SUITE.erl @@ -20,9 +20,7 @@ -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]). @@ -33,25 +31,14 @@ -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 @@ -270,12 +251,12 @@ calc_sched_bits(NoScheds, Shift) -> schedulers() -> S = erlang:system_info(schedulers), try - DCPUS = erlang:system_info(dirty_cpu_schedulers), - DIOS = erlang:system_info(dirty_io_schedulers), - S+DCPUS+DIOS + DCPUS = erlang:system_info(dirty_cpu_schedulers), + DIOS = erlang:system_info(dirty_io_schedulers), + S+DCPUS+DIOS catch - _ : _ -> - S + _ : _ -> + S end. init_uniqint_info() -> @@ -292,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) -> @@ -329,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), @@ -345,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 Int=~p FAILED~n", [Int]), - 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 @@ -386,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 0037a9a477..93a03e8f91 100644 --- a/erts/emulator/test/z_SUITE.erl +++ b/erts/emulator/test/z_SUITE.erl @@ -32,146 +32,115 @@ -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,66 +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), + 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, - ?line case InitPollsetSize =:= FinPollsetSize of + 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 -> @@ -266,27 +225,23 @@ 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 + HasGethost), - ?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() -> @@ -309,8 +264,8 @@ check_io_debug_test() -> %% port returns an EAGAIN ok end, - ?line 0 = NoDrvEvStructs, - ?line ok. + 0 = NoDrvEvStructs, + ok. has_gethost() -> has_gethost(erlang:ports()). @@ -356,6 +311,3 @@ get_check_io_info() -> receive after 100 -> ok end, get_check_io_info() end. - - - diff --git a/erts/emulator/valgrind/suppress.patched.3.6.0 b/erts/emulator/valgrind/suppress.patched.3.6.0 index 16cecf2dba..fcde4a0123 100644 --- a/erts/emulator/valgrind/suppress.patched.3.6.0 +++ b/erts/emulator/valgrind/suppress.patched.3.6.0 @@ -368,7 +368,7 @@ Memcheck:Addr4 ... fun:erts_print_scheduler_info ... -fun:erl_exit +fun:erts_exit fun:broken_halt_test fun:erts_debug_set_internal_state_2 fun:process_main diff --git a/erts/emulator/valgrind/suppress.standard b/erts/emulator/valgrind/suppress.standard index a1f3f82364..bb07c92fc1 100644 --- a/erts/emulator/valgrind/suppress.standard +++ b/erts/emulator/valgrind/suppress.standard @@ -336,7 +336,7 @@ Memcheck:Addr4 ... fun:erts_print_scheduler_info ... -fun:erl_exit +fun:erts_exit fun:broken_halt_test fun:erts_debug_set_internal_state_2 fun:process_main diff --git a/erts/epmd/src/epmd.c b/erts/epmd/src/epmd.c index 21ce4e52b0..324ae6ac40 100644 --- a/erts/epmd/src/epmd.c +++ b/erts/epmd/src/epmd.c @@ -343,7 +343,7 @@ static void run_daemon(EpmdVars *g) for (fd = 0; fd < g->max_conn ; fd++) /* close all files ... */ close(fd); /* Syslog on linux will try to write to whatever if we dont - inform it of that the log is closed. */ + inform it that the log is closed. */ closelog(); /* These shouldn't be needed but for safety... */ diff --git a/erts/epmd/src/epmd_cli.c b/erts/epmd/src/epmd_cli.c index a8fe865d9a..6fc05e153e 100644 --- a/erts/epmd/src/epmd_cli.c +++ b/erts/epmd/src/epmd_cli.c @@ -136,19 +136,33 @@ void epmd_call(EpmdVars *g,int what) static int conn_to_epmd(EpmdVars *g) { struct EPMD_SOCKADDR_IN address; + size_t salen = 0; int connect_sock; - - connect_sock = socket(FAMILY, SOCK_STREAM, 0); - if (connect_sock<0) - goto error; + unsigned short sport = g->port; + +#if defined(EPMD6) + SET_ADDR6(address, in6addr_loopback, sport); + salen = sizeof(struct sockaddr_in6); + + connect_sock = socket(AF_INET6, SOCK_STREAM, 0); + if (connect_sock>=0) { + + if (connect(connect_sock, (struct sockaddr*)&address, salen) == 0) + return connect_sock; - { /* store port number in unsigned short */ - unsigned short sport = g->port; - SET_ADDR(address, EPMD_ADDR_LOOPBACK, sport); + close(connect_sock); } +#endif + SET_ADDR(address, htonl(INADDR_LOOPBACK), sport); + salen = sizeof(struct sockaddr_in); - if (connect(connect_sock, (struct sockaddr*)&address, sizeof address) < 0) + connect_sock = socket(AF_INET, SOCK_STREAM, 0); + if (connect_sock<0) goto error; + + if (connect(connect_sock, (struct sockaddr*)&address, salen) < 0) + goto error; + return connect_sock; error: diff --git a/erts/epmd/src/epmd_int.h b/erts/epmd/src/epmd_int.h index e222abb4b7..e127eff097 100644 --- a/erts/epmd/src/epmd_int.h +++ b/erts/epmd/src/epmd_int.h @@ -48,6 +48,7 @@ # ifndef WINDOWS_H_INCLUDES_WINSOCK2_H # include <winsock2.h> # endif +# include <ws2tcpip.h> # include <windows.h> # include <process.h> #endif @@ -114,6 +115,10 @@ # include <systemd/sd-daemon.h> #endif /* HAVE_SYSTEMD_DAEMON */ +#if defined(HAVE_IN6) && defined(AF_INET6) && defined(HAVE_INET_PTON) +# define EPMD6 +#endif + /* ************************************************************************ */ /* Replace some functions by others by making the function name a macro */ @@ -167,33 +172,53 @@ /* ************************************************************************ */ /* Macros that let us use IPv6 */ -#if defined(HAVE_IN6) && defined(AF_INET6) && defined(EPMD6) +#if HAVE_IN6 +# if ! defined(HAVE_IN6ADDR_ANY) || ! HAVE_IN6ADDR_ANY +# if HAVE_DECL_IN6ADDR_ANY_INIT +static const struct in6_addr in6addr_any = { { IN6ADDR_ANY_INIT } }; +# else +static const struct in6_addr in6addr_any = + { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } }; +# endif /* HAVE_IN6ADDR_ANY_INIT */ +# endif /* ! HAVE_DECL_IN6ADDR_ANY */ + +# if ! defined(HAVE_IN6ADDR_LOOPBACK) || ! HAVE_IN6ADDR_LOOPBACK +# if HAVE_DECL_IN6ADDR_LOOPBACK_INIT +static const struct in6_addr in6addr_loopback = + { { IN6ADDR_LOOPBACK_INIT } }; +# else +static const struct in6_addr in6addr_loopback = + { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } }; +# endif /* HAVE_IN6ADDR_LOOPBACK_INIT */ +# endif /* ! HAVE_DECL_IN6ADDR_LOOPBACK */ +#endif /* HAVE_IN6 */ + +#define IS_ADDR_LOOPBACK(addr) ((addr).s_addr == htonl(INADDR_LOOPBACK)) + +#if defined(EPMD6) -#define EPMD_SOCKADDR_IN sockaddr_in6 -#define EPMD_IN_ADDR in6_addr -#define EPMD_S_ADDR s6_addr -#define EPMD_ADDR_LOOPBACK in6addr_loopback.s6_addr -#define EPMD_ADDR_ANY in6addr_any.s6_addr +#define EPMD_SOCKADDR_IN sockaddr_storage #define FAMILY AF_INET6 -#define SET_ADDR(dst, addr, port) do { \ - memset((char*)&(dst), 0, sizeof(dst)); \ - memcpy((char*)&(dst).sin6_addr.s6_addr, (char*)&(addr), 16); \ - (dst).sin6_family = AF_INET6; \ - (dst).sin6_flowinfo = 0; \ - (dst).sin6_port = htons(port); \ +#define SET_ADDR6(dst, addr, port) do { \ + struct sockaddr_in6 *sa = (struct sockaddr_in6 *)&(dst); \ + memset(sa, 0, sizeof(dst)); \ + sa->sin6_family = AF_INET6; \ + sa->sin6_addr = (addr); \ + sa->sin6_port = htons(port); \ } while(0) -#define IS_ADDR_LOOPBACK(addr) \ - (memcmp((addr).s6_addr, in6addr_loopback.s6_addr, 16) == 0) +#define SET_ADDR(dst, addr, port) do { \ + struct sockaddr_in *sa = (struct sockaddr_in *)&(dst); \ + memset(sa, 0, sizeof(dst)); \ + sa->sin_family = AF_INET; \ + sa->sin_addr.s_addr = (addr); \ + sa->sin_port = htons(port); \ + } while(0) #else /* Not IP v6 */ #define EPMD_SOCKADDR_IN sockaddr_in -#define EPMD_IN_ADDR in_addr -#define EPMD_S_ADDR s_addr -#define EPMD_ADDR_LOOPBACK htonl(INADDR_LOOPBACK) -#define EPMD_ADDR_ANY htonl(INADDR_ANY) #define FAMILY AF_INET #define SET_ADDR(dst, addr, port) do { \ @@ -203,8 +228,6 @@ (dst).sin_port = htons(port); \ } while(0) -#define IS_ADDR_LOOPBACK(addr) ((addr).s_addr == htonl(INADDR_LOOPBACK)) - #endif /* Not IP v6 */ /* ************************************************************************ */ diff --git a/erts/epmd/src/epmd_srv.c b/erts/epmd/src/epmd_srv.c index fb8cae05df..75a33f28cb 100644 --- a/erts/epmd/src/epmd_srv.c +++ b/erts/epmd/src/epmd_srv.c @@ -71,6 +71,7 @@ static time_t current_time(EpmdVars*); static Connection *conn_init(EpmdVars*); static int conn_open(EpmdVars*,int); +static int conn_local_peer_check(EpmdVars*, int); static int conn_close_fd(EpmdVars*,int); static void node_init(EpmdVars*); @@ -201,10 +202,11 @@ void run(EpmdVars *g) { struct EPMD_SOCKADDR_IN iserv_addr[MAX_LISTEN_SOCKETS]; int listensock[MAX_LISTEN_SOCKETS]; - int num_sockets; + int num_sockets = 0; int i; int opt; unsigned short sport = g->port; + int bound = 0; node_init(g); g->conn = conn_init(g); @@ -247,64 +249,82 @@ void run(EpmdVars *g) if (g->addresses != NULL && /* String contains non-separator characters if: */ g->addresses[strspn(g->addresses," ,")] != '\000') { - char *tmp; - char *token; - int loopback_ok = 0; + char *tmp = NULL; + char *token = NULL; + + /* Always listen on the loopback. */ + SET_ADDR(iserv_addr[num_sockets],htonl(INADDR_LOOPBACK),sport); + num_sockets++; +#if defined(EPMD6) + SET_ADDR6(iserv_addr[num_sockets],in6addr_loopback,sport); + num_sockets++; +#endif - if ((tmp = (char *)malloc(strlen(g->addresses) + 1)) == NULL) + if ((tmp = strdup(g->addresses)) == NULL) { dbg_perror(g,"cannot allocate memory"); epmd_cleanup_exit(g,1); } - strcpy(tmp,g->addresses); - for(token = strtok(tmp,", "), num_sockets = 0; + for(token = strtok(tmp,", "); token != NULL; - token = strtok(NULL,", "), num_sockets++) + token = strtok(NULL,", ")) { - struct EPMD_IN_ADDR addr; -#ifdef HAVE_INET_PTON - int ret; + struct in_addr addr; +#if defined(EPMD6) + struct in6_addr addr6; + struct sockaddr_storage *sa = &iserv_addr[num_sockets]; - if ((ret = inet_pton(FAMILY,token,&addr)) == -1) + if (inet_pton(AF_INET6,token,&addr6) == 1) { - dbg_perror(g,"cannot convert IP address to network format"); - epmd_cleanup_exit(g,1); + SET_ADDR6(iserv_addr[num_sockets],addr6,sport); + } + else if (inet_pton(AF_INET,token,&addr) == 1) + { + SET_ADDR(iserv_addr[num_sockets],addr.s_addr,sport); + } + else +#else + if ((addr.s_addr = inet_addr(token)) != INADDR_NONE) + { + SET_ADDR(iserv_addr[num_sockets],addr.s_addr,sport); } - else if (ret == 0) -#elif !defined(EPMD6) - if ((addr.EPMD_S_ADDR = inet_addr(token)) == INADDR_NONE) + else #endif { dbg_tty_printf(g,0,"cannot parse IP address \"%s\"",token); epmd_cleanup_exit(g,1); } +#if defined(EPMD6) + if (sa->ss_family == AF_INET6 && IN6_IS_ADDR_LOOPBACK(&addr6)) + continue; + + if (sa->ss_family == AF_INET) +#endif if (IS_ADDR_LOOPBACK(addr)) - loopback_ok = 1; + continue; - if (num_sockets - loopback_ok == MAX_LISTEN_SOCKETS - 1) + num_sockets++; + + if (num_sockets >= MAX_LISTEN_SOCKETS) { dbg_tty_printf(g,0,"cannot listen on more than %d IP addresses", MAX_LISTEN_SOCKETS); epmd_cleanup_exit(g,1); } - - SET_ADDR(iserv_addr[num_sockets],addr.EPMD_S_ADDR,sport); } free(tmp); - - if (!loopback_ok) - { - SET_ADDR(iserv_addr[num_sockets],EPMD_ADDR_LOOPBACK,sport); - num_sockets++; - } } else { - SET_ADDR(iserv_addr[0],EPMD_ADDR_ANY,sport); - num_sockets = 1; + SET_ADDR(iserv_addr[num_sockets],htonl(INADDR_ANY),sport); + num_sockets++; +#if defined(EPMD6) + SET_ADDR6(iserv_addr[num_sockets],in6addr_any,sport); + num_sockets++; +#endif } #ifdef HAVE_SYSTEMD_DAEMON } @@ -335,13 +355,39 @@ void run(EpmdVars *g) #endif /* HAVE_SYSTEMD_DAEMON */ for (i = 0; i < num_sockets; i++) { - if ((listensock[i] = socket(FAMILY,SOCK_STREAM,0)) < 0) + struct sockaddr *sa = (struct sockaddr *)&iserv_addr[i]; +#if defined(EPMD6) + size_t salen = (sa->sa_family == AF_INET6 ? + sizeof(struct sockaddr_in6) : + sizeof(struct sockaddr_in)); +#else + size_t salen = sizeof(struct sockaddr_in); +#endif + + if ((listensock[i] = socket(sa->sa_family,SOCK_STREAM,0)) < 0) { - dbg_perror(g,"error opening stream socket"); + switch (errno) { + case EAFNOSUPPORT: + case EPROTONOSUPPORT: + continue; + default: + dbg_perror(g,"error opening stream socket"); + epmd_cleanup_exit(g,1); + } + } + g->listenfd[bound++] = listensock[i]; + +#if HAVE_DECL_IPV6_V6ONLY + opt = 1; + if (sa->sa_family == AF_INET6 && + setsockopt(listensock[i],IPPROTO_IPV6,IPV6_V6ONLY,&opt, + sizeof(opt)) <0) + { + dbg_perror(g,"can't set IPv6 only socket option"); epmd_cleanup_exit(g,1); } - g->listenfd[i] = listensock[i]; - +#endif + /* * Note that we must not enable the SO_REUSEADDR on Windows, * because addresses will be reused even if they are still in use. @@ -373,8 +419,7 @@ void run(EpmdVars *g) dbg_perror(g,"failed to set non-blocking mode of listening socket %d", listensock[i]); - if (bind(listensock[i], (struct sockaddr*) &iserv_addr[i], - sizeof(iserv_addr[i])) < 0) + if (bind(listensock[i], (struct sockaddr*) &iserv_addr[i], salen) < 0) { if (errno == EADDRINUSE) { @@ -395,6 +440,11 @@ void run(EpmdVars *g) } select_fd_set(g, listensock[i]); } + if (bound == 0) { + dbg_perror(g,"unable to bind any address"); + epmd_cleanup_exit(g,1); + } + num_sockets = bound; #ifdef HAVE_SYSTEMD_DAEMON } sd_notifyf(0, "READY=1\n" @@ -439,8 +489,8 @@ void run(EpmdVars *g) } for (i = 0; i < num_sockets; i++) - if (FD_ISSET(listensock[i],&read_mask)) { - if (do_accept(g, listensock[i]) && g->active_conn < g->max_conn) { + if (FD_ISSET(g->listenfd[i],&read_mask)) { + if (do_accept(g, g->listenfd[i]) && g->active_conn < g->max_conn) { /* * The accept() succeeded, and we have at least one file * descriptor still free, which means that another accept() @@ -1000,15 +1050,6 @@ static int conn_open(EpmdVars *g,int fd) for (i = 0; i < g->max_conn; i++) { if (g->conn[i].open == EPMD_FALSE) { - struct sockaddr_in si; - struct sockaddr_in di; -#ifdef HAVE_SOCKLEN_T - socklen_t st; -#else - int st; -#endif - st = sizeof(si); - g->active_conn++; s = &g->conn[i]; @@ -1019,20 +1060,7 @@ static int conn_open(EpmdVars *g,int fd) s->open = EPMD_TRUE; s->keep = EPMD_FALSE; - /* Determine if connection is from localhost */ - if (getpeername(s->fd,(struct sockaddr*) &si,&st) || - st < sizeof(si)) { - /* Failure to get peername is regarded as non local host */ - s->local_peer = EPMD_FALSE; - } else { - /* Only 127.x.x.x and connections from the host's IP address - allowed, no false positives */ - s->local_peer = - (((((unsigned) ntohl(si.sin_addr.s_addr)) & 0xFF000000U) == - 0x7F000000U) || - (getsockname(s->fd,(struct sockaddr*) &di,&st) ? - EPMD_FALSE : si.sin_addr.s_addr == di.sin_addr.s_addr)); - } + s->local_peer = conn_local_peer_check(g, s->fd); dbg_tty_printf(g,2,(s->local_peer) ? "Local peer connected" : "Non-local peer connected"); @@ -1040,7 +1068,7 @@ static int conn_open(EpmdVars *g,int fd) s->got = 0; s->mod_time = current_time(g); /* Note activity */ - s->buf = (char *)malloc(INBUF_SIZE); + s->buf = malloc(INBUF_SIZE); if (s->buf == NULL) { dbg_printf(g,0,"epmd: Insufficient memory"); @@ -1058,6 +1086,60 @@ static int conn_open(EpmdVars *g,int fd) return EPMD_FALSE; } +static int conn_local_peer_check(EpmdVars *g, int fd) +{ + struct EPMD_SOCKADDR_IN si; + struct EPMD_SOCKADDR_IN di; + + struct sockaddr_in *si4 = (struct sockaddr_in *)&si; + struct sockaddr_in *di4 = (struct sockaddr_in *)&di; + +#if defined(EPMD6) + struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&si; + struct sockaddr_in6 *di6 = (struct sockaddr_in6 *)&di; +#endif + +#ifdef HAVE_SOCKLEN_T + socklen_t st; +#else + int st; +#endif + + st = sizeof(si); + + /* Determine if connection is from localhost */ + if (getpeername(fd,(struct sockaddr*) &si,&st) || + st > sizeof(si)) { + /* Failure to get peername is regarded as non local host */ + return EPMD_FALSE; + } + + /* Only 127.x.x.x and connections from the host's IP address + allowed, no false positives */ +#if defined(EPMD6) + if (si.ss_family == AF_INET6 && IN6_IS_ADDR_LOOPBACK(&(si6->sin6_addr))) + return EPMD_TRUE; + + if (si.ss_family == AF_INET) +#endif + if ((((unsigned) ntohl(si4->sin_addr.s_addr)) & 0xFF000000U) == + 0x7F000000U) + return EPMD_TRUE; + + if (getsockname(fd,(struct sockaddr*) &di,&st)) + return EPMD_FALSE; + +#if defined(EPMD6) + if (si.ss_family == AF_INET6) + return IN6_ARE_ADDR_EQUAL( &(si6->sin6_addr), &(di6->sin6_addr)); + if (si.ss_family == AF_INET) +#endif + return si4->sin_addr.s_addr == di4->sin_addr.s_addr; +#if defined(EPMD6) + return EPMD_FALSE; +#endif +} + static int conn_close_fd(EpmdVars *g,int fd) { int i; diff --git a/erts/epmd/test/epmd_SUITE.erl b/erts/epmd/test/epmd_SUITE.erl index 0c8f01ef6b..44d3c5a880 100644 --- a/erts/epmd/test/epmd_SUITE.erl +++ b/erts/epmd/test/epmd_SUITE.erl @@ -43,6 +43,7 @@ -export( [ register_name/1, + register_name_ipv6/1, register_names_1/1, register_names_2/1, register_duplicate_name/1, @@ -113,7 +114,8 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [register_name, register_names_1, register_names_2, + [register_name, register_name_ipv6, + register_names_1, register_names_2, register_duplicate_name, unicode_name, long_unicode_name, get_port_nr, slow_get_port_nr, unregister_others_name_1, unregister_others_name_2, @@ -172,6 +174,24 @@ register_name(Config) when is_list(Config) -> ?line ok = close(Sock), % Unregister ok. +register_name_ipv6(doc) -> + ["Register a name over IPv6"]; +register_name_ipv6(suite) -> + []; +register_name_ipv6(Config) when is_list(Config) -> + % Test if the host has an IPv6 loopback address + Res = gen_tcp:listen(0, [inet6, {ip, {0,0,0,0,0,0,0,1}}]), + case Res of + {ok,LSock} -> + gen_tcp:close(LSock), + ?line ok = epmdrun(), + ?line {ok,Sock} = register_node6("foobar6"), + ?line ok = close(Sock), % Unregister + ok; + _Error -> + {skip, "Host does not have an IPv6 loopback address"} + end. + register_names_1(doc) -> ["Register and unregister two nodes"]; register_names_1(suite) -> @@ -245,9 +265,14 @@ register_node(Name) -> register_node(Name,Port) -> register_node_v2(Port,$M,0,5,5,Name,""). +register_node6(Name) -> + register_node_v2({0,0,0,0,0,0,0,1},?DUMMY_PORT,$M,0,5,5,Name,""). + register_node_v2(Port, NodeType, Prot, HVsn, LVsn, Name, Extra) -> + register_node_v2("localhost", Port, NodeType, Prot, HVsn, LVsn, Name, Extra). +register_node_v2(Addr, Port, NodeType, Prot, HVsn, LVsn, Name, Extra) -> Req = alive2_req(Port, NodeType, Prot, HVsn, LVsn, Name, Extra), - case send_req(Req) of + case send_req(Req, Addr) of {ok,Sock} -> case recv(Sock,4) of {ok, [?EPMD_ALIVE2_RESP,_Res=0,_C0,_C1]} -> @@ -1186,7 +1211,9 @@ send_direct(Sock, Bytes) -> end. send_req(Req) -> - case connect() of + send_req(Req, "localhost"). +send_req(Req, Addr) -> + case connect(Addr) of {ok,Sock} -> case send(Sock, [size16(Req), Req]) of ok -> diff --git a/erts/etc/common/erlexec.c b/erts/etc/common/erlexec.c index f21671e837..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 }; diff --git a/erts/preloaded/ebin/erlang.beam b/erts/preloaded/ebin/erlang.beam Binary files differindex db17c53ff3..2ea2de4c70 100644 --- a/erts/preloaded/ebin/erlang.beam +++ b/erts/preloaded/ebin/erlang.beam diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl index 9bf8d13fde..dfbd116d6e 100644 --- a/erts/preloaded/src/erlang.erl +++ b/erts/preloaded/src/erlang.erl @@ -2300,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(); @@ -2446,14 +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(); - (message_queue_data) -> message_queue_data(); + (normal_multi_scheduling_blockers) -> [Pid :: pid()]; (otp_release) -> string(); (os_monotonic_time_source) -> [{atom(),term()}]; (os_system_time_source) -> [{atom(),term()}]; diff --git a/erts/test/otp_SUITE.erl b/erts/test/otp_SUITE.erl index 6777c205b0..2efb5ae200 100644 --- a/erts/test/otp_SUITE.erl +++ b/erts/test/otp_SUITE.erl @@ -298,7 +298,7 @@ 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], + tools], not_recommended_calls(Config, Apps, {erlang,now,0}). not_recommended_calls(Config, Apps0, MFA) -> @@ -459,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; @@ -488,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) -> |