diff options
212 files changed, 7044 insertions, 4941 deletions
diff --git a/bootstrap/lib/compiler/ebin/sys_core_fold.beam b/bootstrap/lib/compiler/ebin/sys_core_fold.beam Binary files differindex c510dfde01..52c0d62f5f 100644 --- a/bootstrap/lib/compiler/ebin/sys_core_fold.beam +++ b/bootstrap/lib/compiler/ebin/sys_core_fold.beam diff --git a/bootstrap/lib/compiler/ebin/v3_core.beam b/bootstrap/lib/compiler/ebin/v3_core.beam Binary files differindex 6e6496c7f9..8fc18ce4a5 100644 --- a/bootstrap/lib/compiler/ebin/v3_core.beam +++ b/bootstrap/lib/compiler/ebin/v3_core.beam diff --git a/bootstrap/lib/kernel/ebin/code.beam b/bootstrap/lib/kernel/ebin/code.beam Binary files differindex 42f71e7a20..28d8a5b579 100644 --- a/bootstrap/lib/kernel/ebin/code.beam +++ b/bootstrap/lib/kernel/ebin/code.beam diff --git a/bootstrap/lib/kernel/ebin/code_server.beam b/bootstrap/lib/kernel/ebin/code_server.beam Binary files differindex 9b250ba708..135fd066d9 100644 --- a/bootstrap/lib/kernel/ebin/code_server.beam +++ b/bootstrap/lib/kernel/ebin/code_server.beam diff --git a/bootstrap/lib/kernel/ebin/heart.beam b/bootstrap/lib/kernel/ebin/heart.beam Binary files differindex 480cb0b878..86044153af 100644 --- a/bootstrap/lib/kernel/ebin/heart.beam +++ b/bootstrap/lib/kernel/ebin/heart.beam diff --git a/bootstrap/lib/kernel/ebin/hipe_unified_loader.beam b/bootstrap/lib/kernel/ebin/hipe_unified_loader.beam Binary files differindex 3faa4c94ba..a90757bd32 100644 --- a/bootstrap/lib/kernel/ebin/hipe_unified_loader.beam +++ b/bootstrap/lib/kernel/ebin/hipe_unified_loader.beam diff --git a/bootstrap/lib/stdlib/ebin/beam_lib.beam b/bootstrap/lib/stdlib/ebin/beam_lib.beam Binary files differindex 4caf4f6455..8b987fd7f7 100644 --- a/bootstrap/lib/stdlib/ebin/beam_lib.beam +++ b/bootstrap/lib/stdlib/ebin/beam_lib.beam diff --git a/bootstrap/lib/stdlib/ebin/maps.beam b/bootstrap/lib/stdlib/ebin/maps.beam Binary files differindex d616a902ae..7533b56554 100644 --- a/bootstrap/lib/stdlib/ebin/maps.beam +++ b/bootstrap/lib/stdlib/ebin/maps.beam diff --git a/bootstrap/lib/stdlib/ebin/otp_internal.beam b/bootstrap/lib/stdlib/ebin/otp_internal.beam Binary files differindex 3e3673577a..e834be6dca 100644 --- a/bootstrap/lib/stdlib/ebin/otp_internal.beam +++ b/bootstrap/lib/stdlib/ebin/otp_internal.beam diff --git a/erts/configure.in b/erts/configure.in index ba735fe921..a8d6015aee 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" 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..1f8e89768c 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 diff --git a/erts/emulator/beam/atom.names b/erts/emulator/beam/atom.names index 6fb08ee896..dca8b503bf 100644 --- a/erts/emulator/beam/atom.names +++ b/erts/emulator/beam/atom.names @@ -211,6 +211,7 @@ atom dsend atom dsend_continue_trap atom dunlink atom duplicate_bag +atom duplicated atom dupnames atom einval atom elib_malloc @@ -273,6 +274,7 @@ atom gather_gc_info_result atom gather_io_bytes atom gather_microstate_accounting_result atom gather_sched_wall_time_result +atom gather_system_check_result atom getting_linked atom getting_unlinked atom global diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c index 1b4c022370..0b47fc3586 100644 --- a/erts/emulator/beam/beam_bif_load.c +++ b/erts/emulator/beam/beam_bif_load.c @@ -86,7 +86,7 @@ BIF_RETTYPE code_make_stub_module_3(BIF_ALIST_3) ASSERT(modp->curr.num_breakpoints == 0); } - erts_start_staging_code_ix(); + erts_start_staging_code_ix(1); res = erts_make_stub_module(BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3); @@ -139,6 +139,25 @@ prepare_loading_2(BIF_ALIST_2) BIF_RET(res); } +BIF_RETTYPE +has_prepared_code_on_load_1(BIF_ALIST_1) +{ + Eterm res; + ProcBin* pb; + + if (!ERTS_TERM_IS_MAGIC_BINARY(BIF_ARG_1)) { + error: + BIF_ERROR(BIF_P, BADARG); + } + + pb = (ProcBin*) binary_val(BIF_ARG_1); + res = erts_has_code_on_load(pb->val); + if (res == NIL) { + goto error; + } + BIF_RET(res); +} + struct m { Binary* code; Eterm module; @@ -163,14 +182,13 @@ exception_list(Process* p, Eterm tag, struct m* mp, Sint exceptions) Eterm* hp = HAlloc(p, 3 + 2*exceptions); Eterm res = NIL; - mp += exceptions - 1; while (exceptions > 0) { if (mp->exception) { res = CONS(hp, mp->module, res); hp += 2; exceptions--; } - mp--; + mp++; } return TUPLE2(hp, tag, res); } @@ -202,8 +220,12 @@ finish_loading_1(BIF_ALIST_1) n = erts_list_length(BIF_ARG_1); if (n < 0) { - ERTS_BIF_PREP_ERROR(res, BIF_P, BADARG); - goto done; + badarg: + if (p) { + erts_free(ERTS_ALC_T_LOADER_TMP, p); + } + erts_release_code_write_permission(); + BIF_ERROR(BIF_P, BADARG); } p = erts_alloc(ERTS_ALC_T_LOADER_TMP, n*sizeof(struct m)); @@ -218,29 +240,32 @@ finish_loading_1(BIF_ALIST_1) ProcBin* pb; if (!ERTS_TERM_IS_MAGIC_BINARY(term)) { - ERTS_BIF_PREP_ERROR(res, BIF_P, BADARG); - goto done; + goto badarg; } pb = (ProcBin*) binary_val(term); p[i].code = pb->val; p[i].module = erts_module_for_prepared_code(p[i].code); if (p[i].module == NIL) { - ERTS_BIF_PREP_ERROR(res, BIF_P, BADARG); - goto done; + goto badarg; } BIF_ARG_1 = CDR(cons); } /* * Since we cannot handle atomic loading of a group of modules - * if one or more of them uses on_load, we will only allow one - * element in the list. This limitation is intended to be - * lifted in the future. + * if one or more of them uses on_load, we will only allow + * more than one element in the list if none of the modules + * have an on_load function. */ if (n > 1) { - ERTS_BIF_PREP_ERROR(res, BIF_P, SYSTEM_LIMIT); - goto done; + for (i = 0; i < n; i++) { + if (erts_has_code_on_load(p[i].code) == am_true) { + erts_free(ERTS_ALC_T_LOADER_TMP, p); + erts_release_code_write_permission(); + BIF_ERROR(BIF_P, SYSTEM_LIMIT); + } + } } /* @@ -252,11 +277,27 @@ finish_loading_1(BIF_ALIST_1) */ res = am_ok; - erts_start_staging_code_ix(); + erts_start_staging_code_ix(n); for (i = 0; i < n; i++) { p[i].modp = erts_put_module(p[i].module); + p[i].modp->seen = 0; } + + exceptions = 0; + for (i = 0; i < n; i++) { + p[i].exception = 0; + if (p[i].modp->seen) { + p[i].exception = 1; + exceptions++; + } + p[i].modp->seen = 1; + } + if (exceptions) { + res = exception_list(BIF_P, am_duplicated, p, exceptions); + goto done; + } + for (i = 0; i < n; i++) { if (p[i].modp->curr.num_breakpoints > 0 || p[i].modp->curr.num_traced_exports > 0 || @@ -492,7 +533,7 @@ BIF_RETTYPE delete_module_1(BIF_ALIST_1) } { - erts_start_staging_code_ix(); + erts_start_staging_code_ix(0); code_ix = erts_staging_code_ix(); modp = erts_get_module(BIF_ARG_1, code_ix); if (!modp) { 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/beam_load.c b/erts/emulator/beam/beam_load.c index 1511a4f935..f115df935f 100644 --- a/erts/emulator/beam/beam_load.c +++ b/erts/emulator/beam/beam_load.c @@ -888,6 +888,23 @@ erts_module_for_prepared_code(Binary* magic) } } +/* + * Return a non-zero value if the module has an on_load function, + * or 0 if it does not. + */ + +Eterm +erts_has_code_on_load(Binary* magic) +{ + LoaderState* stp; + + if (ERTS_MAGIC_BIN_DESTRUCTOR(magic) != loader_state_dtor) { + return NIL; + } + stp = ERTS_MAGIC_BIN_DATA(magic); + return stp->on_load ? am_true : am_false; +} + static void free_loader_state(Binary* magic) { diff --git a/erts/emulator/beam/beam_ranges.c b/erts/emulator/beam/beam_ranges.c index 5a2b66727a..54c337ee72 100644 --- a/erts/emulator/beam/beam_ranges.c +++ b/erts/emulator/beam/beam_ranges.c @@ -53,6 +53,7 @@ struct ranges { }; static struct ranges r[ERTS_NUM_CODE_IX]; static erts_smp_atomic_t mem_used; +static Range* write_ptr; #ifdef HARD_DEBUG static void check_consistency(struct ranges* p) @@ -72,6 +73,17 @@ static void check_consistency(struct ranges* p) # define CHECK(r) #endif /* HARD_DEBUG */ +static int +rangecompare(Range* a, Range* b) +{ + if (a->start < b->start) { + return -1; + } else if (a->start == b->start) { + return 0; + } else { + return 1; + } +} void erts_init_ranges(void) @@ -88,45 +100,70 @@ erts_init_ranges(void) } void -erts_start_staging_ranges(void) +erts_start_staging_ranges(int num_new) { + ErtsCodeIndex src = erts_active_code_ix(); ErtsCodeIndex dst = erts_staging_code_ix(); + Sint need; if (r[dst].modules) { erts_smp_atomic_add_nob(&mem_used, -r[dst].allocated); erts_free(ERTS_ALC_T_MODULE_REFS, r[dst].modules); - r[dst].modules = NULL; } + + need = r[dst].allocated = r[src].n + num_new; + erts_smp_atomic_add_nob(&mem_used, need); + write_ptr = erts_alloc(ERTS_ALC_T_MODULE_REFS, + need * sizeof(Range)); + r[dst].modules = write_ptr; } void erts_end_staging_ranges(int commit) { - ErtsCodeIndex dst = erts_staging_code_ix(); - - if (commit && r[dst].modules == NULL) { + if (commit) { Sint i; - Sint n; - - /* No modules added, just clone src and remove purged code. */ ErtsCodeIndex src = erts_active_code_ix(); + ErtsCodeIndex dst = erts_staging_code_ix(); + Range* mp; + Sint num_inserted; - erts_smp_atomic_add_nob(&mem_used, r[src].n); - r[dst].modules = erts_alloc(ERTS_ALC_T_MODULE_REFS, - r[src].n * sizeof(Range)); - r[dst].allocated = r[src].n; - n = 0; + mp = r[dst].modules; + num_inserted = write_ptr - mp; for (i = 0; i < r[src].n; i++) { Range* rp = r[src].modules+i; if (rp->start < RANGE_END(rp)) { /* Only insert a module that has not been purged. */ - r[dst].modules[n] = *rp; - n++; + write_ptr->start = rp->start; + erts_smp_atomic_init_nob(&write_ptr->end, + (erts_aint_t)(RANGE_END(rp))); + write_ptr++; + } + } + + /* + * There are num_inserted new range entries (unsorted) at the + * beginning of the modules array, followed by the old entries + * (sorted). We must now sort the entire array. + */ + + r[dst].n = write_ptr - mp; + if (num_inserted > 1) { + qsort(mp, r[dst].n, sizeof(Range), + (int (*)(const void *, const void *)) rangecompare); + } else if (num_inserted == 1) { + /* Sift the new range into place. This is faster than qsort(). */ + Range t = mp[0]; + for (i = 0; i < r[dst].n-1 && t.start > mp[i+1].start; i++) { + mp[i] = mp[i+1]; } + mp[i] = t; } - r[dst].n = n; + r[dst].modules = mp; + CHECK(&r[dst]); erts_smp_atomic_set_nob(&r[dst].mid, - (erts_aint_t) (r[dst].modules + n / 2)); + (erts_aint_t) (r[dst].modules + + r[dst].n / 2)); } } @@ -135,82 +172,29 @@ erts_update_ranges(BeamInstr* code, Uint size) { ErtsCodeIndex dst = erts_staging_code_ix(); ErtsCodeIndex src = erts_active_code_ix(); - Sint i; - Sint n; - Sint need; if (src == dst) { ASSERT(!erts_initialized); /* - * During start-up of system, the indices are the same. - * Handle this by faking a source area. + * During start-up of system, the indices are the same + * and erts_start_staging_ranges() has not been called. */ - src = (src+1) % ERTS_NUM_CODE_IX; - if (r[src].modules) { - erts_smp_atomic_add_nob(&mem_used, -r[src].allocated); - erts_free(ERTS_ALC_T_MODULE_REFS, r[src].modules); + if (r[dst].modules == NULL) { + Sint need = 128; + erts_smp_atomic_add_nob(&mem_used, need); + r[dst].modules = erts_alloc(ERTS_ALC_T_MODULE_REFS, + need * sizeof(Range)); + r[dst].allocated = need; + write_ptr = r[dst].modules; } - r[src] = r[dst]; - r[dst].modules = 0; } - CHECK(&r[src]); - - ASSERT(r[dst].modules == NULL); - need = r[dst].allocated = r[src].n + 1; - erts_smp_atomic_add_nob(&mem_used, need); - r[dst].modules = (Range *) erts_alloc(ERTS_ALC_T_MODULE_REFS, - need * sizeof(Range)); - n = 0; - for (i = 0; i < r[src].n; i++) { - Range* rp = r[src].modules+i; - if (code < rp->start) { - r[dst].modules[n].start = code; - erts_smp_atomic_init_nob(&r[dst].modules[n].end, - (erts_aint_t)(((byte *)code) + size)); - ASSERT(!n || RANGE_END(&r[dst].modules[n-1]) < code); - n++; - break; - } - if (rp->start < RANGE_END(rp)) { - /* Only insert a module that has not been purged. */ - r[dst].modules[n].start = rp->start; - erts_smp_atomic_init_nob(&r[dst].modules[n].end, - (erts_aint_t)(RANGE_END(rp))); - ASSERT(!n || RANGE_END(&r[dst].modules[n-1]) < rp->start); - n++; - } - } - - while (i < r[src].n) { - Range* rp = r[src].modules+i; - if (rp->start < RANGE_END(rp)) { - /* Only insert a module that has not been purged. */ - r[dst].modules[n].start = rp->start; - erts_smp_atomic_init_nob(&r[dst].modules[n].end, - (erts_aint_t)(RANGE_END(rp))); - ASSERT(!n || RANGE_END(&r[dst].modules[n-1]) < rp->start); - n++; - } - i++; - } - - if (n == 0 || code > r[dst].modules[n-1].start) { - r[dst].modules[n].start = code; - erts_smp_atomic_init_nob(&r[dst].modules[n].end, - (erts_aint_t)(((byte *)code) + size)); - ASSERT(!n || RANGE_END(&r[dst].modules[n-1]) < code); - n++; - } - - ASSERT(n <= r[src].n+1); - r[dst].n = n; - erts_smp_atomic_set_nob(&r[dst].mid, - (erts_aint_t) (r[dst].modules + n / 2)); - - CHECK(&r[dst]); - CHECK(&r[src]); + ASSERT(r[dst].modules); + write_ptr->start = code; + erts_smp_atomic_init_nob(&(write_ptr->end), + (erts_aint_t)(((byte *)code) + size)); + write_ptr++; } void diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c index 2654785ffc..6ab75496a0 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); diff --git a/erts/emulator/beam/bif.tab b/erts/emulator/beam/bif.tab index 4efc055aaf..a6670c10e8 100644 --- a/erts/emulator/beam/bif.tab +++ b/erts/emulator/beam/bif.tab @@ -174,6 +174,8 @@ bif erts_internal:perf_counter_unit/0 bif erts_internal:is_system_process/1 +bif erts_internal:system_check/1 + # inet_db support bif erlang:port_set_data/2 bif erlang:port_get_data/1 @@ -649,6 +651,7 @@ bif binary:split/2 bif binary:split/3 bif erts_debug:size_shared/1 bif erts_debug:copy_shared/1 +bif erlang:has_prepared_code_on_load/1 # # Obsolete diff --git a/erts/emulator/beam/big.c b/erts/emulator/beam/big.c index 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/code_ix.c b/erts/emulator/beam/code_ix.c index 209d008d18..1b0968c55c 100644 --- a/erts/emulator/beam/code_ix.c +++ b/erts/emulator/beam/code_ix.c @@ -65,12 +65,12 @@ void erts_code_ix_init(void) CIX_TRACE("init"); } -void erts_start_staging_code_ix(void) +void erts_start_staging_code_ix(int num_new) { beam_catches_start_staging(); export_start_staging(); module_start_staging(); - erts_start_staging_ranges(); + erts_start_staging_ranges(num_new); CIX_TRACE("start"); } diff --git a/erts/emulator/beam/code_ix.h b/erts/emulator/beam/code_ix.h index 5f00b409ef..7a66211a5b 100644 --- a/erts/emulator/beam/code_ix.h +++ b/erts/emulator/beam/code_ix.h @@ -100,7 +100,7 @@ void erts_release_code_write_permission(void); * Must be followed by calls to either "end" and "commit" or "abort" before * code write permission can be released. */ -void erts_start_staging_code_ix(void); +void erts_start_staging_code_ix(int num_new); /* End the staging. * Preceded by "start" and must be followed by "commit". diff --git a/erts/emulator/beam/copy.c b/erts/emulator/beam/copy.c index 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..53b87c7e4b 100644 --- a/erts/emulator/beam/erl_alloc.c +++ b/erts/emulator/beam/erl_alloc.c @@ -665,11 +665,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 } @@ -810,13 +810,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 +887,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 +969,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 +1014,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 +1042,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 +1116,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); @@ -1908,7 +1908,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 +1922,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 +3120,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 +3354,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 +3819,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 +3836,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 +3864,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.types b/erts/emulator/beam/erl_alloc.types index 5f153ac0ab..2932adca84 100644 --- a/erts/emulator/beam/erl_alloc.types +++ b/erts/emulator/beam/erl_alloc.types @@ -362,6 +362,7 @@ type SCHED_WTIME_REQ SHORT_LIVED SYSTEM sched_wall_time_request type GC_INFO_REQ SHORT_LIVED SYSTEM gc_info_request type PORT_DATA_HEAP STANDARD SYSTEM port_data_heap type MSACC DRIVER SYSTEM microstate_accounting +type SYS_CHECK_REQ SHORT_LIVED SYSTEM system_check_request # # Types used by system specific code diff --git a/erts/emulator/beam/erl_alloc_util.c b/erts/emulator/beam/erl_alloc_util.c index 3230b6ef34..a4e56a6ff7 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); } @@ -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 bc5c83e542..39eb257c2c 100644 --- a/erts/emulator/beam/erl_bif_info.c +++ b/erts/emulator/beam/erl_bif_info.c @@ -66,6 +66,7 @@ static Export* gather_io_bytes_trap = NULL; static Export *gather_sched_wall_time_res_trap; static Export *gather_msacc_res_trap; static Export *gather_gc_info_res_trap; +static Export *gather_system_check_res_trap; #define DECL_AM(S) Eterm AM_ ## S = am_atom_put(#S, sizeof(#S) - 1) @@ -931,7 +932,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__); } } @@ -971,7 +972,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__); } } @@ -1726,7 +1727,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); @@ -1745,7 +1746,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); @@ -3786,6 +3787,18 @@ BIF_RETTYPE erts_internal_is_system_process_1(BIF_ALIST_1) BIF_ERROR(BIF_P, BADARG); } +BIF_RETTYPE erts_internal_system_check_1(BIF_ALIST_1) +{ + Eterm res; + if (ERTS_IS_ATOM_STR("schedulers", BIF_ARG_1)) { + res = erts_system_check_request(BIF_P); + if (is_non_value(res)) + BIF_RET(am_undefined); + BIF_TRAP1(gather_system_check_res_trap, BIF_P, res); + } + + BIF_ERROR(BIF_P, BADARG); +} static erts_smp_atomic_t hipe_test_reschedule_flag; @@ -3800,7 +3813,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); } @@ -4045,7 +4058,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); @@ -4407,7 +4420,8 @@ erts_bif_info_init(void) = erts_export_put(am_erts_internal, am_gather_io_bytes, 2); gather_msacc_res_trap = erts_export_put(am_erts_internal, am_gather_microstate_accounting_result, 2); - + gather_system_check_res_trap + = erts_export_put(am_erts_internal, am_gather_system_check_result, 1); process_info_init(); os_info_init(); } 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 255c93260a..c69cbc023c 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -505,7 +505,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); } @@ -959,10 +959,24 @@ typedef struct { erts_smp_atomic32_t refc; } ErtsSchedWallTimeReq; +typedef struct { + Process *proc; + Eterm ref; + Eterm ref_heap[REF_THING_SIZE]; + Uint req_sched; + erts_smp_atomic32_t refc; +} ErtsSystemCheckReq; + + ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(swtreq, - ErtsSchedWallTimeReq, - 5, - ERTS_ALC_T_SCHED_WTIME_REQ) + ErtsSchedWallTimeReq, + 5, + ERTS_ALC_T_SCHED_WTIME_REQ) + +ERTS_SCHED_PREF_QUICK_ALLOC_IMPL(screq, + ErtsSystemCheckReq, + 5, + ERTS_ALC_T_SYS_CHECK_REQ) static void reply_sched_wall_time(void *vswtrp) @@ -1095,6 +1109,75 @@ erts_sched_wall_time_request(Process *c_p, int set, int enable) return ref; } +static void +reply_system_check(void *vscrp) +{ + ErtsSchedulerData *esdp = erts_get_scheduler_data(); + ErtsSystemCheckReq *scrp = (ErtsSystemCheckReq *) vscrp; + ErtsProcLocks rp_locks = (scrp->req_sched == esdp->no ? ERTS_PROC_LOCK_MAIN : 0); + Process *rp = scrp->proc; + Eterm msg; + Eterm *hp = NULL; + Eterm **hpp; + Uint sz; + ErlOffHeap *ohp = NULL; + ErtsMessage *mp = NULL; + + ASSERT(esdp); +#ifdef ERTS_DIRTY_SCHEDULERS + ASSERT(!ERTS_SCHEDULER_IS_DIRTY(esdp)); +#endif + + sz = REF_THING_SIZE; + mp = erts_alloc_message_heap(rp, &rp_locks, sz, &hp, &ohp); + hpp = &hp; + msg = STORE_NC(hpp, ohp, scrp->ref); + + erts_queue_message(rp, &rp_locks, mp, msg, NIL); + + if (scrp->req_sched == esdp->no) + rp_locks &= ~ERTS_PROC_LOCK_MAIN; + + if (rp_locks) + erts_smp_proc_unlock(rp, rp_locks); + + erts_proc_dec_refc(rp); + + if (erts_smp_atomic32_dec_read_nob(&scrp->refc) == 0) + screq_free(vscrp); +} + + +Eterm erts_system_check_request(Process *c_p) { + ErtsSchedulerData *esdp = ERTS_PROC_GET_SCHDATA(c_p); + Eterm ref; + ErtsSystemCheckReq *scrp; + Eterm *hp; + + scrp = screq_alloc(); + ref = erts_make_ref(c_p); + hp = &scrp->ref_heap[0]; + + scrp->proc = c_p; + scrp->ref = STORE_NC(&hp, NULL, ref); + scrp->req_sched = esdp->no; + erts_smp_atomic32_init_nob(&scrp->refc, (erts_aint32_t) erts_no_schedulers); + + erts_proc_add_refc(c_p, (Sint) erts_no_schedulers); + +#ifdef ERTS_SMP + if (erts_no_schedulers > 1) + erts_schedule_multi_misc_aux_work(1, + erts_no_schedulers, + reply_system_check, + (void *) scrp); +#endif + + reply_system_check((void *) scrp); + + return ref; +} + static ERTS_INLINE ErtsProcList * proclist_create(Process *p) { @@ -1189,7 +1272,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; } @@ -2147,7 +2230,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; @@ -3664,7 +3747,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; @@ -3688,7 +3771,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); @@ -3879,7 +3962,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); @@ -4124,7 +4207,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; @@ -5775,6 +5858,7 @@ erts_init_scheduling(int no_schedulers, int no_schedulers_online init_misc_aux_work(); init_swtreq_alloc(); + init_screq_alloc(); erts_atomic32_init_nob(&debug_wait_completed_count, 0); /* debug only */ debug_wait_completed_flags = 0; @@ -8134,7 +8218,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; @@ -8199,7 +8283,7 @@ sched_dirty_cpu_thread_func(void *vesdp) 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; @@ -8262,7 +8346,7 @@ sched_dirty_io_thread_func(void *vesdp) 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; @@ -8292,12 +8376,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 @@ -8335,14 +8419,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 @@ -8354,10 +8438,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); @@ -12308,7 +12392,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); @@ -12349,7 +12433,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 @@ -12467,7 +12551,7 @@ erts_continue_exit_process(Process *p) 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); } } @@ -12964,10 +13048,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 ef4aab7234..6b370e630e 100644 --- a/erts/emulator/beam/erl_process.h +++ b/erts/emulator/beam/erl_process.h @@ -1523,6 +1523,7 @@ void erts_init_scheduling(int, int int erts_set_gc_state(Process *c_p, int enable); Eterm erts_sched_wall_time_request(Process *c_p, int set, int enable); +Eterm erts_system_check_request(Process *c_p); Eterm erts_gc_info_request(Process *c_p); Uint64 erts_get_proc_interval(void); Uint64 erts_ensure_later_proc_interval(Uint64); @@ -2461,6 +2462,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 2a8bdb6ee3..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); \ @@ -1008,6 +1008,7 @@ typedef struct { Binary* erts_alloc_loader_state(void); Eterm erts_module_for_prepared_code(Binary* magic); +Eterm erts_has_code_on_load(Binary* magic); Eterm erts_prepare_loading(Binary* loader_state, Process *c_p, Eterm group_leader, Eterm* modp, byte* code, Uint size); @@ -1026,7 +1027,7 @@ Eterm erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info); /* beam_ranges.c */ void erts_init_ranges(void); -void erts_start_staging_ranges(void); +void erts_start_staging_ranges(int num_new); void erts_end_staging_ranges(int commit); void erts_update_ranges(BeamInstr* code, Uint size); void erts_remove_from_ranges(BeamInstr* code); @@ -1047,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/module.h b/erts/emulator/beam/module.h index e66d628ca9..b7468b0926 100644 --- a/erts/emulator/beam/module.h +++ b/erts/emulator/beam/module.h @@ -37,6 +37,7 @@ struct erl_module_instance { typedef struct erl_module { IndexSlot slot; /* Must be located at top of struct! */ int module; /* Atom index for module (not tagged). */ + int seen; /* Used by finish_loading() */ struct erl_module_instance curr; struct erl_module_instance old; /* protected by "old_code" rwlock */ diff --git a/erts/emulator/beam/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/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_mseg.c b/erts/emulator/sys/common/erl_mseg.c index 20695899eb..461f0faf75 100644 --- a/erts/emulator/sys/common/erl_mseg.c +++ b/erts/emulator/sys/common/erl_mseg.c @@ -1405,7 +1405,7 @@ erts_mseg_init(ErtsMsegInit_t *init) erts_mmap_init(&erts_dflt_mmapper, &init->dflt_mmap); 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/Makefile b/erts/emulator/test/Makefile index 987a655c3d..318db4b45e 100644 --- a/erts/emulator/test/Makefile +++ b/erts/emulator/test/Makefile @@ -74,6 +74,7 @@ MODULES= \ match_spec_SUITE \ module_info_SUITE \ monitor_SUITE \ + multi_load_SUITE \ nested_SUITE \ nif_SUITE \ node_container_SUITE \ diff --git a/erts/emulator/test/multi_load_SUITE.erl b/erts/emulator/test/multi_load_SUITE.erl new file mode 100644 index 0000000000..784b239116 --- /dev/null +++ b/erts/emulator/test/multi_load_SUITE.erl @@ -0,0 +1,196 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2012. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% + +-module(multi_load_SUITE). +-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, + init_per_group/2,end_per_group/2, + many/1,on_load/1,errors/1]). + +-include_lib("common_test/include/ct.hrl"). + +suite() -> [{ct_hooks,[ts_install_cth]}]. + +all() -> + [many,on_load,errors]. + +groups() -> + []. + +init_per_suite(Config) -> + Config. + +end_per_suite(_Config) -> + ok. + +init_per_group(_GroupName, Config) -> + Config. + +end_per_group(_GroupName, Config) -> + Config. + +many(_Config) -> + Ms = make_modules(100, fun many_module/1), + + io:put_chars("Light load\n" + "=========="), + many_measure(Ms), + + _ = [spawn_link(fun many_worker/0) || _ <- lists:seq(1, 8)], + erlang:yield(), + io:put_chars("Heavy load\n" + "=========="), + many_measure(Ms), + + ok. + +many_module(M) -> + ["-module("++M++").", + "-compile(export_all).", + "f1() -> ok.", + "f2() -> ok.", + "f3() -> ok.", + "f4() -> ok."]. + +many_measure(Ms) -> + many_purge(Ms), + MsPrep1 = prepare_modules(Ms), + Us1 = ms(fun() -> many_load_seq(MsPrep1) end), + many_try_call(Ms), + many_purge(Ms), + MsPrep2 = prepare_modules(Ms), + Us2 = ms(fun() -> many_load_par(MsPrep2) end), + many_try_call(Ms), + io:format("# modules: ~9w\n" + "Sequential: ~9w µs\n" + "Parallel: ~9w µs\n" + "Ratio: ~9w\n", + [length(Ms),Us1,Us2,round(Us1/Us2)]), + ok. + +many_load_seq(Ms) -> + [erlang:finish_loading([M]) || M <- Ms], + ok. + +many_load_par(Ms) -> + erlang:finish_loading(Ms). + +many_purge(Ms) -> + _ = [catch erlang:purge_module(M) || {M,_} <- Ms], + ok. + +many_try_call(Ms) -> + _ = [begin + ok = M:f1(), + ok = M:f2(), + ok = M:f3(), + ok = M:f4() + end || {M,_} <- Ms], + ok. + +many_worker() -> + many_worker(lists:seq(1, 100)). + +many_worker(L) -> + N0 = length(L), + N1 = N0 * N0 * N0, + N2 = N1 div (N0 * N0), + N3 = N2 + 10, + _ = N3 - 10, + many_worker(L). + + +on_load(_Config) -> + On = make_modules(2, fun on_load_module/1), + OnPrep = prepare_modules(On), + {'EXIT',{system_limit,_}} = (catch erlang:finish_loading(OnPrep)), + + Normal = make_modules(1, fun on_load_normal/1), + Mixed = Normal ++ tl(On), + MixedPrep = prepare_modules(Mixed), + {'EXIT',{system_limit,_}} = (catch erlang:finish_loading(MixedPrep)), + + [false,true] = [erlang:has_prepared_code_on_load(Code) || + Code <- MixedPrep], + {'EXIT',{badarg,_}} = (catch erlang:has_prepared_code_on_load(<<1,2,3>>)), + Magic = ets:match_spec_compile([{'_',[true],['$_']}]), + {'EXIT',{badarg,_}} = (catch erlang:has_prepared_code_on_load(Magic)), + + SingleOnPrep = tl(OnPrep), + {on_load,[OnLoadMod]} = erlang:finish_loading(SingleOnPrep), + ok = erlang:call_on_load_function(OnLoadMod), + + ok. + +on_load_module(M) -> + ["-module("++M++").", + "-on_load(f/0).", + "f() -> ok."]. + +on_load_normal(M) -> + ["-module("++M++")."]. + + +errors(_Config) -> + finish_loading_badarg(x), + finish_loading_badarg([x|y]), + finish_loading_badarg([x]), + finish_loading_badarg([<<>>]), + + Mods = make_modules(2, fun errors_module/1), + Ms = lists:sort([M || {M,_} <- Mods]), + Prep = prepare_modules(Mods), + {duplicated,Dups} = erlang:finish_loading(Prep ++ Prep), + Ms = lists:sort(Dups), + ok. + +finish_loading_badarg(Arg) -> + {'EXIT',{badarg,[{erlang,finish_loading,[Arg],_}|_]}} = + (catch erlang:finish_loading(Arg)). + +errors_module(M) -> + ["-module("++M++").", + "-export([f/0]).", + "f() -> ok."]. + +%%% +%%% Common utilities +%%% + +ms(Fun) -> + {Ms,ok} = timer:tc(Fun), + Ms. + +make_modules(0, _) -> + []; +make_modules(N, Fun) -> + U = erlang:unique_integer([positive]), + M0 = "m__" ++ integer_to_list(N) ++ "_" ++ integer_to_list(U), + Contents = Fun(M0), + Forms = [make_form(S) || S <- Contents], + {ok,M,Code} = compile:forms(Forms), + [{M,Code}|make_modules(N-1, Fun)]. + +make_form(S) -> + {ok,Toks,_} = erl_scan:string(S), + {ok,Form} = erl_parse:parse_form(Toks), + Form. + +prepare_modules(Ms) -> + [erlang:prepare_loading(M, Code) || {M,Code} <- Ms]. diff --git a/erts/emulator/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..84a2e0a3ea 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; + + num_sockets++; - if (num_sockets - loopback_ok == MAX_LISTEN_SOCKETS - 1) + 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"); - epmd_cleanup_exit(g,1); + switch (errno) { + case EAFNOSUPPORT: + case EPROTONOSUPPORT: + continue; + default: + dbg_perror(g,"error opening stream socket"); + epmd_cleanup_exit(g,1); + } } g->listenfd[i] = 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); + } +#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) { @@ -389,12 +434,18 @@ void run(EpmdVars *g) } } + bound++; + if(listen(listensock[i], SOMAXCONN) < 0) { dbg_perror(g,"failed to listen on socket"); epmd_cleanup_exit(g,1); } select_fd_set(g, listensock[i]); } + if (bound == 0) { + dbg_perror(g,"unable to bind any address"); + epmd_cleanup_exit(g,1); + } #ifdef HAVE_SYSTEMD_DAEMON } sd_notifyf(0, "READY=1\n" @@ -1000,15 +1051,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 +1061,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 +1069,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 +1087,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/heart.c b/erts/etc/common/heart.c index 9571b83ffd..1a826221fb 100644 --- a/erts/etc/common/heart.c +++ b/erts/etc/common/heart.c @@ -472,10 +472,6 @@ message_loop(erlin_fd, erlout_fd) switch (mp->op) { case HEART_BEAT: timestamp(&last_received); -#ifdef USE_WATCHDOG - /* reset the hardware watchdog timer */ - wd_reset(); -#endif break; case SHUT_DOWN: return R_SHUT_DOWN; diff --git a/erts/preloaded/ebin/erl_prim_loader.beam b/erts/preloaded/ebin/erl_prim_loader.beam Binary files differindex ca9e6bd20f..6d777fa811 100644 --- a/erts/preloaded/ebin/erl_prim_loader.beam +++ b/erts/preloaded/ebin/erl_prim_loader.beam diff --git a/erts/preloaded/ebin/erlang.beam b/erts/preloaded/ebin/erlang.beam Binary files differindex b353129a34..db17c53ff3 100644 --- a/erts/preloaded/ebin/erlang.beam +++ b/erts/preloaded/ebin/erlang.beam diff --git a/erts/preloaded/ebin/erts_internal.beam b/erts/preloaded/ebin/erts_internal.beam Binary files differindex 5590f5a911..88da34b192 100644 --- a/erts/preloaded/ebin/erts_internal.beam +++ b/erts/preloaded/ebin/erts_internal.beam diff --git a/erts/preloaded/src/erl_prim_loader.erl b/erts/preloaded/src/erl_prim_loader.erl index 824ed3435d..cbcced5512 100644 --- a/erts/preloaded/src/erl_prim_loader.erl +++ b/erts/preloaded/src/erl_prim_loader.erl @@ -55,6 +55,9 @@ %% Used by test suites -export([purge_archive_cache/0]). +%% Used by init and the code server. +-export([get_modules/3]). + -include_lib("kernel/include/file.hrl"). -type host() :: atom(). @@ -236,6 +239,16 @@ set_primary_archive(File, ArchiveBin, FileInfo, ParserFun) purge_archive_cache() -> request(purge_archive_cache). + +-spec get_modules([module()], + fun((atom(), string(), binary()) -> + {'ok',any()} | {'error',any()}), + [string()]) -> + {'ok',{[any()],[any()]}}. + +get_modules(Modules, Fun, Path) -> + request({get_modules,{Modules,Fun,Path}}). + request(Req) -> Loader = whereis(erl_prim_loader), Loader ! {self(),Req}, @@ -325,6 +338,8 @@ handle_request(Req, Paths, St0) -> {{ok,Paths},St0}; {get_file,File} -> handle_get_file(St0, Paths, File); + {get_modules,{Modules,Fun,ModPaths}} -> + handle_get_modules(St0, Modules, Fun, ModPaths); {list_dir,Dir} -> handle_list_dir(St0, Dir); {read_file_info,File} -> @@ -465,6 +480,124 @@ efile_timeout_handler(State, _Parent) -> State. %%% -------------------------------------------------------- +%%% Read and process severals modules in parallel. +%%% -------------------------------------------------------- + +handle_get_modules(#state{loader=efile}=St, Ms, Process, Paths) -> + Primary = (St#state.prim_state)#prim_state.primary_archive, + Res = case efile_any_archives(Paths, Primary) of + false -> + efile_get_mods_par(Ms, Process, Paths); + true -> + Get = fun efile_get_file_from_port/3, + gm_get_mods(St, Get, Ms, Process, Paths) + end, + {Res,St}; +handle_get_modules(#state{loader=inet}=St, Ms, Process, Paths) -> + Get = fun inet_get_file_from_port/3, + {gm_get_mods(St, Get, Ms, Process, Paths),St}. + +efile_get_mods_par(Ms, Process, Paths) -> + Self = self(), + Ref = make_ref(), + GmSpawn = fun() -> + efile_gm_spawn({Self,Ref}, Ms, Process, Paths) + end, + _ = spawn_link(GmSpawn), + N = length(Ms), + efile_gm_recv(N, Ref, [], []). + +efile_any_archives([H|T], Primary) -> + case name_split(Primary, H) of + {file,_} -> efile_any_archives(T, Primary); + {archive,_,_} -> true + end; +efile_any_archives([], _) -> + false. + +efile_gm_recv(0, _Ref, Succ, Fail) -> + {ok,{Succ,Fail}}; +efile_gm_recv(N, Ref, Succ, Fail) -> + receive + {Ref,Mod,{ok,Res}} -> + efile_gm_recv(N-1, Ref, [{Mod,Res}|Succ], Fail); + {Ref,Mod,{error,Res}} -> + efile_gm_recv(N-1, Ref, Succ, [{Mod,Res}|Fail]) + end. + +efile_gm_spawn(ParentRef, Ms, Process, Paths) -> + efile_gm_spawn_1(0, Ms, ParentRef, Process, Paths). + +efile_gm_spawn_1(N, Ms, ParentRef, Process, Paths) when N >= 32 -> + receive + {'DOWN',_,process,_,_} -> + efile_gm_spawn_1(N-1, Ms, ParentRef, Process, Paths) + end; +efile_gm_spawn_1(N, [M|Ms], ParentRef, Process, Paths) -> + Get = fun() -> efile_gm_get(Paths, M, ParentRef, Process) end, + _ = spawn_monitor(Get), + efile_gm_spawn_1(N+1, Ms, ParentRef, Process, Paths); +efile_gm_spawn_1(_, [], _, _, _) -> + ok. + +efile_gm_get(Paths, Mod, ParentRef, Process) -> + File = atom_to_list(Mod) ++ init:objfile_extension(), + efile_gm_get_1(Paths, File, Mod, ParentRef, Process). + +efile_gm_get_1([P|Ps], File0, Mod, {Parent,Ref}=PR, Process) -> + File = join(P, File0), + Res = try prim_file:read_file(File) of + {ok,Bin} -> + gm_process(Mod, File, Bin, Process); + {error,enoent} -> + efile_gm_get_1(Ps, File0, Mod, PR, Process); + Error -> + check_file_result(get_modules, File, Error), + Error + catch + _:Reason -> + {error,{crash,Reason}} + end, + Parent ! {Ref,Mod,Res}; +efile_gm_get_1([], _, Mod, {Parent,Ref}, _Process) -> + Parent ! {Ref,Mod,{error,enoent}}. + +gm_get_mods(St, Get, Ms, Process, Paths) -> + gm_get_mods(St, Get, Ms, Process, Paths, [], []). + +gm_get_mods(St, Get, [M|Ms], Process, Paths, Succ, Fail) -> + File = atom_to_list(M) ++ init:objfile_extension(), + case gm_arch_get(St, Get, M, File, Paths, Process) of + {ok,Res} -> + gm_get_mods(St, Get, Ms, Process, Paths, + [{M,Res}|Succ], Fail); + {error,Res} -> + gm_get_mods(St, Get, Ms, Process, Paths, + Succ, [{M,Res}|Fail]) + end; +gm_get_mods(_St, _Get, [], _, _, Succ, Fail) -> + {ok,{Succ,Fail}}. + +gm_arch_get(St, Get, Mod, File, Paths, Process) -> + case Get(St, File, Paths) of + {{error,_}=E,_} -> + E; + {{ok,Bin,Full},_} -> + gm_process(Mod, Full, Bin, Process) + end. + +gm_process(Mod, File, Bin, Process) -> + try Process(Mod, File, Bin) of + {ok,_}=Res -> Res; + {error,_}=Res -> Res; + Other -> {error,{bad_return,Other}} + catch + _:Error -> + {error,{crash,Error}} + end. + + +%%% -------------------------------------------------------- %%% Functions which handle inet prim_loader %%% -------------------------------------------------------- diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl index ab51cf385c..9bf8d13fde 100644 --- a/erts/preloaded/src/erlang.erl +++ b/erts/preloaded/src/erlang.erl @@ -105,7 +105,9 @@ -export([garbage_collect/0, garbage_collect/1, garbage_collect/2]). -export([garbage_collect_message_area/0, get/0, get/1, get_keys/0, get_keys/1]). -export([get_module_info/1, get_stacktrace/0, group_leader/0]). --export([group_leader/2, halt/0, halt/1, halt/2, hash/2, hibernate/3]). +-export([group_leader/2]). +-export([halt/0, halt/1, halt/2, hash/2, + has_prepared_code_on_load/1, hibernate/3]). -export([insert_element/3]). -export([integer_to_binary/1, integer_to_list/1]). -export([iolist_size/1, iolist_to_binary/1]). @@ -997,6 +999,12 @@ halt(_Status, _Options) -> hash(_Term, _Range) -> erlang:nif_error(undefined). +%% has_prepared_code_on_load/1 +-spec erlang:has_prepared_code_on_load(PreparedCode) -> boolean() when + PreparedCode :: binary(). +has_prepared_code_on_load(_PreparedCode) -> + erlang:nif_error(undefined). + %% hibernate/3 -spec erlang:hibernate(Module, Function, Args) -> no_return() when Module :: module(), diff --git a/erts/preloaded/src/erts_internal.erl b/erts/preloaded/src/erts_internal.erl index 26025d6704..330fcc4a9c 100644 --- a/erts/preloaded/src/erts_internal.erl +++ b/erts/preloaded/src/erts_internal.erl @@ -35,6 +35,9 @@ -export([open_port/2, port_command/3, port_connect/2, port_close/1, port_control/3, port_call/3, port_info/1, port_info/2]). +-export([system_check/1, + gather_system_check_result/1]). + -export([request_system_task/3]). -export([check_process_code/3]). @@ -281,6 +284,23 @@ copy_literals(_Mod, _Bool) -> purge_module(_Module) -> erlang:nif_error(undefined). +-spec system_check(Type) -> 'ok' when + Type :: 'schedulers'. + +system_check(_Type) -> + erlang:nif_error(undefined). + +gather_system_check_result(Ref) when is_reference(Ref) -> + gather_system_check_result(Ref, erlang:system_info(schedulers)). + +gather_system_check_result(_Ref, 0) -> + ok; +gather_system_check_result(Ref, N) -> + receive + Ref -> + gather_system_check_result(Ref, N - 1) + end. + %% term compare where integer() < float() = true -spec cmp_term(A,B) -> Result when diff --git a/lib/common_test/src/ct_conn_log_h.erl b/lib/common_test/src/ct_conn_log_h.erl index f7615fdc14..93f358462d 100644 --- a/lib/common_test/src/ct_conn_log_h.erl +++ b/lib/common_test/src/ct_conn_log_h.erl @@ -117,7 +117,7 @@ write_report(Time,#conn_log{module=ConnMod}=Info,Data,GL,State) -> ok; {LogType,Fd} -> case format_data(ConnMod,LogType,Data) of - [] -> + [] when Info#conn_log.action==send; Info#conn_log.action==recv -> ok; FormattedData -> io:format(Fd,"~n~ts~ts~ts",[format_head(ConnMod,LogType,Time), diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl index f792269c41..8fb7a03bb0 100644 --- a/lib/common_test/src/ct_framework.erl +++ b/lib/common_test/src/ct_framework.erl @@ -28,7 +28,7 @@ -export([init_tc/3, end_tc/3, end_tc/4, get_suite/2, get_all_cases/1]). -export([report/2, warn/1, error_notification/4]). --export([get_logopts/0, format_comment/1, get_html_wrapper/4]). +-export([get_log_dir/0, get_logopts/0, format_comment/1, get_html_wrapper/4]). -export([error_in_suite/1, init_per_suite/1, end_per_suite/1, init_per_group/2, end_per_group/2]). @@ -1480,3 +1480,8 @@ get_html_wrapper(TestName, PrintLabel, Cwd, TableCols) -> get_html_wrapper(TestName, PrintLabel, Cwd, TableCols, Encoding) -> ct_logs:get_ts_html_wrapper(TestName, PrintLabel, Cwd, TableCols, Encoding). + +%%%----------------------------------------------------------------- +%%% @spec get_log_dir() -> {ok,LogDir} +get_log_dir() -> + ct_logs:get_log_dir(true). diff --git a/lib/common_test/src/ct_netconfc.erl b/lib/common_test/src/ct_netconfc.erl index 3da1115c76..8812514ad9 100644 --- a/lib/common_test/src/ct_netconfc.erl +++ b/lib/common_test/src/ct_netconfc.erl @@ -234,7 +234,6 @@ %% Internal defines %%---------------------------------------------------------------------- -define(APPLICATION,?MODULE). --define(VALID_SSH_OPTS,[user, password, user_dir]). -define(DEFAULT_STREAM,"NETCONF"). -define(error(ConnName,Report), @@ -1257,13 +1256,11 @@ check_options([{port,Port}|T], Host, _, #options{} = Options) -> check_options([{timeout, Timeout}|T], Host, Port, Options) when is_integer(Timeout); Timeout==infinity -> check_options(T, Host, Port, Options#options{timeout = Timeout}); -check_options([{X,_}=Opt|T], Host, Port, #options{ssh=SshOpts}=Options) -> - case lists:member(X,?VALID_SSH_OPTS) of - true -> - check_options(T, Host, Port, Options#options{ssh=[Opt|SshOpts]}); - false -> - {error, {invalid_option, Opt}} - end. +check_options([{timeout, _} = Opt|_T], _Host, _Port, _Options) -> + {error, {invalid_option, Opt}}; +check_options([Opt|T], Host, Port, #options{ssh=SshOpts}=Options) -> + %% Option verified by ssh + check_options(T, Host, Port, Options#options{ssh=[Opt|SshOpts]}). %%%----------------------------------------------------------------- set_request_timer(infinity) -> diff --git a/lib/common_test/src/ct_release_test.erl b/lib/common_test/src/ct_release_test.erl index 6438ea01c1..c4cbe0c424 100644 --- a/lib/common_test/src/ct_release_test.erl +++ b/lib/common_test/src/ct_release_test.erl @@ -753,7 +753,7 @@ create_relfile(AppsVsns,CreateDir,RelName0,RelVsn) -> %% Should test tools really be included? Some library functions %% here could be used by callback, but not everything since %% processes of these applications will not be running. - TestToolAppsVsns0 = get_vsns([test_server,common_test]), + TestToolAppsVsns0 = get_vsns([common_test]), TestToolAppsVsns = [{A,V,none} || {A,V} <- TestToolAppsVsns0, false == lists:keymember(A,1,AllAppsVsns0)], diff --git a/lib/common_test/src/test_server.erl b/lib/common_test/src/test_server.erl index 73803030a3..671674c617 100644 --- a/lib/common_test/src/test_server.erl +++ b/lib/common_test/src/test_server.erl @@ -63,13 +63,11 @@ init_target_info() -> [$.|Emu] = code:objfile_extension(), {_, OTPRel} = init:script_id(), - TestServerDir = filename:absname(filename:dirname(code:which(?MODULE))), #target_info{os_family=test_server_sup:get_os_family(), os_type=os:type(), version=erlang:system_info(version), system_version=erlang:system_info(system_version), root_dir=code:root_dir(), - test_server_dir=TestServerDir, emulator=Emu, otp_release=OTPRel, username=test_server_sup:get_username(), diff --git a/lib/common_test/src/test_server_internal.hrl b/lib/common_test/src/test_server_internal.hrl index 578f359010..1ec2d83417 100644 --- a/lib/common_test/src/test_server_internal.hrl +++ b/lib/common_test/src/test_server_internal.hrl @@ -30,7 +30,6 @@ version, % string() system_version, % string() root_dir, % string() - test_server_dir, % string() emulator, % string() otp_release, % string() username, % string() diff --git a/lib/common_test/src/test_server_node.erl b/lib/common_test/src/test_server_node.erl index c12832e0d0..c64399e485 100644 --- a/lib/common_test/src/test_server_node.erl +++ b/lib/common_test/src/test_server_node.erl @@ -307,11 +307,11 @@ start_node_peer(SlaveName, OptList, From, TI) -> HostStr, " ", WaitPort]), % Support for erl_crash_dump files.. - CrashFile = filename:join([TI#target_info.test_server_dir, + CrashDir = test_server_sup:crash_dump_dir(), + CrashFile = filename:join([CrashDir, "erl_crash_dump."++cast_to_list(SlaveName)]), CrashArgs = lists:concat([" -env ERL_CRASH_DUMP \"",CrashFile,"\" "]), FailOnError = start_node_get_option_value(fail_on_error, OptList, true), - Pa = TI#target_info.test_server_dir, Prog0 = start_node_get_option_value(erl, OptList, default), Prog = quote_progname(pick_erl_program(Prog0)), Args = @@ -322,7 +322,6 @@ start_node_peer(SlaveName, OptList, From, TI) -> Cmd = lists:concat([Prog, " -detached ", TI#target_info.naming, " ", SlaveName, - " -pa \"", Pa,"\"", NodeStarted, CrashArgs, " ", Args]), @@ -370,15 +369,15 @@ wait_for_node_started_fun(LSock, Tmo, Cleanup, TI, Self) -> %% Slave nodes are started on a remote host if %% - the option remote is given when calling test_server:start_node/3 %% -start_node_slave(SlaveName, OptList, From, TI) -> +start_node_slave(SlaveName, OptList, From, _TI) -> SuppliedArgs = start_node_get_option_value(args, OptList, []), Cleanup = start_node_get_option_value(cleanup, OptList, true), - CrashFile = filename:join([TI#target_info.test_server_dir, + CrashDir = test_server_sup:crash_dump_dir(), + CrashFile = filename:join([CrashDir, "erl_crash_dump."++cast_to_list(SlaveName)]), CrashArgs = lists:concat([" -env ERL_CRASH_DUMP \"",CrashFile,"\" "]), - Pa = TI#target_info.test_server_dir, - Args = lists:concat([" -pa \"", Pa, "\" ", SuppliedArgs, CrashArgs]), + Args = lists:concat([" ", SuppliedArgs, CrashArgs]), Prog0 = start_node_get_option_value(erl, OptList, default), Prog = pick_erl_program(Prog0), diff --git a/lib/common_test/src/test_server_sup.erl b/lib/common_test/src/test_server_sup.erl index fc2cfd57bd..1c0eb18d70 100644 --- a/lib/common_test/src/test_server_sup.erl +++ b/lib/common_test/src/test_server_sup.erl @@ -594,7 +594,8 @@ cleanup_crash_dumps() -> delete_files(Dumps). crash_dump_dir() -> - filename:dirname(code:which(?MODULE)). + {ok,Dir} = test_server_sup:framework_call(get_log_dir,[]), + Dir. tar_crash_dumps() -> Dir = crash_dump_dir(), diff --git a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl index 49b02d2bba..9d4c798795 100644 --- a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl +++ b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl @@ -332,7 +332,8 @@ invalid_opt(Config) -> Opts1 = ?DEFAULT_SSH_OPTS(DataDir) ++ [{timeout,invalidvalue}], {error,{invalid_option,{timeout,invalidvalue}}} = ct_netconfc:open(Opts1), Opts2 = ?DEFAULT_SSH_OPTS(DataDir) ++ [{some_other_opt,true}], - {error,{invalid_option,{some_other_opt,true}}} = ct_netconfc:open(Opts2), + {error,{ssh,could_not_connect_to_server,{options,_}}} = + ct_netconfc:open(Opts2), ok. timeout_close_session(Config) -> diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl index 43ce9a7172..ab67c8164b 100644 --- a/lib/compiler/src/sys_core_fold.erl +++ b/lib/compiler/src/sys_core_fold.erl @@ -277,7 +277,7 @@ expr(#c_fun{}=Fun, effect, _) -> add_warning(Fun, useless_building), void(); expr(#c_fun{vars=Vs0,body=B0}=Fun, Ctxt0, Sub0) -> - {Vs1,Sub1} = pattern_list(Vs0, Sub0), + {Vs1,Sub1} = var_list(Vs0, Sub0), Ctxt = case Ctxt0 of {letrec,Ctxt1} -> Ctxt1; value -> value @@ -420,13 +420,13 @@ expr(#c_try{anno=A,arg=E0,vars=Vs0,body=B0,evars=Evs0,handler=H0}=Try, _, Sub0) %% Here is the general try/catch construct outside of guards. %% We can remove try if the value is simple and replace it with a let. E1 = body(E0, value, Sub0), - {Vs1,Sub1} = pattern_list(Vs0, Sub0), + {Vs1,Sub1} = var_list(Vs0, Sub0), B1 = body(B0, value, Sub1), case is_safe_simple(E1, Sub0) of true -> expr(#c_let{anno=A,vars=Vs1,arg=E1,body=B1}, value, Sub0); false -> - {Evs1,Sub2} = pattern_list(Evs0, Sub0), + {Evs1,Sub2} = var_list(Evs0, Sub0), H1 = body(H0, value, Sub2), Try#c_try{arg=E1,vars=Vs1,body=B1,evars=Evs1,handler=H1} end. @@ -1078,15 +1078,28 @@ is_atom_or_var(_) -> false. %% clause(Clause, Cepxr, Context, Sub) -> Clause. -clause(#c_clause{pats=Ps0,guard=G0,body=B0}=Cl, Cexpr, Ctxt, Sub0) -> - {Ps1,Sub1} = pattern_list(Ps0, Sub0), +clause(#c_clause{pats=Ps0}=Cl, Cexpr, Ctxt, Sub0) -> + try pattern_list(Ps0, Sub0) of + {Ps1,Sub1} -> + clause_1(Cl, Ps1, Cexpr, Ctxt, Sub1) + catch + nomatch -> + Cl#c_clause{anno=[compiler_generated], + guard=#c_literal{val=false}} + end. + +clause_1(#c_clause{guard=G0,body=B0}=Cl, Ps1, Cexpr, Ctxt, Sub1) -> Sub2 = update_types(Cexpr, Ps1, Sub1), - GSub = case {Cexpr,Ps1} of - {#c_var{name='_'},_} -> + GSub = case {Cexpr,Ps1,G0} of + {_,_,#c_literal{}} -> + %% No need for substitution tricks when the guard + %% does not contain any variables. + Sub2; + {#c_var{name='_'},_,_} -> %% In a 'receive', Cexpr is the variable '_', which represents the %% message being matched. We must NOT do any extra substiutions. Sub2; - {#c_var{},[#c_var{}=Var]} -> + {#c_var{},[#c_var{}=Var],_} -> %% The idea here is to optimize expressions such as %% %% case A of A -> ... @@ -1120,7 +1133,7 @@ clause(#c_clause{pats=Ps0,guard=G0,body=B0}=Cl, Cexpr, Ctxt, Sub0) -> %% the unsubstituted variables and values. let_substs(Vs0, As0, Sub0) -> - {Vs1,Sub1} = pattern_list(Vs0, Sub0), + {Vs1,Sub1} = var_list(Vs0, Sub0), {Vs2,As1,Ss} = let_substs_1(Vs1, As0, Sub1), Sub2 = sub_add_scope([V || #c_var{name=V} <- Vs2], Sub1), {Vs2,As1, @@ -1206,20 +1219,132 @@ bin_pattern_list(Ps0, Isub, Osub0) -> {Ps,{_,Osub}} = mapfoldl(fun bin_pattern/2, {Isub,Osub0}, Ps0), {Ps,Osub}. -bin_pattern(#c_bitstr{val=E0,size=Size0}=Pat, {Isub0,Osub0}) -> +bin_pattern(#c_bitstr{val=E0,size=Size0}=Pat0, {Isub0,Osub0}) -> Size1 = expr(Size0, Isub0), {E1,Osub} = pattern(E0, Isub0, Osub0), Isub = case E0 of #c_var{} -> sub_set_var(E0, E1, Isub0); _ -> Isub0 end, - {Pat#c_bitstr{val=E1,size=Size1},{Isub,Osub}}. + Pat = Pat0#c_bitstr{val=E1,size=Size1}, + bin_pat_warn(Pat), + {Pat,{Isub,Osub}}. pattern_list(Ps, Sub) -> pattern_list(Ps, Sub, Sub). pattern_list(Ps0, Isub, Osub0) -> mapfoldl(fun (P, Osub) -> pattern(P, Isub, Osub) end, Osub0, Ps0). +%% var_list([Var], InSub) -> {Pattern,OutSub}. +%% Works like pattern_list/2 but only accept variables and is +%% guaranteed not to throw an exception. + +var_list(Vs, Sub0) -> + mapfoldl(fun (#c_var{}=V, Sub) -> + pattern(V, Sub, Sub) + end, Sub0, Vs). + + +%%% +%%% Generate warnings for binary patterns that will not match. +%%% + +bin_pat_warn(#c_bitstr{type=#c_literal{val=Type}, + val=Val0, + size=#c_literal{val=Sz}, + unit=#c_literal{val=Unit}, + flags=Fl}=Pat) -> + case {Type,Sz} of + {_,_} when is_integer(Sz), Sz >= 0 -> ok; + {binary,all} -> ok; + {utf8,undefined} -> ok; + {utf16,undefined} -> ok; + {utf32,undefined} -> ok; + {_,_} -> + add_warning(Pat, {nomatch_bit_syntax_size,Sz}), + throw(nomatch) + end, + case {Type,Val0} of + {integer,#c_literal{val=Val}} when is_integer(Val) -> + Signedness = signedness(Fl), + TotalSz = Sz * Unit, + bit_pat_warn_int(Val, TotalSz, Signedness, Pat); + {float,#c_literal{val=Val}} when is_float(Val) -> + ok; + {utf8,#c_literal{val=Val}} when is_integer(Val) -> + bit_pat_warn_unicode(Val, Pat); + {utf16,#c_literal{val=Val}} when is_integer(Val) -> + bit_pat_warn_unicode(Val, Pat); + {utf32,#c_literal{val=Val}} when is_integer(Val) -> + bit_pat_warn_unicode(Val, Pat); + {_,#c_literal{val=Val}} -> + add_warning(Pat, {nomatch_bit_syntax_type,Val,Type}), + throw(nomatch); + {_,_} -> + ok + end; +bin_pat_warn(#c_bitstr{type=#c_literal{val=Type},val=Val0,flags=Fl}=Pat) -> + %% Size is variable. Not much that we can check. + case {Type,Val0} of + {integer,#c_literal{val=Val}} when is_integer(Val) -> + case signedness(Fl) of + unsigned when Val < 0 -> + add_warning(Pat, {nomatch_bit_syntax_unsigned,Val}), + throw(nomatch); + _ -> + ok + end; + {float,#c_literal{val=Val}} when is_float(Val) -> + ok; + {_,#c_literal{val=Val}} -> + add_warning(Pat, {nomatch_bit_syntax_type,Val,Type}), + throw(nomatch); + {_,_} -> + ok + end. + +bit_pat_warn_int(Val, 0, signed, Pat) -> + if + Val =:= 0 -> + ok; + true -> + add_warning(Pat, {nomatch_bit_syntax_truncated,signed,Val,0}), + throw(nomatch) + end; +bit_pat_warn_int(Val, Sz, signed, Pat) -> + if + Val < 0, Val bsr (Sz - 1) =/= -1 -> + add_warning(Pat, {nomatch_bit_syntax_truncated,signed,Val,Sz}), + throw(nomatch); + Val > 0, Val bsr (Sz - 1) =/= 0 -> + add_warning(Pat, {nomatch_bit_syntax_truncated,signed,Val,Sz}), + throw(nomatch); + true -> + ok + end; +bit_pat_warn_int(Val, _Sz, unsigned, Pat) when Val < 0 -> + add_warning(Pat, {nomatch_bit_syntax_unsigned,Val}), + throw(nomatch); +bit_pat_warn_int(Val, Sz, unsigned, Pat) -> + if + Val bsr Sz =:= 0 -> + ok; + true -> + add_warning(Pat, {nomatch_bit_syntax_truncated,unsigned,Val,Sz}), + throw(nomatch) + end. + +bit_pat_warn_unicode(U, _Pat) when 0 =< U, U =< 16#10FFFF -> + ok; +bit_pat_warn_unicode(U, Pat) -> + add_warning(Pat, {nomatch_bit_syntax_unicode,U}), + throw(nomatch). + +signedness(#c_literal{val=Flags}) -> + [S] = [F || F <- Flags, F =:= signed orelse F =:= unsigned], + S. + + %% is_subst(Expr) -> true | false. %% Test whether an expression is a suitable substitution. @@ -2251,11 +2376,11 @@ move_let_into_expr(#c_let{vars=InnerVs0,body=InnerBody0}=Inner, %% Arg = body(Arg0, Sub0), ScopeSub0 = sub_subst_scope(Sub0#sub{t=#{}}), - {OuterVs,ScopeSub} = pattern_list(OuterVs0, ScopeSub0), + {OuterVs,ScopeSub} = var_list(OuterVs0, ScopeSub0), OuterBody = body(OuterBody0, ScopeSub), - {InnerVs,Sub} = pattern_list(InnerVs0, Sub0), + {InnerVs,Sub} = var_list(InnerVs0, Sub0), InnerBody = body(InnerBody0, Sub), Outer#c_let{vars=OuterVs,arg=Arg, body=Inner#c_let{vars=InnerVs,arg=OuterBody,body=InnerBody}}; @@ -2271,39 +2396,49 @@ move_let_into_expr(#c_let{vars=Lvs0,body=Lbody0}=Let, case {TwoClauses,is_failing_clause(Ca0),is_failing_clause(Cb0)} of {true,false,true} -> %% let <Lvars> = case <Case-expr> of - %% <Cvars> -> <Clause-body>; - %% <OtherCvars> -> erlang:error(...) + %% <Cpats> -> <Clause-body>; + %% <OtherCpats> -> erlang:error(...) %% end %% in <Let-body> %% %% ==> %% %% case <Case-expr> of - %% <Cvars> -> + %% <Cpats> -> %% let <Lvars> = <Clause-body> %% in <Let-body>; - %% <OtherCvars> -> erlang:error(...) + %% <OtherCpats> -> erlang:error(...) %% end Cexpr = body(Cexpr0, Sub0), - CaVars0 = Ca0#c_clause.pats, + CaPats0 = Ca0#c_clause.pats, G0 = Ca0#c_clause.guard, B0 = Ca0#c_clause.body, ScopeSub0 = sub_subst_scope(Sub0#sub{t=#{}}), - {CaVars,ScopeSub} = pattern_list(CaVars0, ScopeSub0), - G = guard(G0, ScopeSub), - - B1 = body(B0, ScopeSub), - - {Lvs,B2,Sub1} = let_substs(Lvs0, B1, Sub0), - Sub2 = Sub1#sub{s=cerl_sets:union(ScopeSub#sub.s, - Sub1#sub.s)}, - Lbody = body(Lbody0, Sub2), - B = Let#c_let{vars=Lvs,arg=core_lib:make_values(B2),body=Lbody}, - - Ca = Ca0#c_clause{pats=CaVars,guard=G,body=B}, - Cb = clause(Cb0, Cexpr, value, Sub0), - Case#c_case{arg=Cexpr,clauses=[Ca,Cb]}; + try pattern_list(CaPats0, ScopeSub0) of + {CaPats,ScopeSub} -> + G = guard(G0, ScopeSub), + + B1 = body(B0, ScopeSub), + + {Lvs,B2,Sub1} = let_substs(Lvs0, B1, Sub0), + Sub2 = Sub1#sub{s=cerl_sets:union(ScopeSub#sub.s, + Sub1#sub.s)}, + Lbody = body(Lbody0, Sub2), + B = Let#c_let{vars=Lvs, + arg=core_lib:make_values(B2), + body=Lbody}, + + Ca = Ca0#c_clause{pats=CaPats,guard=G,body=B}, + Cb = clause(Cb0, Cexpr, value, Sub0), + Case#c_case{arg=Cexpr,clauses=[Ca,Cb]} + catch + nomatch -> + %% This is not a defeat. The code will eventually + %% be optimized to erlang:error(...) by the other + %% optimizations done in this module. + impossible + end; {_,_,_} -> impossible end; move_let_into_expr(#c_let{vars=Lvs0,body=Lbody0}=Let, @@ -2595,7 +2730,7 @@ move_case_into_arg(#c_case{arg=#c_let{vars=OuterVars0,arg=OuterArg, %% in case <InnerArg> of <InnerClauses> end %% ScopeSub0 = sub_subst_scope(Sub#sub{t=#{}}), - {OuterVars,ScopeSub} = pattern_list(OuterVars0, ScopeSub0), + {OuterVars,ScopeSub} = var_list(OuterVars0, ScopeSub0), InnerArg = body(InnerArg0, ScopeSub), Outer#c_let{vars=OuterVars,arg=OuterArg, body=Inner#c_case{arg=InnerArg,clauses=InnerClauses}}; @@ -2624,14 +2759,18 @@ move_case_into_arg(#c_case{arg=#c_case{arg=OuterArg, %% end %% ScopeSub0 = sub_subst_scope(Sub#sub{t=#{}}), - {OuterPats,ScopeSub} = pattern_list(OuterPats0, ScopeSub0), - OuterGuard = guard(OuterGuard0, ScopeSub), - InnerArg = body(InnerArg0, ScopeSub), - Inner = Inner0#c_case{arg=InnerArg,clauses=InnerClauses}, - OuterCa = OuterCa0#c_clause{pats=OuterPats,guard=OuterGuard, - body=Inner}, - Outer#c_case{arg=OuterArg, - clauses=[OuterCa,OuterCb]}; + + %% We KNOW that pattern_list/2 has already been called for OuterPats0; + %% therefore, it cannot throw an exception. + {OuterPats,ScopeSub} = pattern_list(OuterPats0, ScopeSub0), + OuterGuard = guard(OuterGuard0, ScopeSub), + InnerArg = body(InnerArg0, ScopeSub), + Inner = Inner0#c_case{arg=InnerArg,clauses=InnerClauses}, + OuterCa = OuterCa0#c_clause{pats=OuterPats, + guard=OuterGuard, + body=Inner}, + Outer#c_case{arg=OuterArg, + clauses=[OuterCa,OuterCb]}; false -> impossible end; @@ -3213,6 +3352,29 @@ format_error(nomatch_shadow) -> "this clause cannot match because a previous clause always matches"; format_error(nomatch_guard) -> "the guard for this clause evaluates to 'false'"; +format_error({nomatch_bit_syntax_truncated,Signess,Val,Sz}) -> + S = case Signess of + signed -> "a 'signed'"; + unsigned -> "an 'unsigned'" + end, + F = "this clause cannot match because the value ~P" + " will not fit in ~s binary segment of size ~p", + flatten(io_lib:format(F, [Val,10,S,Sz])); +format_error({nomatch_bit_syntax_unsigned,Val}) -> + F = "this clause cannot match because the negative value ~P" + " will never match the value of an 'unsigned' binary segment", + flatten(io_lib:format(F, [Val,10])); +format_error({nomatch_bit_syntax_size,Sz}) -> + F = "this clause cannot match because '~P' is not a valid size for a binary segment", + flatten(io_lib:format(F, [Sz,10])); +format_error({nomatch_bit_syntax_type,Val,Type}) -> + F = "this clause cannot match because '~P' is not of the" + " expected type '~p'", + flatten(io_lib:format(F, [Val,10,Type])); +format_error({nomatch_bit_syntax_unicode,Val}) -> + F = "this clause cannot match because the value ~p" + " is not a valid Unicode code point", + flatten(io_lib:format(F, [Val])); format_error(no_clause_match) -> "no clause will ever match"; format_error(nomatch_clause_type) -> diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl index 72649e5c9f..68c9f964d8 100644 --- a/lib/compiler/src/v3_core.erl +++ b/lib/compiler/src/v3_core.erl @@ -1653,10 +1653,12 @@ pat_alias_map_pairs_1([]) -> []. pat_bin(Ps, St) -> [pat_segment(P, St) || P <- Ps]. -pat_segment({bin_element,_,Val,Size,[Type,{unit,Unit}|Flags]}, St) -> +pat_segment({bin_element,L,Val,Size,[Type,{unit,Unit}|Flags]}, St) -> + Anno = lineno_anno(L, St), {Pval,[],St1} = pattern(Val,St), {Psize,[],_St2} = pattern(Size,St1), - #c_bitstr{val=Pval,size=Psize, + #c_bitstr{anno=Anno, + val=Pval,size=Psize, unit=#c_literal{val=Unit}, type=#c_literal{val=Type}, flags=#c_literal{val=Flags}}. diff --git a/lib/compiler/test/andor_SUITE.erl b/lib/compiler/test/andor_SUITE.erl index 264dc38907..9736f75fe8 100644 --- a/lib/compiler/test/andor_SUITE.erl +++ b/lib/compiler/test/andor_SUITE.erl @@ -54,28 +54,28 @@ end_per_group(_GroupName, Config) -> t_case(Config) when is_list(Config) -> %% We test boolean cases almost but not quite like cases %% generated by andalso/orelse. - ?line less = t_case_a(1, 2), - ?line not_less = t_case_a(2, 2), - ?line {'EXIT',{{case_clause,false},_}} = (catch t_case_b({x,y,z}, 2)), - ?line {'EXIT',{{case_clause,true},_}} = (catch t_case_b(a, a)), - ?line eq = t_case_c(a, a), - ?line ne = t_case_c(42, []), - ?line t = t_case_d(x, x, true), - ?line f = t_case_d(x, x, false), - ?line f = t_case_d(x, y, true), - ?line {'EXIT',{badarg,_}} = (catch t_case_d(x, y, blurf)), - ?line true = (catch t_case_e({a,b}, {a,b})), - ?line false = (catch t_case_e({a,b}, 42)), - - ?line true = t_case_xy(42, 100, 700), - ?line true = t_case_xy(42, 100, whatever), - ?line false = t_case_xy(42, wrong, 700), - ?line false = t_case_xy(42, wrong, whatever), - - ?line true = t_case_xy(0, whatever, 700), - ?line true = t_case_xy(0, 100, 700), - ?line false = t_case_xy(0, whatever, wrong), - ?line false = t_case_xy(0, 100, wrong), + less = t_case_a(1, 2), + not_less = t_case_a(2, 2), + {'EXIT',{{case_clause,false},_}} = (catch t_case_b({x,y,z}, 2)), + {'EXIT',{{case_clause,true},_}} = (catch t_case_b(a, a)), + eq = t_case_c(a, a), + ne = t_case_c(42, []), + t = t_case_d(x, x, true), + f = t_case_d(x, x, false), + f = t_case_d(x, y, true), + {'EXIT',{badarg,_}} = (catch t_case_d(x, y, blurf)), + true = (catch t_case_e({a,b}, {a,b})), + false = (catch t_case_e({a,b}, 42)), + + true = t_case_xy(42, 100, 700), + true = t_case_xy(42, 100, whatever), + false = t_case_xy(42, wrong, 700), + false = t_case_xy(42, wrong, whatever), + + true = t_case_xy(0, whatever, 700), + true = t_case_xy(0, 100, 700), + false = t_case_xy(0, whatever, wrong), + false = t_case_xy(0, 100, wrong), ok. @@ -135,35 +135,35 @@ t_case_y(X, Y, Z) -> end). t_and_or(Config) when is_list(Config) -> - ?line true = true and true, - ?line false = true and false, - ?line false = false and true, - ?line false = false and false, - - ?line true = id(true) and true, - ?line false = id(true) and false, - ?line false = id(false) and true, - ?line false = id(false) and false, - - ?line true = true and id(true), - ?line false = true and id(false), - ?line false = false and id(true), - ?line false = false and id(false), - - ?line true = true or true, - ?line true = true or false, - ?line true = false or true, - ?line false = false or false, - - ?line true = id(true) or true, - ?line true = id(true) or false, - ?line true = id(false) or true, - ?line false = id(false) or false, - - ?line true = true or id(true), - ?line true = true or id(false), - ?line true = false or id(true), - ?line false = false or id(false), + true = true and true, + false = true and false, + false = false and true, + false = false and false, + + true = id(true) and true, + false = id(true) and false, + false = id(false) and true, + false = id(false) and false, + + true = true and id(true), + false = true and id(false), + false = false and id(true), + false = false and id(false), + + true = true or true, + true = true or false, + true = false or true, + false = false or false, + + true = id(true) or true, + true = id(true) or false, + true = id(false) or true, + false = id(false) or false, + + true = true or id(true), + true = true or id(false), + true = false or id(true), + false = false or id(false), True = id(true), @@ -187,28 +187,28 @@ t_andalso(Config) when is_list(Config) -> Ps = [{X,Y} || X <- Bs, Y <- Bs], lists:foreach(fun (P) -> t_andalso_1(P) end, Ps), - ?line true = true andalso true, - ?line false = true andalso false, - ?line false = false andalso true, - ?line false = false andalso false, + true = true andalso true, + false = true andalso false, + false = false andalso true, + false = false andalso false, - ?line true = ?GUARD(true andalso true), - ?line false = ?GUARD(true andalso false), - ?line false = ?GUARD(false andalso true), - ?line false = ?GUARD(false andalso false), + true = ?GUARD(true andalso true), + false = ?GUARD(true andalso false), + false = ?GUARD(false andalso true), + false = ?GUARD(false andalso false), - ?line false = false andalso glurf, - ?line false = false andalso exit(exit_now), + false = false andalso glurf, + false = false andalso exit(exit_now), - ?line true = not id(false) andalso not id(false), - ?line false = not id(false) andalso not id(true), - ?line false = not id(true) andalso not id(false), - ?line false = not id(true) andalso not id(true), + true = not id(false) andalso not id(false), + false = not id(false) andalso not id(true), + false = not id(true) andalso not id(false), + false = not id(true) andalso not id(true), - ?line {'EXIT',{badarg,_}} = (catch not id(glurf) andalso id(true)), - ?line {'EXIT',{badarg,_}} = (catch not id(false) andalso not id(glurf)), - ?line false = id(false) andalso not id(glurf), - ?line false = false andalso not id(glurf), + {'EXIT',{badarg,_}} = (catch not id(glurf) andalso id(true)), + {'EXIT',{badarg,_}} = (catch not id(false) andalso not id(glurf)), + false = id(false) andalso not id(glurf), + false = false andalso not id(glurf), true = begin (X1 = true) andalso X1, X1 end, false = false = begin (X2 = false) andalso X2, X2 end, @@ -220,28 +220,28 @@ t_orelse(Config) when is_list(Config) -> Ps = [{X,Y} || X <- Bs, Y <- Bs], lists:foreach(fun (P) -> t_orelse_1(P) end, Ps), - ?line true = true orelse true, - ?line true = true orelse false, - ?line true = false orelse true, - ?line false = false orelse false, + true = true orelse true, + true = true orelse false, + true = false orelse true, + false = false orelse false, - ?line true = ?GUARD(true orelse true), - ?line true = ?GUARD(true orelse false), - ?line true = ?GUARD(false orelse true), - ?line false = ?GUARD(false orelse false), + true = ?GUARD(true orelse true), + true = ?GUARD(true orelse false), + true = ?GUARD(false orelse true), + false = ?GUARD(false orelse false), - ?line true = true orelse glurf, - ?line true = true orelse exit(exit_now), + true = true orelse glurf, + true = true orelse exit(exit_now), - ?line true = not id(false) orelse not id(false), - ?line true = not id(false) orelse not id(true), - ?line true = not id(true) orelse not id(false), - ?line false = not id(true) orelse not id(true), + true = not id(false) orelse not id(false), + true = not id(false) orelse not id(true), + true = not id(true) orelse not id(false), + false = not id(true) orelse not id(true), - ?line {'EXIT',{badarg,_}} = (catch not id(glurf) orelse id(true)), - ?line {'EXIT',{badarg,_}} = (catch not id(true) orelse not id(glurf)), - ?line true = id(true) orelse not id(glurf), - ?line true = true orelse not id(glurf), + {'EXIT',{badarg,_}} = (catch not id(glurf) orelse id(true)), + {'EXIT',{badarg,_}} = (catch not id(true) orelse not id(glurf)), + true = id(true) orelse not id(glurf), + true = true orelse not id(glurf), true = begin (X1 = true) orelse X1, X1 end, false = begin (X2 = false) orelse X2, X2 end, @@ -255,7 +255,7 @@ t_andalso_1({X,Y}) -> X andalso Y -> true; true -> false end, - check(V1, X and Y). + V1 = id(X and Y). t_orelse_1({X,Y}) -> io:fwrite("~w orelse ~w: ",[X,Y]), @@ -264,19 +264,19 @@ t_orelse_1({X,Y}) -> X orelse Y -> true; true -> false end, - check(V1, X or Y). + V1 = id(X or Y). inside(Config) when is_list(Config) -> - ?line true = inside(-8, 1), - ?line false = inside(-53.5, -879798), - ?line false = inside(1.0, -879), - ?line false = inside(59, -879), - ?line false = inside(-11, 1.0), - ?line false = inside(100, 0.2), - ?line false = inside(100, 1.2), - ?line false = inside(-53.5, 4), - ?line false = inside(1.0, 5.3), - ?line false = inside(59, 879), + true = inside(-8, 1), + false = inside(-53.5, -879798), + false = inside(1.0, -879), + false = inside(59, -879), + false = inside(-11, 1.0), + false = inside(100, 0.2), + false = inside(100, 1.2), + false = inside(-53.5, 4), + false = inside(1.0, 5.3), + false = inside(59, 879), ok. inside(Xm, Ym) -> @@ -311,15 +311,15 @@ inside_guard(Xm, Ym, X, Y, W, H) -> {false,Xm,Ym,X,Y,W,H}. overlap(Config) when is_list(Config) -> - ?line true = overlap(7.0, 2.0, 8.0, 0.5), - ?line true = overlap(7.0, 2.0, 8.0, 2.5), - ?line true = overlap(7.0, 2.0, 5.3, 2), - ?line true = overlap(7.0, 2.0, 0.0, 100.0), - - ?line false = overlap(-1, 2, -35, 0.5), - ?line false = overlap(-1, 2, 777, 0.5), - ?line false = overlap(-1, 2, 2, 10), - ?line false = overlap(2, 10, 12, 55.3), + true = overlap(7.0, 2.0, 8.0, 0.5), + true = overlap(7.0, 2.0, 8.0, 2.5), + true = overlap(7.0, 2.0, 5.3, 2), + true = overlap(7.0, 2.0, 0.0, 100.0), + + false = overlap(-1, 2, -35, 0.5), + false = overlap(-1, 2, 777, 0.5), + false = overlap(-1, 2, 2, 10), + false = overlap(2, 10, 12, 55.3), ok. overlap(Pos1, Len1, Pos2, Len2) -> @@ -343,33 +343,33 @@ overlap(Pos1, Len1, Pos2, Len2) -> -define(COMB(A,B,C), (A andalso B orelse C)). combined(Config) when is_list(Config) -> - ?line false = comb(false, false, false), - ?line true = comb(false, false, true), - ?line false = comb(false, true, false), - ?line true = comb(false, true, true), - - ?line false = comb(true, false, false), - ?line true = comb(true, true, false), - ?line true = comb(true, false, true), - ?line true = comb(true, true, true), - - ?line false = comb(false, blurf, false), - ?line true = comb(false, blurf, true), - ?line true = comb(true, true, blurf), - - ?line false = ?COMB(false, false, false), - ?line true = ?COMB(false, false, true), - ?line false = ?COMB(false, true, false), - ?line true = ?COMB(false, true, true), - - ?line false = ?COMB(true, false, false), - ?line true = ?COMB(true, true, false), - ?line true = ?COMB(true, false, true), - ?line true = ?COMB(true, true, true), - - ?line false = ?COMB(false, blurf, false), - ?line true = ?COMB(false, blurf, true), - ?line true = ?COMB(true, true, blurf), + false = comb(false, false, false), + true = comb(false, false, true), + false = comb(false, true, false), + true = comb(false, true, true), + + false = comb(true, false, false), + true = comb(true, true, false), + true = comb(true, false, true), + true = comb(true, true, true), + + false = comb(false, blurf, false), + true = comb(false, blurf, true), + true = comb(true, true, blurf), + + false = ?COMB(false, false, false), + true = ?COMB(false, false, true), + false = ?COMB(false, true, false), + true = ?COMB(false, true, true), + + false = ?COMB(true, false, false), + true = ?COMB(true, true, false), + true = ?COMB(true, false, true), + true = ?COMB(true, true, true), + + false = ?COMB(false, blurf, false), + true = ?COMB(false, blurf, true), + true = ?COMB(true, true, blurf), false = simple_comb(false, false), false = simple_comb(false, true), @@ -412,13 +412,13 @@ simple_comb(A, B) -> %% Test that a boolean expression in a case expression is properly %% optimized (in particular, that the error behaviour is correct). in_case(Config) when is_list(Config) -> - ?line edge_rings = in_case_1(1, 1, 1, 1, 1), - ?line not_loop = in_case_1(0.5, 1, 1, 1, 1), - ?line loop = in_case_1(0.5, 0.9, 1.1, 1, 4), - ?line {'EXIT',{badarith,_}} = (catch in_case_1(1, 1, 1, 1, 0)), - ?line {'EXIT',{badarith,_}} = (catch in_case_1(1, 1, 1, 1, nan)), - ?line {'EXIT',{badarg,_}} = (catch in_case_1(1, 1, 1, blurf, 1)), - ?line {'EXIT',{badarith,_}} = (catch in_case_1([nan], 1, 1, 1, 1)), + edge_rings = in_case_1(1, 1, 1, 1, 1), + not_loop = in_case_1(0.5, 1, 1, 1, 1), + loop = in_case_1(0.5, 0.9, 1.1, 1, 4), + {'EXIT',{badarith,_}} = (catch in_case_1(1, 1, 1, 1, 0)), + {'EXIT',{badarith,_}} = (catch in_case_1(1, 1, 1, 1, nan)), + {'EXIT',{badarg,_}} = (catch in_case_1(1, 1, 1, blurf, 1)), + {'EXIT',{badarith,_}} = (catch in_case_1([nan], 1, 1, 1, 1)), ok. in_case_1(LenUp, LenDw, LenN, Rotation, Count) -> @@ -451,23 +451,23 @@ in_case_1_guard(LenUp, LenDw, LenN, Rotation, Count) -> end. before_and_inside_if(Config) when is_list(Config) -> - ?line no = before_and_inside_if([a], [b], delete), - ?line no = before_and_inside_if([a], [b], x), - ?line no = before_and_inside_if([a], [], delete), - ?line no = before_and_inside_if([a], [], x), - ?line no = before_and_inside_if([], [], delete), - ?line yes = before_and_inside_if([], [], x), - ?line yes = before_and_inside_if([], [b], delete), - ?line yes = before_and_inside_if([], [b], x), - - ?line {ch1,ch2} = before_and_inside_if_2([a], [b], blah), - ?line {ch1,ch2} = before_and_inside_if_2([a], [b], xx), - ?line {ch1,ch2} = before_and_inside_if_2([a], [], blah), - ?line {ch1,ch2} = before_and_inside_if_2([a], [], xx), - ?line {no,no} = before_and_inside_if_2([], [b], blah), - ?line {no,no} = before_and_inside_if_2([], [b], xx), - ?line {ch1,no} = before_and_inside_if_2([], [], blah), - ?line {no,ch2} = before_and_inside_if_2([], [], xx), + no = before_and_inside_if([a], [b], delete), + no = before_and_inside_if([a], [b], x), + no = before_and_inside_if([a], [], delete), + no = before_and_inside_if([a], [], x), + no = before_and_inside_if([], [], delete), + yes = before_and_inside_if([], [], x), + yes = before_and_inside_if([], [b], delete), + yes = before_and_inside_if([], [b], x), + + {ch1,ch2} = before_and_inside_if_2([a], [b], blah), + {ch1,ch2} = before_and_inside_if_2([a], [b], xx), + {ch1,ch2} = before_and_inside_if_2([a], [], blah), + {ch1,ch2} = before_and_inside_if_2([a], [], xx), + {no,no} = before_and_inside_if_2([], [b], blah), + {no,no} = before_and_inside_if_2([], [b], xx), + {ch1,no} = before_and_inside_if_2([], [], blah), + {no,ch2} = before_and_inside_if_2([], [], xx), ok. %% Thanks to Simon Cornish and Kostis Sagonas. @@ -539,14 +539,6 @@ slow_compilation_1(T, _) when element(1, T) == a -> %% Utilities. -check(V1, V0) -> - if V1 /= V0 -> - io:fwrite("error: ~w.\n", [V1]), - ?t:fail(); - true -> - io:fwrite("ok: ~w.\n", [V1]) - end. - echo(X) -> io:fwrite("eval(~w); ",[X]), X. diff --git a/lib/compiler/test/apply_SUITE.erl b/lib/compiler/test/apply_SUITE.erl index 868bc674f9..8abcfe9dac 100644 --- a/lib/compiler/test/apply_SUITE.erl +++ b/lib/compiler/test/apply_SUITE.erl @@ -53,44 +53,44 @@ end_per_group(_GroupName, Config) -> -define(APPLY2(M, F, A1, A2), (fun(Res) -> Res = M:F(A1, A2) end)(apply(M, F, [A1,A2]))). mfa(Config) when is_list(Config) -> - ?line ok = ?APPLY0(?MODULE, foo), - ?line {[a,b]} = ?APPLY1(?MODULE, bar, [a,b]), - ?line {39,{a}} = ?APPLY2(?MODULE, baz, 39, {a}), - - ?line Mod = id(?MODULE), - ?line ok = ?APPLY0(Mod, foo), - ?line {[a,b]} = ?APPLY1(Mod, bar, [a,b]), - ?line {39,{a}} = ?APPLY2(Mod, baz, 39, {a}), - - ?line ok = ?APPLY0(?MODULE, (id(foo))), - ?line {[a,b]} = ?APPLY1(?MODULE, (id(bar)), [a,b]), - ?line {39,{a}} = ?APPLY2(?MODULE, (id(baz)), 39, {a}), - - ?line ok = ?APPLY0(Mod, (id(foo))), - ?line {[a,b]} = ?APPLY1(Mod, (id(bar)), [a,b]), - ?line {39,{a}} = ?APPLY2(Mod, (id(baz)), 39, {a}), - - ?line {'EXIT',_} = (catch ?APPLY2(Mod, (id(bazzzzzz)), a, b)), - ?line {'EXIT',_} = (catch ?APPLY2({}, baz, a, b)), - ?line {'EXIT',_} = (catch ?APPLY2(?MODULE, [], a, b)), - - ?line ok = apply(Mod, foo, id([])), - ?line {[a,b|c]} = apply(Mod, bar, id([[a,b|c]])), - ?line {[xx],{a}} = apply(?MODULE, baz, id([[xx],{a}])), - - ?line Erlang = id(erlang), - ?line Self = self(), - ?line Self = ?APPLY0(Erlang, self), - ?line 42.0 = ?APPLY1(Erlang, abs, -42.0), - ?line b = ?APPLY2(Erlang, element, 2, {a,b,c}), - ?line true = ?APPLY1(Erlang, is_function, fun erlang:list_to_binary/1), - ?line true = ?APPLY1(Erlang, is_function, fun() -> ok end), - ?line false = ?APPLY1(Erlang, is_function, blurf), - ?line true = ?APPLY2(Erlang, is_function, fun erlang:list_to_binary/1, 1), - ?line true = ?APPLY2(Erlang, is_function, fun() -> ok end, 0), - ?line false = ?APPLY2(Erlang, is_function, blurf, 0), - - ?line apply(Mod, foo, []). + ok = ?APPLY0(?MODULE, foo), + {[a,b]} = ?APPLY1(?MODULE, bar, [a,b]), + {39,{a}} = ?APPLY2(?MODULE, baz, 39, {a}), + + Mod = id(?MODULE), + ok = ?APPLY0(Mod, foo), + {[a,b]} = ?APPLY1(Mod, bar, [a,b]), + {39,{a}} = ?APPLY2(Mod, baz, 39, {a}), + + ok = ?APPLY0(?MODULE, (id(foo))), + {[a,b]} = ?APPLY1(?MODULE, (id(bar)), [a,b]), + {39,{a}} = ?APPLY2(?MODULE, (id(baz)), 39, {a}), + + ok = ?APPLY0(Mod, (id(foo))), + {[a,b]} = ?APPLY1(Mod, (id(bar)), [a,b]), + {39,{a}} = ?APPLY2(Mod, (id(baz)), 39, {a}), + + {'EXIT',_} = (catch ?APPLY2(Mod, (id(bazzzzzz)), a, b)), + {'EXIT',_} = (catch ?APPLY2({}, baz, a, b)), + {'EXIT',_} = (catch ?APPLY2(?MODULE, [], a, b)), + + ok = apply(Mod, foo, id([])), + {[a,b|c]} = apply(Mod, bar, id([[a,b|c]])), + {[xx],{a}} = apply(?MODULE, baz, id([[xx],{a}])), + + Erlang = id(erlang), + Self = self(), + Self = ?APPLY0(Erlang, self), + 42.0 = ?APPLY1(Erlang, abs, -42.0), + b = ?APPLY2(Erlang, element, 2, {a,b,c}), + true = ?APPLY1(Erlang, is_function, fun erlang:list_to_binary/1), + true = ?APPLY1(Erlang, is_function, fun() -> ok end), + false = ?APPLY1(Erlang, is_function, blurf), + true = ?APPLY2(Erlang, is_function, fun erlang:list_to_binary/1, 1), + true = ?APPLY2(Erlang, is_function, fun() -> ok end, 0), + false = ?APPLY2(Erlang, is_function, blurf, 0), + + apply(Mod, foo, []). foo() -> ok. @@ -106,21 +106,21 @@ baz(A, B) -> -define(FUNAPPLY2(F, A1, A2), (fun(Res) -> Res = F(A1, A2) end)(apply(F, [A1,A2]))). fun_apply(Config) when is_list(Config) -> - ?line Self = self(), + Self = self(), - ?line Self = ?FUNAPPLY0(fun() -> self() end), - ?line Self = ?FUNAPPLY0((id(fun() -> self() end))), - ?line ok = ?FUNAPPLY0(fun ?MODULE:foo/0), - ?line ok = ?FUNAPPLY0((id(fun ?MODULE:foo/0))), + Self = ?FUNAPPLY0(fun() -> self() end), + Self = ?FUNAPPLY0((id(fun() -> self() end))), + ok = ?FUNAPPLY0(fun ?MODULE:foo/0), + ok = ?FUNAPPLY0((id(fun ?MODULE:foo/0))), - ?line -42 = ?FUNAPPLY1(fun(A) -> -A end, 42), - ?line [x,yy] = ?FUNAPPLY1((id(fun(T) -> [x|T] end)), [yy]), - ?line {[a|b]} = ?FUNAPPLY1(fun ?MODULE:bar/1, [a|b]), - ?line {[a|b]} = ?FUNAPPLY1((id(fun ?MODULE:bar/1)), [a|b]), + -42 = ?FUNAPPLY1(fun(A) -> -A end, 42), + [x,yy] = ?FUNAPPLY1((id(fun(T) -> [x|T] end)), [yy]), + {[a|b]} = ?FUNAPPLY1(fun ?MODULE:bar/1, [a|b]), + {[a|b]} = ?FUNAPPLY1((id(fun ?MODULE:bar/1)), [a|b]), - ?line {a,b} = ?FUNAPPLY2(fun(A, B) -> {A,B} end, a, b), - ?line {a,[b]} = ?FUNAPPLY2((id(fun(A, B) -> {A,B} end)), a, [b]), - ?line {42,{a}} = ?FUNAPPLY2((id(fun ?MODULE:baz/2)), 42, {a}), + {a,b} = ?FUNAPPLY2(fun(A, B) -> {A,B} end, a, b), + {a,[b]} = ?FUNAPPLY2((id(fun(A, B) -> {A,B} end)), a, [b]), + {42,{a}} = ?FUNAPPLY2((id(fun ?MODULE:baz/2)), 42, {a}), ok. diff --git a/lib/compiler/test/beam_disasm_SUITE.erl b/lib/compiler/test/beam_disasm_SUITE.erl index 4268729e75..90598d9639 100644 --- a/lib/compiler/test/beam_disasm_SUITE.erl +++ b/lib/compiler/test/beam_disasm_SUITE.erl @@ -46,21 +46,20 @@ init_per_group(_GroupName, Config) -> end_per_group(_GroupName, Config) -> Config. -stripped(doc) -> - ["Check that stripped beam files can be disassembled"]; +%% Check that stripped beam files can be disassembled. stripped(Config) when is_list(Config) -> - ?line PrivDir = ?config(priv_dir, Config), - ?line SrcName = filename:join(PrivDir, "tmp.erl"), - ?line BeamName = filename:join(PrivDir, "tmp.beam"), + PrivDir = proplists:get_value(priv_dir, Config), + SrcName = filename:join(PrivDir, "tmp.erl"), + BeamName = filename:join(PrivDir, "tmp.beam"), Prog = <<"-module(tmp).\n-export([tmp/0]).\ntmp()->ok.\n">>, - ?line ok = file:write_file(SrcName, Prog), - ?line {ok, tmp} = + ok = file:write_file(SrcName, Prog), + {ok, tmp} = compile:file(SrcName, [{outdir, PrivDir}]), - ?line {beam_file, tmp, _, Attr, CompileInfo, [_|_]} = + {beam_file, tmp, _, Attr, CompileInfo, [_|_]} = beam_disasm:file(BeamName), - ?line true = is_list(Attr), - ?line true = is_list(CompileInfo), - ?line {ok, {tmp, _}} = beam_lib:strip(BeamName), - ?line {beam_file, tmp, _, [], [], [_|_]} = + true = is_list(Attr), + true = is_list(CompileInfo), + {ok, {tmp, _}} = beam_lib:strip(BeamName), + {beam_file, tmp, _, [], [], [_|_]} = beam_disasm:file(BeamName), ok. diff --git a/lib/compiler/test/beam_validator_SUITE.erl b/lib/compiler/test/beam_validator_SUITE.erl index cb217e4655..d27512b6eb 100644 --- a/lib/compiler/test/beam_validator_SUITE.erl +++ b/lib/compiler/test/beam_validator_SUITE.erl @@ -37,15 +37,14 @@ -include_lib("common_test/include/ct.hrl"). init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) -> - Dog = test_server:timetrap(?t:minutes(10)), - [{watchdog,Dog}|Config]. + Config. end_per_testcase(Case, Config) when is_atom(Case), is_list(Config) -> - Dog = ?config(watchdog, Config), - ?t:timetrap_cancel(Dog), ok. -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,10}}]. all() -> test_lib:recompile(?MODULE), @@ -78,7 +77,7 @@ end_per_group(_GroupName, Config) -> compiler_bug(Config) when is_list(Config) -> %% Check that the compiler returns an error if we try to %% assemble one of the bad '.S' files. - Data = ?config(data_dir, Config), + Data = proplists:get_value(data_dir, Config), File = filename:join(Data, "compiler_bug"), error = compile:file(File, [from_asm,report_errors,time]), @@ -93,43 +92,41 @@ compiler_bug(Config) when is_list(Config) -> %% The following code is stupid but it should compile. stupid_but_valid(Config) when is_list(Config) -> AnAtom = nisse, - ?line try setelement(5, setelement(6, AnAtom, value), another_value) of - Term -> ?line ?t:fail({what_happened,Term}) - catch - error:badarg -> ok - end, + try setelement(5, setelement(6, AnAtom, value), another_value) of + Term -> ct:fail({what_happened,Term}) + catch + error:badarg -> ok + end, ok. xrange(Config) when is_list(Config) -> Errors = do_val(xrange, Config), - ?line - [{{t,sum_1,2}, - {{bif,'+',{f,0},[{x,-1},{x,1}],{x,0}},4, - {uninitialized_reg,{x,-1}}}}, - {{t,sum_2,2}, - {{bif,'+',{f,0},[{x,0},{x,1023}],{x,0}},4, - {uninitialized_reg,{x,1023}}}}, - {{t,sum_3,2}, - {{bif,'+',{f,0},[{x,0},{x,1}],{x,-1}},4, - {invalid_store,{x,-1},number}}}, - {{t,sum_4,2}, - {{bif,'+',{f,0},[{x,0},{x,1}],{x,1023}},4,limit}}] = Errors, + [{{t,sum_1,2}, + {{bif,'+',{f,0},[{x,-1},{x,1}],{x,0}},4, + {uninitialized_reg,{x,-1}}}}, + {{t,sum_2,2}, + {{bif,'+',{f,0},[{x,0},{x,1023}],{x,0}},4, + {uninitialized_reg,{x,1023}}}}, + {{t,sum_3,2}, + {{bif,'+',{f,0},[{x,0},{x,1}],{x,-1}},4, + {invalid_store,{x,-1},number}}}, + {{t,sum_4,2}, + {{bif,'+',{f,0},[{x,0},{x,1}],{x,1023}},4,limit}}] = Errors, ok. yrange(Config) when is_list(Config) -> Errors = do_val(yrange, Config), - ?line - [{{t,sum_1,2}, - {{move,{x,1},{y,-1}},5, - {invalid_store,{y,-1},term}}}, - {{t,sum_2,2}, - {{bif,'+',{f,0},[{x,0},{y,1024}],{x,0}},7, - {uninitialized_reg,{y,1024}}}}, - {{t,sum_3,2}, - {{move,{x,1},{y,1024}},5,limit}}, - {{t,sum_4,2}, - {{move,{x,1},{y,-1}},5, - {invalid_store,{y,-1},term}}}] = Errors, + [{{t,sum_1,2}, + {{move,{x,1},{y,-1}},5, + {invalid_store,{y,-1},term}}}, + {{t,sum_2,2}, + {{bif,'+',{f,0},[{x,0},{y,1024}],{x,0}},7, + {uninitialized_reg,{y,1024}}}}, + {{t,sum_3,2}, + {{move,{x,1},{y,1024}},5,limit}}, + {{t,sum_4,2}, + {{move,{x,1},{y,-1}},5, + {invalid_store,{y,-1},term}}}] = Errors, ok. stack(Config) when is_list(Config) -> @@ -163,25 +160,23 @@ merge_undefined(Config) when is_list(Config) -> uninit(Config) when is_list(Config) -> Errors = do_val(uninit, Config), - ?line - [{{t,sum_1,2}, - {{move,{y,0},{x,0}},5,{uninitialized_reg,{y,0}}}}, - {{t,sum_2,2}, - {{call,1,{f,8}},5,{uninitialized_reg,{y,0}}}}, - {{t,sum_3,2}, - {{bif,'+',{f,0},[{x,0},{y,0}],{x,0}}, - 6, - {unassigned,{y,0}}}}] = Errors, + [{{t,sum_1,2}, + {{move,{y,0},{x,0}},5,{uninitialized_reg,{y,0}}}}, + {{t,sum_2,2}, + {{call,1,{f,8}},5,{uninitialized_reg,{y,0}}}}, + {{t,sum_3,2}, + {{bif,'+',{f,0},[{x,0},{y,0}],{x,0}}, + 6, + {unassigned,{y,0}}}}] = Errors, ok. unsafe_catch(Config) when is_list(Config) -> Errors = do_val(unsafe_catch, Config), - ?line - [{{t,small,2}, - {{bs_put_integer,{f,0},{integer,16},1, - {field_flags,[unsigned,big]},{y,0}}, - 20, - {unassigned,{y,0}}}}] = Errors, + [{{t,small,2}, + {{bs_put_integer,{f,0},{integer,16},1, + {field_flags,[unsigned,big]},{y,0}}, + 20, + {unassigned,{y,0}}}}] = Errors, ok. dead_code(Config) when is_list(Config) -> @@ -190,16 +185,14 @@ dead_code(Config) when is_list(Config) -> overwrite_catchtag(Config) when is_list(Config) -> Errors = do_val(overwrite_catchtag, Config), - ?line - [{{overwrite_catchtag,foo,1}, - {{move,{x,0},{y,0}},6,{catchtag,_}}}] = Errors, + [{{overwrite_catchtag,foo,1}, + {{move,{x,0},{y,0}},6,{catchtag,_}}}] = Errors, ok. overwrite_trytag(Config) when is_list(Config) -> Errors = do_val(overwrite_trytag, Config), - ?line - [{{overwrite_trytag,foo,1}, - {{kill,{y,2}},8,{trytag,_}}}] = Errors, + [{{overwrite_trytag,foo,1}, + {{kill,{y,2}},8,{trytag,_}}}] = Errors, ok. accessing_tags(Config) when is_list(Config) -> @@ -231,82 +224,77 @@ bad_catch_try(Config) when is_list(Config) -> cons_guard(Config) when is_list(Config) -> Errors = do_val(cons, Config), - ?line - [{{cons,foo,1}, - {{get_list,{x,0},{x,1},{x,2}}, - 5, - {bad_type,{needed,cons},{actual,term}}}}] = Errors, + [{{cons,foo,1}, + {{get_list,{x,0},{x,1},{x,2}}, + 5, + {bad_type,{needed,cons},{actual,term}}}}] = Errors, ok. freg_range(Config) when is_list(Config) -> Errors = do_val(freg_range, Config), - ?line - [{{t,sum_1,2}, - {{bif,fadd,{f,0},[{fr,-1},{fr,1}],{fr,0}}, - 5, - {bad_source,{fr,-1}}}}, - {{t,sum_2,2}, - {{bif,fadd,{f,0},[{fr,0},{fr,1024}],{fr,0}}, - 6, - {uninitialized_reg,{fr,1024}}}}, - {{t,sum_3,2}, - {{bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,-1}}, - 7, - {bad_target,{fr,-1}}}}, - {{t,sum_4,2}, - {{bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,1024}}, - 7, - limit}}] = Errors, + [{{t,sum_1,2}, + {{bif,fadd,{f,0},[{fr,-1},{fr,1}],{fr,0}}, + 5, + {bad_source,{fr,-1}}}}, + {{t,sum_2,2}, + {{bif,fadd,{f,0},[{fr,0},{fr,1024}],{fr,0}}, + 6, + {uninitialized_reg,{fr,1024}}}}, + {{t,sum_3,2}, + {{bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,-1}}, + 7, + {bad_target,{fr,-1}}}}, + {{t,sum_4,2}, + {{bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,1024}}, + 7, + limit}}] = Errors, ok. freg_uninit(Config) when is_list(Config) -> Errors = do_val(freg_uninit, Config), - ?line - [{{t,sum_1,2}, - {{bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,0}}, - 6, - {uninitialized_reg,{fr,1}}}}, - {{t,sum_2,2}, - {{bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,0}}, - 9, - {uninitialized_reg,{fr,0}}}}] = Errors, + [{{t,sum_1,2}, + {{bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,0}}, + 6, + {uninitialized_reg,{fr,1}}}}, + {{t,sum_2,2}, + {{bif,fadd,{f,0},[{fr,0},{fr,1}],{fr,0}}, + 9, + {uninitialized_reg,{fr,0}}}}] = Errors, ok. freg_state(Config) when is_list(Config) -> Errors = do_val(freg_state, Config), - ?line - [{{t,sum_1,2}, - {{bif,fmul,{f,0},[{fr,0},{fr,1}],{fr,0}}, - 6, - {bad_floating_point_state,undefined}}}, - {{t,sum_2,2}, - {{fmove,{fr,0},{x,0}}, - 8, - {bad_floating_point_state,cleared}}}, - {{t,sum_3,2}, - {{bif,'-',{f,0},[{x,1},{x,0}],{x,1}}, - 8, - {unsafe_instruction,{float_error_state,cleared}}}}, - {{t,sum_4,2}, - {{fcheckerror,{f,0}}, - 4, - {bad_floating_point_state,undefined}}}, - {{t,sum_5,2}, - {fclearerror,5,{bad_floating_point_state,cleared}}}] = Errors, + [{{t,sum_1,2}, + {{bif,fmul,{f,0},[{fr,0},{fr,1}],{fr,0}}, + 6, + {bad_floating_point_state,undefined}}}, + {{t,sum_2,2}, + {{fmove,{fr,0},{x,0}}, + 8, + {bad_floating_point_state,cleared}}}, + {{t,sum_3,2}, + {{bif,'-',{f,0},[{x,1},{x,0}],{x,1}}, + 8, + {unsafe_instruction,{float_error_state,cleared}}}}, + {{t,sum_4,2}, + {{fcheckerror,{f,0}}, + 4, + {bad_floating_point_state,undefined}}}, + {{t,sum_5,2}, + {fclearerror,5,{bad_floating_point_state,cleared}}}] = Errors, ok. bad_bin_match(Config) when is_list(Config) -> - [{{t,t,1},{return,5,{match_context,{x,0}}}}] = - do_val(bad_bin_match, Config), - ok. + [{{t,t,1},{return,5,{match_context,{x,0}}}}] = + do_val(bad_bin_match, Config), + ok. bad_dsetel(Config) when is_list(Config) -> Errors = do_val(bad_dsetel, Config), - ?line - [{{t,t,1}, - {{set_tuple_element,{x,1},{x,0},1}, - 17, - illegal_context_for_set_tuple_element}}] = Errors, + [{{t,t,1}, + {{set_tuple_element,{x,1},{x,0},1}, + 17, + illegal_context_for_set_tuple_element}}] = Errors, ok. state_after_fault_in_catch(Config) when is_list(Config) -> @@ -382,9 +370,9 @@ illegal_instruction(Config) when is_list(Config) -> %% (Thanks to Kiran Khaladkar.) %% failing_gc_guard_bif(Config) when is_list(Config) -> - ?line ok = process_request(lists:seq(1, 36)), - ?line error = process_request([]), - ?line error = process_request(not_a_list), + ok = process_request(lists:seq(1, 36)), + error = process_request([]), + error = process_request(not_a_list), ok. process_request(ConfId) -> @@ -421,7 +409,7 @@ map_field_lists(Config) -> %%%------------------------------------------------------------------------- do_val(Mod, Config) -> - Data = ?config(data_dir, Config), + Data = proplists:get_value(data_dir, Config), Base = atom_to_list(Mod), File = filename:join(Data, Base), case compile:file(File, [from_asm,no_postopt,return_errors]) of diff --git a/lib/compiler/test/bs_bincomp_SUITE.erl b/lib/compiler/test/bs_bincomp_SUITE.erl index d9865c3746..93bce5c1f6 100644 --- a/lib/compiler/test/bs_bincomp_SUITE.erl +++ b/lib/compiler/test/bs_bincomp_SUITE.erl @@ -55,110 +55,114 @@ end_per_group(_GroupName, Config) -> byte_aligned(Config) when is_list(Config) -> cs_init(), - ?line <<"abcdefg">> = cs(<< <<(X+32)>> || <<X>> <= <<"ABCDEFG">> >>), + <<"abcdefg">> = cs(<< <<(X+32)>> || <<X>> <= <<"ABCDEFG">> >>), <<1:32/little,2:32/little,3:32/little,4:32/little>> = cs(<< <<X:32/little>> || <<X:32>> <= <<1:32,2:32,3:32,4:32>> >>), - ?line cs(<<1:32/little,2:32/little,3:32/little,4:32/little>> = - << <<X:32/little>> || <<X:16>> <= <<1:16,2:16,3:16,4:16>> >>), + cs(<<1:32/little,2:32/little,3:32/little,4:32/little>> = + << <<X:32/little>> || <<X:16>> <= <<1:16,2:16,3:16,4:16>> >>), cs_end(). bit_aligned(Config) when is_list(Config) -> cs_init(), - ?line <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>> = + <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>> = cs(<< <<(X+32):7>> || <<X>> <= <<"ABCDEFG">> >>), - ?line <<"ABCDEFG">> = + <<"ABCDEFG">> = cs(<< <<(X-32)>> || <<X:7>> <= <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>> >>), - ?line <<1:31/little,2:31/little,3:31/little,4:31/little>> = + <<1:31/little,2:31/little,3:31/little,4:31/little>> = cs(<< <<X:31/little>> || <<X:31>> <= <<1:31,2:31,3:31,4:31>> >>), - ?line <<1:31/little,2:31/little,3:31/little,4:31/little>> = + <<1:31/little,2:31/little,3:31/little,4:31/little>> = cs(<< <<X:31/little>> || <<X:15>> <= <<1:15,2:15,3:15,4:15>> >>), cs_end(). extended_byte_aligned(Config) when is_list(Config) -> cs_init(), - ?line <<"abcdefg">> = cs(<< <<(X+32)>> || X <- "ABCDEFG" >>), - ?line "abcdefg" = [(X+32) || <<X>> <= <<"ABCDEFG">>], - ?line <<1:32/little,2:32/little,3:32/little,4:32/little>> = + <<"abcdefg">> = cs(<< <<(X+32)>> || X <- "ABCDEFG" >>), + "abcdefg" = [(X+32) || <<X>> <= <<"ABCDEFG">>], + <<1:32/little,2:32/little,3:32/little,4:32/little>> = cs(<< <<X:32/little>> || X <- [1,2,3,4] >>), - ?line [256,512,768,1024] = + [256,512,768,1024] = [X || <<X:16/little>> <= <<1:16,2:16,3:16,4:16>>], cs_end(). extended_bit_aligned(Config) when is_list(Config) -> cs_init(), - ?line <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>> = + <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>> = cs(<< <<(X+32):7>> || X <- "ABCDEFG" >>), - ?line "ABCDEFG" = [(X-32) || <<X:7>> <= <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>>], - ?line <<1:31/little,2:31/little,3:31/little,4:31/little>> = + "ABCDEFG" = [(X-32) || <<X:7>> <= <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>>], + <<1:31/little,2:31/little,3:31/little,4:31/little>> = cs(<< <<X:31/little>> || X <- [1,2,3,4] >>), - ?line [256,512,768,1024] = + [256,512,768,1024] = [X || <<X:15/little>> <= <<1:15,2:15,3:15,4:15>>], cs_end(). mixed(Config) when is_list(Config) -> cs_init(), - ?line <<2,3,3,4,4,5,5,6>> = + <<2,3,3,4,4,5,5,6>> = cs(<< <<(X+Y)>> || <<X>> <= <<1,2,3,4>>, <<Y>> <= <<1,2>> >>), - ?line <<2,3,3,4,4,5,5,6>> = + <<2,3,3,4,4,5,5,6>> = << <<(X+Y)>> || <<X>> <= <<1,2,3,4>>, Y <- [1,2] >>, - ?line <<2,3,3,4,4,5,5,6>> = + <<2,3,3,4,4,5,5,6>> = cs(<< <<(X+Y)>> || X <- [1,2,3,4], Y <- [1,2] >>), One = id([1,2,3,4]), Two = id([1,2]), - ?line <<2,3,3,4,4,5,5,6>> = + <<2,3,3,4,4,5,5,6>> = cs(<< <<(X+Y)>> || X <- One, Y <- Two >>), - ?line [2,3,3,4,4,5,5,6] = + [2,3,3,4,4,5,5,6] = [(X+Y) || <<X>> <= <<1,2,3,4>>, <<Y>> <= <<1,2>>], - ?line [2,3,3,4,4,5,5,6] = + [2,3,3,4,4,5,5,6] = [(X+Y) || <<X>> <= <<1,2,3,4>>, Y <- [1,2]], - ?line <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> = + <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> = cs(<< <<(X+Y):3>> || <<X:3>> <= <<1:3,2:3,3:3,4:3>>, <<Y:3>> <= <<1:3,2:3>> >>), - ?line <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> = + <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> = cs(<< <<(X+Y):3>> || <<X:3>> <= <<1:3,2:3,3:3,4:3>>, Y <- [1,2] >>), - ?line <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> = + <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> = cs(<< <<(X+Y):3>> || X <- [1,2,3,4], Y <- [1,2] >>), - ?line <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> = + <<2:3,3:3,3:3,4:3,4:3,5:3,5:3,6:3>> = cs_default(<< <<(X+Y):3>> || {X,Y} <- [{1,1},{1,2},{2,1},{2,2}, {3,1},{3,2},{4,1},{4,2}] >>), - ?line [2,3,3,4,4,5,5,6] = + [2,3,3,4,4,5,5,6] = [(X+Y) || <<X:3>> <= <<1:3,2:3,3:3,4:3>>, <<Y:3>> <= <<1:3,2:3>>], - ?line [2,3,3,4,4,5,5,6] = + [2,3,3,4,4,5,5,6] = [(X+Y) || <<X:3>> <= <<1:3,2:3,3:3,4:3>>, {_,Y} <- [{a,1},{b,2}]], cs_end(). filters(Config) when is_list(Config) -> cs_init(), - ?line <<"BDF">> = - cs_default(<< <<(X-32)>> || <<X:7>> <= <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>>, - X rem 2 == 0>>), - ?line <<"abc">> = cs_default(<< <<(X+32)>> || X <- "ABCDEFG", - is_less_than(X, $D)>>), - ?line <<"efg">> = cs_default(<< <<(X+32)>> || X <- "ABCDEFG", - not is_less_than(X, $E)>>), - ?line <<"b">> = cs_default(<< <<(X+32)>> || X <- "ABCDEFG", - is_less_than(X, $D), - X rem 2 == 0>>), - ?line <<"eg">> = cs_default(<< <<(X+32)>> || X <- "ABCDEFG", - not is_less_than(X, $E), - X rem 2 == 1>>), + <<"BDF">> = + cs_default(<< <<(X-32)>> || + <<X:7>> <= <<$a:7,$b:7,$c:7,$d:7,$e:7,$f:7,$g:7>>, + X rem 2 == 0>>), + <<"abc">> = cs_default(<< <<(X+32)>> || + X <- "ABCDEFG", + is_less_than(X, $D)>>), + <<"efg">> = cs_default(<< <<(X+32)>> || + X <- "ABCDEFG", + not is_less_than(X, $E)>>), + <<"b">> = cs_default(<< <<(X+32)>> || + X <- "ABCDEFG", + is_less_than(X, $D), + X rem 2 == 0>>), + <<"eg">> = cs_default(<< <<(X+32)>> || + X <- "ABCDEFG", + not is_less_than(X, $E), + X rem 2 == 1>>), %% Filtering by a non-matching pattern. - ?line <<"abd">> = cs_default(<< <<X:8>> || - <<0:1,X:7>> <= <<$a:8,$b:8,1:1,$c:7,$d:8, - 1:1,$e:7,0:4>> >>), + <<"abd">> = cs_default(<< <<X:8>> || + <<0:1,X:7>> <= <<$a:8,$b:8,1:1,$c:7,$d:8, + 1:1,$e:7,0:4>> >>), - ?line <<42,42>> = cs_default(<< <<42:8>> || - 42 <- [1,2,3,42,43,42] >>), + <<42,42>> = cs_default(<< <<42:8>> || 42 <- [1,2,3,42,43,42] >>), cs_end(). is_less_than(X, C) when X < C -> true; is_less_than(_, _) -> false. trim_coverage(Config) when is_list(Config) -> - ?line <<0,0,0,2,0,0,5,48,0,11,219,174,0,0,0,0>> = coverage_materialiv(a, b, {1328,777134}), - ?line <<67,40,0,0,66,152,0,0,69,66,64,0>> = coverage_trimmer([42,19,777]), - ?line <<0,0,2,43,0,0,3,9,0,0,0,3,64,8,0,0,0,0,0,0, + <<0,0,0,2,0,0,5,48,0,11,219,174,0,0,0,0>> = coverage_materialiv(a, b, {1328,777134}), + <<67,40,0,0,66,152,0,0,69,66,64,0>> = coverage_trimmer([42,19,777]), + <<0,0,2,43,0,0,3,9,0,0,0,3,64,8,0,0,0,0,0,0, 64,68,0,0,0,0,0,0,192,171,198,0,0,0,0,0>> = coverage_lightfv(555, 777, {3.0,40.0,-3555.0}), ok. @@ -186,109 +190,109 @@ coverage_trimmer(Params) -> coverage_summer(A, B, C, D) -> A+B+C+D. nomatch(Config) when is_list(Config) -> - ?line <<>> = << <<X:8>> || X = {_,_} = [_|_] <- [1,2,3] >>, + <<>> = << <<X:8>> || X = {_,_} = [_|_] <- [1,2,3] >>, ok. sizes(Config) when is_list(Config) -> - ?line cs_init(), + cs_init(), Fun0 = fun(List) -> cs(<< <<E:8>> || E <- List >>) end, - ?line <<>> = Fun0([]), - ?line <<1>> = Fun0([1]), - ?line <<1,2>> = Fun0([1,2]), - ?line <<1,2,3>> = Fun0([1,2,3]), + <<>> = Fun0([]), + <<1>> = Fun0([1]), + <<1,2>> = Fun0([1,2]), + <<1,2,3>> = Fun0([1,2,3]), Fun1 = fun(List) -> cs(<< <<E:16>> || E <- List >>) end, - ?line <<>> = Fun1([]), - ?line <<1:16>> = Fun1([1]), - ?line <<1:16,2:16>> = Fun1([1,2]), - ?line <<1:16,2:16,3:16>> = Fun1([1,2,3]), + <<>> = Fun1([]), + <<1:16>> = Fun1([1]), + <<1:16,2:16>> = Fun1([1,2]), + <<1:16,2:16,3:16>> = Fun1([1,2,3]), Fun2 = fun(List) -> cs(<< <<E:4>> || E <- List >>) end, - ?line <<>> = Fun2([]), - ?line <<1:4>> = Fun2([1]), - ?line <<1:4,13:4>> = Fun2([1,13]), - ?line <<1:4,13:4,7:4>> = Fun2([1,13,7]), - ?line <<0:1000/unit:8>> = Fun2(lists:duplicate(2000, 0)), + <<>> = Fun2([]), + <<1:4>> = Fun2([1]), + <<1:4,13:4>> = Fun2([1,13]), + <<1:4,13:4,7:4>> = Fun2([1,13,7]), + <<0:1000/unit:8>> = Fun2(lists:duplicate(2000, 0)), Fun3 = fun(List) -> cs(<< <<E:3>> || E <- List >>) end, - ?line <<>> = Fun3([]), - ?line <<40,177,29:5>> = Fun3([1,2,1,3,0,7,5]), - ?line <<0:512/unit:3>> = Fun3(lists:duplicate(512, 0)), + <<>> = Fun3([]), + <<40,177,29:5>> = Fun3([1,2,1,3,0,7,5]), + <<0:512/unit:3>> = Fun3(lists:duplicate(512, 0)), Fun4 = fun(List, Size) -> cs(<< <<E:Size>> || E <- List >>) end, - ?line <<>> = Fun4([], 8), - ?line <<42:6>> = Fun4([42], 6), - ?line <<42:16>> = Fun4([42], 16), + <<>> = Fun4([], 8), + <<42:6>> = Fun4([42], 6), + <<42:16>> = Fun4([42], 16), Fun5 = fun(List, Sz1, Sz2, Sz3) -> cs(<< <<E:Sz1,(E+1):Sz2/unit:8,(E+2):Sz3/unit:8>> || E <- List >>) end, - ?line <<>> = Fun5([], 1, 1, 1), - ?line <<7:3,8:40,9:56>> = Fun5([7], 3, 5, 7), + <<>> = Fun5([], 1, 1, 1), + <<7:3,8:40,9:56>> = Fun5([7], 3, 5, 7), Fun6 = fun(List, Size) -> cs(<< <<E:8,(E+1):Size>> || E <- List >>) end, - ?line <<>> = Fun6([], 42), - ?line <<42,43:20>> = Fun6([42], 20), + <<>> = Fun6([], 42), + <<42,43:20>> = Fun6([42], 20), %% Binary generators. Fun10 = fun(Bin) -> cs(<< <<E:16>> || <<E:8>> <= Bin >>) end, - ?line <<>> = Fun10(<<>>), - ?line <<1:16>> = Fun10(<<1>>), - ?line <<1:16,2:16>> = Fun10(<<1,2>>), + <<>> = Fun10(<<>>), + <<1:16>> = Fun10(<<1>>), + <<1:16,2:16>> = Fun10(<<1,2>>), Fun11 = fun(Bin) -> cs(<< <<E:8>> || <<E:16>> <= Bin >>) end, - ?line <<>> = Fun11(<<>>), - ?line <<1>> = Fun11(<<1:16>>), - ?line <<1,2>> = Fun11(<<1:16,2:16>>), - ?line <<1,2>> = Fun11(<<1:16,2:16,0:1>>), - ?line <<1,2>> = Fun11(<<1:16,2:16,0:7>>), - ?line <<1,2>> = Fun11(<<1:16,2:16,42:8>>), - ?line <<1,2>> = Fun11(<<1:16,2:16,42:9>>), - ?line <<1,2>> = Fun11(<<1:16,2:16,255:15>>), + <<>> = Fun11(<<>>), + <<1>> = Fun11(<<1:16>>), + <<1,2>> = Fun11(<<1:16,2:16>>), + <<1,2>> = Fun11(<<1:16,2:16,0:1>>), + <<1,2>> = Fun11(<<1:16,2:16,0:7>>), + <<1,2>> = Fun11(<<1:16,2:16,42:8>>), + <<1,2>> = Fun11(<<1:16,2:16,42:9>>), + <<1,2>> = Fun11(<<1:16,2:16,255:15>>), Fun12 = fun(Bin, Sz1, Sz2) -> cs(<< <<E:Sz1>> || <<E:Sz2>> <= Bin >>) end, - ?line <<>> = Fun12(<<>>, 1, 1), - ?line Binary = list_to_binary(lists:seq(0, 255)), - ?line Binary = Fun12(Binary, 1, 1), - ?line Binary = Fun12(Binary, 4, 4), - ?line Binary = Fun12(Binary, 8, 8), - ?line <<17:9,19:9>> = Fun12(<<17:6,19:6>>, 9, 6), + <<>> = Fun12(<<>>, 1, 1), + Binary = list_to_binary(lists:seq(0, 255)), + Binary = Fun12(Binary, 1, 1), + Binary = Fun12(Binary, 4, 4), + Binary = Fun12(Binary, 8, 8), + <<17:9,19:9>> = Fun12(<<17:6,19:6>>, 9, 6), Fun13 = fun(Sz) -> cs_default(<< <<C:8>> || <<C:4>> <= <<1:4,2:4,3:4,0:Sz>> >>) end, - ?line <<1,2,3>> = Fun13(0), - ?line <<1,2,3,0>> = Fun13(4), - ?line <<1,2,3,0>> = Fun13(5), - ?line <<1,2,3,0>> = Fun13(6), - ?line <<1,2,3,0>> = Fun13(7), - ?line <<1,2,3,0,0>> = Fun13(8), + <<1,2,3>> = Fun13(0), + <<1,2,3,0>> = Fun13(4), + <<1,2,3,0>> = Fun13(5), + <<1,2,3,0>> = Fun13(6), + <<1,2,3,0>> = Fun13(7), + <<1,2,3,0,0>> = Fun13(8), <<0:3>> = cs_default(<< <<0:S>> || S <- [0,1,2] >>), <<0:3>> = cs_default(<< <<0:S>> || <<S>> <= <<0,1,2>> >>), - ?line {'EXIT',_} = (catch << <<C:4>> || <<C:8>> <= {1,2,3} >>), + {'EXIT',_} = (catch << <<C:4>> || <<C:8>> <= {1,2,3} >>), - ?line cs_end(), + cs_end(), ok. cs_init() -> diff --git a/lib/compiler/test/bs_bit_binaries_SUITE.erl b/lib/compiler/test/bs_bit_binaries_SUITE.erl index 5bda20e6d6..c1f8f12bf1 100644 --- a/lib/compiler/test/bs_bit_binaries_SUITE.erl +++ b/lib/compiler/test/bs_bit_binaries_SUITE.erl @@ -59,9 +59,9 @@ end_per_group(_GroupName, Config) -> misc(Config) when is_list(Config) -> - ?line <<1:100>> = <<1:100>>, - ?line {ok,ok} = {match(7),match(9)}, - ?line {ok,ok} = {match1(15),match1(31)}, + <<1:100>> = <<1:100>>, + {ok,ok} = {match(7),match(9)}, + {ok,ok} = {match1(15),match1(31)}, ok. @@ -74,75 +74,75 @@ match1(N) -> ok. test_bit_size(Config) when is_list(Config) -> - ?line 101 = erlang:bit_size(<<1:101>>), - ?line 1001 = erlang:bit_size(<<1:1001>>), - ?line 1001 = erlang:bit_size(<<-10:1001>>), - ?line 80 = erlang:bit_size(<<1:80>>), - ?line 800 = erlang:bit_size(<<1:800>>), - ?line Bin = <<0:16#1000000>>, - ?line BigBin = list_to_bitstring([Bin||_ <- lists:seq(1,16#10)]++[<<1:1>>]), - ?line 16#10000001 = erlang:bit_size(BigBin), + 101 = erlang:bit_size(<<1:101>>), + 1001 = erlang:bit_size(<<1:1001>>), + 1001 = erlang:bit_size(<<-10:1001>>), + 80 = erlang:bit_size(<<1:80>>), + 800 = erlang:bit_size(<<1:800>>), + Bin = <<0:16#1000000>>, + BigBin = list_to_bitstring([Bin||_ <- lists:seq(1,16#10)]++[<<1:1>>]), + 16#10000001 = erlang:bit_size(BigBin), %% Only run these on computers with lots of memory %% HugeBin = list_to_bitstring([BigBin||_ <- lists:seq(1,16#10)]++[<<1:1>>]), %% 16#100000011 = erlang:bit_size(HugeBin), - ?line 0 = erlang:bit_size(<<>>), + 0 = erlang:bit_size(<<>>), ok. horrid_match(Config) when is_list(Config) -> - ?line <<1:4,B:24/bitstring>> = <<1:4,42:24/little>>, - ?line <<42:24/little>> = B, + <<1:4,B:24/bitstring>> = <<1:4,42:24/little>>, + <<42:24/little>> = B, ok. test_bitstr(Config) when is_list(Config) -> - ?line <<1:7,B/bitstring>> = <<1:7,<<1:1,6>>/bitstring>>, - ?line <<1:1,6>> = B, - ?line B = <<1:1,6>>, + <<1:7,B/bitstring>> = <<1:7,<<1:1,6>>/bitstring>>, + <<1:1,6>> = B, + B = <<1:1,6>>, ok. asymmetric_tests(Config) when is_list(Config) -> - ?line <<1:12>> = <<0,1:4>>, - ?line <<0,1:4>> = <<1:12>>, - ?line <<1:1,X/bitstring>> = <<128,255,0,0:2>>, - ?line <<1,254,0,0:1>> = X, - ?line X = <<1,254,0,0:1>>, - ?line <<1:1,X1:25/bitstring>> = <<128,255,0,0:2>>, - ?line <<1,254,0,0:1>> = X1, - ?line X1 = <<1,254,0,0:1>>, + <<1:12>> = <<0,1:4>>, + <<0,1:4>> = <<1:12>>, + <<1:1,X/bitstring>> = <<128,255,0,0:2>>, + <<1,254,0,0:1>> = X, + X = <<1,254,0,0:1>>, + <<1:1,X1:25/bitstring>> = <<128,255,0,0:2>>, + <<1,254,0,0:1>> = X1, + X1 = <<1,254,0,0:1>>, ok. big_asymmetric_tests(Config) when is_list(Config) -> - ?line <<1:875,1:12>> = <<1:875,0,1:4>>, - ?line <<1:875,0,1:4>> = <<1:875,1:12>>, - ?line <<1:1,X/bitstring>> = <<128,255,0,0:2,1:875>>, - ?line <<1,254,0,0:1,1:875>> = X, - ?line X = <<1,254,0,0:1,1:875>>, - ?line <<1:1,X1:900/bitstring>> = <<128,255,0,0:2,1:875>>, - ?line <<1,254,0,0:1,1:875>> = X1, - ?line X1 = <<1,254,0,0:1,1:875>>, + <<1:875,1:12>> = <<1:875,0,1:4>>, + <<1:875,0,1:4>> = <<1:875,1:12>>, + <<1:1,X/bitstring>> = <<128,255,0,0:2,1:875>>, + <<1,254,0,0:1,1:875>> = X, + X = <<1,254,0,0:1,1:875>>, + <<1:1,X1:900/bitstring>> = <<128,255,0,0:2,1:875>>, + <<1,254,0,0:1,1:875>> = X1, + X1 = <<1,254,0,0:1,1:875>>, ok. binary_to_and_from_list(Config) when is_list(Config) -> - ?line <<1,2,3,4,1:1>> = list_to_bitstring(bitstring_to_list(<<1,2,3,4,1:1>>)), - ?line [1,2,3,4,<<1:1>>] = bitstring_to_list(<<1,2,3,4,1:1>>), - ?line <<1:1,1,2,3,4>> = list_to_bitstring([<<1:1>>,1,2,3,4]), - ?line [128,129,1,130,<<0:1>>] = bitstring_to_list(<<1:1,1,2,3,4>>), + <<1,2,3,4,1:1>> = list_to_bitstring(bitstring_to_list(<<1,2,3,4,1:1>>)), + [1,2,3,4,<<1:1>>] = bitstring_to_list(<<1,2,3,4,1:1>>), + <<1:1,1,2,3,4>> = list_to_bitstring([<<1:1>>,1,2,3,4]), + [128,129,1,130,<<0:1>>] = bitstring_to_list(<<1:1,1,2,3,4>>), ok. big_binary_to_and_from_list(Config) when is_list(Config) -> - ?line <<1:800,2,3,4,1:1>> = + <<1:800,2,3,4,1:1>> = list_to_bitstring(bitstring_to_list(<<1:800,2,3,4,1:1>>)), - ?line [1,2,3,4|_Rest1] = bitstring_to_list(<<1,2,3,4,1:800,1:1>>), - ?line <<1:801,1,2,3,4>> = list_to_bitstring([<<1:801>>,1,2,3,4]), + [1,2,3,4|_Rest1] = bitstring_to_list(<<1,2,3,4,1:800,1:1>>), + <<1:801,1,2,3,4>> = list_to_bitstring([<<1:801>>,1,2,3,4]), ok. send_and_receive(Config) when is_list(Config) -> - ?line Bin = <<1,2:7>>, + Bin = <<1,2:7>>, Pid = spawn_link(fun() -> receiver(Bin) end), - ?line Pid ! {self(),<<1:7,8:5,Bin/bitstring>>}, - ?line receive - ok -> - ok - end. + Pid ! {self(),<<1:7,8:5,Bin/bitstring>>}, + receive + ok -> + ok + end. receiver(Bin) -> receive diff --git a/lib/compiler/test/bs_construct_SUITE.erl b/lib/compiler/test/bs_construct_SUITE.erl index caf204032c..d94e870e21 100644 --- a/lib/compiler/test/bs_construct_SUITE.erl +++ b/lib/compiler/test/bs_construct_SUITE.erl @@ -33,7 +33,9 @@ -include_lib("common_test/include/ct.hrl"). -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,1}}]. all() -> test_lib:recompile(?MODULE), @@ -60,12 +62,9 @@ end_per_group(_GroupName, Config) -> init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) -> - Dog = test_server:timetrap(?t:minutes(1)), - [{watchdog,Dog}|Config]. + Config. end_per_testcase(Case, Config) when is_atom(Case), is_list(Config) -> - Dog = ?config(watchdog, Config), - ?t:timetrap_cancel(Dog), ok. two(Config) when is_list(Config) -> @@ -86,7 +85,7 @@ id(I) -> I. -define(T(B, L), {B, ??B, L}). -define(N(B), {B, ??B, unknown}). --define(FAIL(Expr), ?line {'EXIT',{badarg,_}} = (catch Expr)). +-define(FAIL(Expr), {'EXIT',{badarg,_}} = (catch Expr)). l(I_13, I_big1, I_16, Bin) -> [ @@ -200,7 +199,7 @@ one_test({C_bin, E_bin, Str, Bytes}) when is_list(Bytes) -> true -> io:format("ERROR: Compiled: ~p. Expected ~p. Got ~p.~n", [Str, Bytes, bitstring_to_list(C_bin)]), - test_server:fail(comp) + ct:fail(comp) end, if E_bin == Bin -> @@ -208,7 +207,7 @@ one_test({C_bin, E_bin, Str, Bytes}) when is_list(Bytes) -> true -> io:format("ERROR: Interpreted: ~p. Expected ~p. Got ~p.~n", [Str, Bytes, bitstring_to_list(E_bin)]), - test_server:fail(comp) + ct:fail(comp) end; one_test({C_bin, E_bin, Str, Result}) -> io:format(" ~s ~p~n", [Str, C_bin]), @@ -229,7 +228,7 @@ one_test({C_bin, E_bin, Str, Result}) -> io:format("ERROR: Compiled not equal to interpreted:" "~n ~p, ~p.~n", [bitstring_to_list(C_bin), bitstring_to_list(E_bin)]), - test_server:fail(comp); + ct:fail(comp); 0 -> ok; %% For situations where the final bits may not matter, like @@ -261,15 +260,15 @@ equal_lists(A, B, R) -> end. test1(Config) when is_list(Config) -> - ?line I_13 = i(13), - ?line I_big1 = big(1), - ?line I_16 = i(16), - ?line Bin = i(<<16#A5,16#5A,16#C3>>), - ?line Vars = lists:sort([{'I_13',I_13}, - {'I_big1',I_big1}, - {'I_16',I_16}, - {'Bin',Bin}]), - ?line lists:foreach(fun one_test/1, eval_list(l(I_13, I_big1, I_16, Bin), Vars)). + I_13 = i(13), + I_big1 = big(1), + I_16 = i(16), + Bin = i(<<16#A5,16#5A,16#C3>>), + Vars = lists:sort([{'I_13',I_13}, + {'I_big1',I_big1}, + {'I_16',I_16}, + {'Bin',Bin}]), + lists:foreach(fun one_test/1, eval_list(l(I_13, I_big1, I_16, Bin), Vars)). fail(Config) when is_list(Config) -> I_minus_777 = i(-777), @@ -278,68 +277,68 @@ fail(Config) when is_list(Config) -> %% One negative field size, but the sum of field sizes will be 1 byte. %% Make sure that we reject that properly. - ?line {'EXIT',{badarg,_}} = (catch <<I_minus_777:2048/unit:8, - 57:I_minus_2047/unit:8>>), + {'EXIT',{badarg,_}} = (catch <<I_minus_777:2048/unit:8, + 57:I_minus_2047/unit:8>>), %% Same thing, but use literals. - ?line {'EXIT',{badarg,_}} = (catch <<I_minus_777:2048/unit:8, - 57:(-2047)/unit:8>>), + {'EXIT',{badarg,_}} = (catch <<I_minus_777:2048/unit:8, + 57:(-2047)/unit:8>>), %% Not numbers. - ?line {'EXIT',{badarg,_}} = (catch <<45:(i(not_a_number))>>), - ?line {'EXIT',{badarg,_}} = (catch <<13:8,45:(i(not_a_number))>>), + {'EXIT',{badarg,_}} = (catch <<45:(i(not_a_number))>>), + {'EXIT',{badarg,_}} = (catch <<13:8,45:(i(not_a_number))>>), %% Unaligned sizes. BadSz = i(7), Bitstr = i(<<42:17>>), - ?line {'EXIT',{badarg,_}} = (catch <<Bitstr:4/binary>>), - ?line {'EXIT',{badarg,_}} = (catch <<Bitstr:BadSz/binary>>), + {'EXIT',{badarg,_}} = (catch <<Bitstr:4/binary>>), + {'EXIT',{badarg,_}} = (catch <<Bitstr:BadSz/binary>>), - ?line [] = [X || {X} <- [], X == <<Bitstr:BadSz/binary>>], - ?line [] = [X || {X} <- [], X == <<Bitstr:4/binary>>], + [] = [X || {X} <- [], X == <<Bitstr:BadSz/binary>>], + [] = [X || {X} <- [], X == <<Bitstr:4/binary>>], %% Literals with incorrect type. - ?line {'EXIT',{badarg,_}} = (catch <<42.0/integer>>), - ?line {'EXIT',{badarg,_}} = (catch <<42/binary>>), - ?line {'EXIT',{badarg,_}} = (catch <<an_atom/integer>>), + {'EXIT',{badarg,_}} = (catch <<42.0/integer>>), + {'EXIT',{badarg,_}} = (catch <<42/binary>>), + {'EXIT',{badarg,_}} = (catch <<an_atom/integer>>), ok. float_bin(Config) when is_list(Config) -> %% Some more coverage. - ?line {<<1,2,3>>,7.0} = float_bin_1(4), + {<<1,2,3>>,7.0} = float_bin_1(4), F = 42.0, - ?line <<42,0,0,0,0,0,0,69,64>> = <<(id(42)),F/little-float>>, + <<42,0,0,0,0,0,0,69,64>> = <<(id(42)),F/little-float>>, ok. float_bin_1(F) -> {<<1,2,3>>,F+3.0}. in_guard(Config) when is_list(Config) -> - ?line 1 = in_guard_1(<<16#74ad:16>>, 16#e95, 5), - ?line 2 = in_guard_1(<<16#3A,16#F7,"hello">>, 16#3AF7, <<"hello">>), - ?line 3 = in_guard_1(<<16#FBCD:14,3.1415/float,3:2>>, 16#FBCD, 3.1415), - ?line 3 = in_guard_1(<<16#FBCD:14,3/float,3:2>>, 16#FBCD, 3), - ?line 3 = in_guard_1(<<16#FBCD:14,(2 bsl 226)/float,3:2>>, 16#FBCD, 2 bsl 226), - ?line nope = in_guard_1(<<1>>, 42, b), - ?line nope = in_guard_1(<<1>>, a, b), - ?line nope = in_guard_1(<<1,2>>, 1, 1), - ?line nope = in_guard_1(<<4,5>>, 1, 2.71), - ?line nope = in_guard_1(<<4,5>>, 1, <<12,13>>), - - ?line 1 = in_guard_2(<<0,56>>, 7, blurf), - ?line 2 = in_guard_2(<<1,255>>, 511, blurf), - ?line 3 = in_guard_2(<<0,3>>, 0, blurf), - ?line 4 = in_guard_2(<<>>, 1, {<<7:16>>}), - ?line nope = in_guard_2(<<4,5>>, 1, blurf), - - ?line 42 = in_guard_3(<<1,2,3,42>>, <<1,2,3>>), - ?line 42 = in_guard_3(<<1,2,3,42>>, <<1,2,3>>), - ?line nope = in_guard_3(<<>>, <<>>), - - ?line ok = in_guard_4(<<15:4>>, 255), - ?line nope = in_guard_4(<<15:8>>, 255), + 1 = in_guard_1(<<16#74ad:16>>, 16#e95, 5), + 2 = in_guard_1(<<16#3A,16#F7,"hello">>, 16#3AF7, <<"hello">>), + 3 = in_guard_1(<<16#FBCD:14,3.1415/float,3:2>>, 16#FBCD, 3.1415), + 3 = in_guard_1(<<16#FBCD:14,3/float,3:2>>, 16#FBCD, 3), + 3 = in_guard_1(<<16#FBCD:14,(2 bsl 226)/float,3:2>>, 16#FBCD, 2 bsl 226), + nope = in_guard_1(<<1>>, 42, b), + nope = in_guard_1(<<1>>, a, b), + nope = in_guard_1(<<1,2>>, 1, 1), + nope = in_guard_1(<<4,5>>, 1, 2.71), + nope = in_guard_1(<<4,5>>, 1, <<12,13>>), + + 1 = in_guard_2(<<0,56>>, 7, blurf), + 2 = in_guard_2(<<1,255>>, 511, blurf), + 3 = in_guard_2(<<0,3>>, 0, blurf), + 4 = in_guard_2(<<>>, 1, {<<7:16>>}), + nope = in_guard_2(<<4,5>>, 1, blurf), + + 42 = in_guard_3(<<1,2,3,42>>, <<1,2,3>>), + 42 = in_guard_3(<<1,2,3,42>>, <<1,2,3>>), + nope = in_guard_3(<<>>, <<>>), + + ok = in_guard_4(<<15:4>>, 255), + nope = in_guard_4(<<15:8>>, 255), ok. in_guard_1(Bin, A, B) when <<A:13,B:3>> == Bin -> 1; @@ -361,10 +360,10 @@ in_guard_4(Bin, A) when <<A:4>> =:= Bin -> ok; in_guard_4(_, _) -> nope. in_catch(Config) when is_list(Config) -> - ?line <<42,0,5>> = small(42, 5), - ?line <<255>> = small(255, <<1,2,3,4,5,6,7,8,9>>), - ?line <<1,2>> = small(<<7,8,9,10>>, 258), - ?line <<>> = small(<<1,2,3,4,5>>, <<7,8,9,10>>), + <<42,0,5>> = small(42, 5), + <<255>> = small(255, <<1,2,3,4,5,6,7,8,9>>), + <<1,2>> = small(<<7,8,9,10>>, 258), + <<>> = small(<<1,2,3,4,5>>, <<7,8,9,10>>), <<15,240,0,42>> = small2(255, 42), <<7:20>> = small2(<<1,2,3>>, 7), @@ -413,20 +412,20 @@ small2(A, B) -> nasty_literals(Config) when is_list(Config) -> case erlang:system_info(endian) of big -> - ?line [0,42] = binary_to_list(id(<<42:16/native>>)); + [0,42] = binary_to_list(id(<<42:16/native>>)); little -> - ?line [42,0] = binary_to_list(id(<<42:16/native>>)) + [42,0] = binary_to_list(id(<<42:16/native>>)) end, - ?line Bin0 = id(<<1,2,3,0:10000000,4,5,6>>), - ?line 1250006 = size(Bin0), - ?line <<1,2,3,0:10000000,4,5,6>> = Bin0, + Bin0 = id(<<1,2,3,0:10000000,4,5,6>>), + 1250006 = size(Bin0), + <<1,2,3,0:10000000,4,5,6>> = Bin0, - ?line Bin1 = id(<<0:10000000,7,8,-1:10000000,9,10,0:10000000>>), - ?line 3750004 = size(Bin1), - ?line <<0:10000000,7,8,-1:10000000/signed,9,10,0:10000000>> = Bin1, + Bin1 = id(<<0:10000000,7,8,-1:10000000,9,10,0:10000000>>), + 3750004 = size(Bin1), + <<0:10000000,7,8,-1:10000000/signed,9,10,0:10000000>> = Bin1, - ?line <<255,255,0,0,0>> = id(<<255,255,0,0,0>>), + <<255,255,0,0,0>> = id(<<255,255,0,0,0>>), %% Coverage. I = 16#7777FFFF7777FFFF7777FFFF7777FFFF7777FFFF7777FFFF, @@ -435,18 +434,18 @@ nasty_literals(Config) when is_list(Config) -> ok. -define(COF(Int0), - ?line (fun(Int) -> - true = <<Int:32/float>> =:= <<(float(Int)):32/float>>, - true = <<Int:64/float>> =:= <<(float(Int)):64/float>> - end)(nonliteral(Int0)), - ?line true = <<Int0:32/float>> =:= <<(float(Int0)):32/float>>, - ?line true = <<Int0:64/float>> =:= <<(float(Int0)):64/float>>). + (fun(Int) -> + true = <<Int:32/float>> =:= <<(float(Int)):32/float>>, + true = <<Int:64/float>> =:= <<(float(Int)):64/float>> + end)(nonliteral(Int0)), + true = <<Int0:32/float>> =:= <<(float(Int0)):32/float>>, + true = <<Int0:64/float>> =:= <<(float(Int0)):64/float>>). -define(COF64(Int0), - ?line (fun(Int) -> - true = <<Int:64/float>> =:= <<(float(Int)):64/float>> - end)(nonliteral(Int0)), - ?line true = <<Int0:64/float>> =:= <<(float(Int0)):64/float>>). + (fun(Int) -> + true = <<Int:64/float>> =:= <<(float(Int)):64/float>> + end)(nonliteral(Int0)), + true = <<Int0:64/float>> =:= <<(float(Int0)):64/float>>). nonliteral(X) -> X. @@ -467,7 +466,7 @@ coerce_to_float(Config) when is_list(Config) -> side_effect(Config) when is_list(Config) -> {'EXIT',{badarg,_}} = (catch side_effect_1(a)), {'EXIT',{badarg,_}} = (catch side_effect_1(<<>>)), - ?line ok = side_effect_1(42), + ok = side_effect_1(42), ok. side_effect_1(A) -> @@ -477,32 +476,32 @@ side_effect_1(A) -> -record(otp_7029, {a,b}). opt(Config) when is_list(Config) -> - ?line 42 = otp_7029(#otp_7029{a = <<>>,b = 42}), + 42 = otp_7029(#otp_7029{a = <<>>,b = 42}), N = 16, - ?line <<1,3,65>> = id(<<1,833:N>>), - ?line <<1,66,3>> = id(<<1,834:N/little>>), - ?line <<1,65,136,0,0>> = id(<<1,17.0:32/float>>), - ?line <<1,64,8,0,0,0,0,0,0>> = id(<<1,3.0:N/float-unit:4>>), - ?line <<1,0,0,0,0,0,0,8,64>> = id(<<1,3.0:N/little-float-unit:4>>), - ?line {'EXIT',{badarg,_}} = (catch id(<<3.1416:N/float>>)), + <<1,3,65>> = id(<<1,833:N>>), + <<1,66,3>> = id(<<1,834:N/little>>), + <<1,65,136,0,0>> = id(<<1,17.0:32/float>>), + <<1,64,8,0,0,0,0,0,0>> = id(<<1,3.0:N/float-unit:4>>), + <<1,0,0,0,0,0,0,8,64>> = id(<<1,3.0:N/little-float-unit:4>>), + {'EXIT',{badarg,_}} = (catch id(<<3.1416:N/float>>)), B = <<1,2,3,4,5>>, - ?line <<0,1,2,3,4,5>> = id(<<0,B/binary>>), - ?line <<1,2,3,4,5,19>> = id(<<B:5/binary,19>>), - ?line <<1,2,3,42>> = id(<<B:3/binary,42>>), + <<0,1,2,3,4,5>> = id(<<0,B/binary>>), + <<1,2,3,4,5,19>> = id(<<B:5/binary,19>>), + <<1,2,3,42>> = id(<<B:3/binary,42>>), - ?line {'EXIT',_} = (catch <<<<23,56,0,2>>:(2.5)/binary>>), - ?line {'EXIT',_} = (catch <<<<23,56,0,2>>:(-16)/binary>>), - ?line {'EXIT',_} = (catch <<<<23,56,0,2>>:(anka)>>), - ?line {'EXIT',_} = (catch <<<<23,56,0,2>>:64/float>>), - ?line {'EXIT',_} = (catch <<<<23,56,0,2:7>>/binary>>), + {'EXIT',_} = (catch <<<<23,56,0,2>>:(2.5)/binary>>), + {'EXIT',_} = (catch <<<<23,56,0,2>>:(-16)/binary>>), + {'EXIT',_} = (catch <<<<23,56,0,2>>:(anka)>>), + {'EXIT',_} = (catch <<<<23,56,0,2>>:64/float>>), + {'EXIT',_} = (catch <<<<23,56,0,2:7>>/binary>>), %% Test constant propagation - there should be a warning. BadSz = 2.5, {'EXIT',_} = (catch <<<<N,56,0,2>>:BadSz/binary>>), case id(false) of - true -> ?line opt_dont_call_me(); + true -> opt_dont_call_me(); false -> ok end, @@ -530,7 +529,7 @@ otp_7556(Bin, A, B, C) -> %% for a binary construction with a later allocation). float_arith(Config) when is_list(Config) -> - ?line {<<1,2,3,64,69,0,0,0,0,0,0>>,21.0} = do_float_arith(<<1,2,3>>, 42, 2), + {<<1,2,3,64,69,0,0,0,0,0,0>>,21.0} = do_float_arith(<<1,2,3>>, 42, 2), ok. do_float_arith(Bin0, X, Y) -> @@ -538,7 +537,7 @@ do_float_arith(Bin0, X, Y) -> {Bin,X / Y}. otp_8054(Config) when is_list(Config) -> - ?line <<"abc">> = otp_8054_1([null,1,2,3], <<"abc">>), + <<"abc">> = otp_8054_1([null,1,2,3], <<"abc">>), ok. otp_8054_1([H|T], Bin) -> diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl index 99539f3779..7fa26b6c26 100644 --- a/lib/compiler/test/bs_match_SUITE.erl +++ b/lib/compiler/test/bs_match_SUITE.erl @@ -37,14 +37,18 @@ cover_beam_bool/1,matched_out_size/1,follow_fail_branch/1, no_partition/1,calling_a_binary/1,binary_in_map/1, match_string_opt/1,select_on_integer/1, - map_and_binary/1,unsafe_branch_caching/1]). + map_and_binary/1,unsafe_branch_caching/1, + bad_literals/1,good_literals/1]). -export([coverage_id/1,coverage_external_ignore/2]). -include_lib("common_test/include/ct.hrl"). +-include_lib("syntax_tools/include/merl.hrl"). -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,1}}]. all() -> test_lib:recompile(?MODULE), @@ -64,7 +68,8 @@ groups() -> cover_beam_bool,matched_out_size,follow_fail_branch, no_partition,calling_a_binary,binary_in_map, match_string_opt,select_on_integer, - map_and_binary,unsafe_branch_caching]}]. + map_and_binary,unsafe_branch_caching, + bad_literals,good_literals]}]. init_per_suite(Config) -> @@ -81,20 +86,17 @@ end_per_group(_GroupName, Config) -> init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) -> - Dog = test_server:timetrap(?t:minutes(1)), - [{watchdog,Dog}|Config]. + Config. end_per_testcase(Case, Config) when is_atom(Case), is_list(Config) -> - Dog = ?config(watchdog, Config), - ?t:timetrap_cancel(Dog), ok. fun_shadow(Config) when is_list(Config) -> %% OTP-5270 - ?line 7 = fun_shadow_1(), - ?line 7 = fun_shadow_2(8), - ?line 7 = fun_shadow_3(), - ?line no = fun_shadow_4(8), + 7 = fun_shadow_1(), + 7 = fun_shadow_2(8), + 7 = fun_shadow_3(), + no = fun_shadow_4(8), ok. fun_shadow_1() -> @@ -124,7 +126,7 @@ int_float(Config) when is_list(Config) -> %% Coverage of error cases in sys_pre_expand:coerce_to_float/2. case id(default) of <<(1 bsl 1024):64/float>> -> - ?t:fail(); + ct:fail(should_not_match); default -> ok end. @@ -132,64 +134,64 @@ int_float(Config) when is_list(Config) -> %% Stolen from erl_eval_SUITE and modified. %% OTP-5269. Bugs in the bit syntax. otp_5269(Config) when is_list(Config) -> - ?line check(fun() -> L = 8, - F = fun(<<A:L,B:A>>) -> B end, - F(<<16:8, 7:16>>) + check(fun() -> L = 8, + F = fun(<<A:L,B:A>>) -> B end, + F(<<16:8, 7:16>>) end, 7), - ?line check(fun() -> L = 8, <<A:L,B:A>> = <<16:8, 7:16>>, B end, - 7), - ?line check(fun() -> U = 8, (fun(<<U:U>>) -> U end)(<<32:8>>) end, - 32), - ?line check(fun() -> U = 8, [U || <<U:U>> <- [<<32:8>>]] end, - [32]), - ?line check(fun() -> [X || <<A:8, - B:A>> <- [<<16:8,19:16>>], - <<X:8>> <- [<<B:8>>]] end, - [19]), - ?line check(fun() -> A = 4, B = 28, bit_size(<<13:(A+(X=B))>>), X end, - 28), - ?line check(fun() -> - <<Size,B:Size/binary,Rest/binary>> = <<2,"AB","CD">>, - {Size,B,Rest} - end, - {2,<<"AB">>,<<"CD">>}), - ?line check(fun() -> X = 32, - [X || <<X:X>> <- [<<1:32>>,<<2:32>>,<<3:8>>]] end, - %% "binsize variable" ^ - [1,2]), - ?line check(fun() -> - (fun (<<A:1/binary, B:8/integer, _C:B/binary>>) -> - case A of - B -> wrong; - _ -> ok - end - end)(<<1,2,3,4>>) end, - ok), + check(fun() -> L = 8, <<A:L,B:A>> = <<16:8, 7:16>>, B end, + 7), + check(fun() -> U = 8, (fun(<<U:U>>) -> U end)(<<32:8>>) end, + 32), + check(fun() -> U = 8, [U || <<U:U>> <- [<<32:8>>]] end, + [32]), + check(fun() -> [X || <<A:8, + B:A>> <- [<<16:8,19:16>>], + <<X:8>> <- [<<B:8>>]] end, + [19]), + check(fun() -> A = 4, B = 28, bit_size(<<13:(A+(X=B))>>), X end, + 28), + check(fun() -> + <<Size,B:Size/binary,Rest/binary>> = <<2,"AB","CD">>, + {Size,B,Rest} + end, + {2,<<"AB">>,<<"CD">>}), + check(fun() -> X = 32, + [X || <<X:X>> <- [<<1:32>>,<<2:32>>,<<3:8>>]] end, + %% "binsize variable" ^ + [1,2]), + check(fun() -> + (fun (<<A:1/binary, B:8/integer, _C:B/binary>>) -> + case A of + B -> wrong; + _ -> ok + end + end)(<<1,2,3,4>>) end, + ok), ok. null_fields(Config) when is_list(Config) -> - ?line check(fun() -> - W = id(0), - F = fun(<<_:W>>) -> tail; - (<<>>) -> empty - end, - F(<<>>) - end, tail), - ?line check(fun() -> - F = fun(<<_/binary>>) -> tail; - (<<>>) -> empty - end, - F(<<>>) - end, tail), + check(fun() -> + W = id(0), + F = fun(<<_:W>>) -> tail; + (<<>>) -> empty + end, + F(<<>>) + end, tail), + check(fun() -> + F = fun(<<_/binary>>) -> tail; + (<<>>) -> empty + end, + F(<<>>) + end, tail), ok. wiger(Config) when is_list(Config) -> - ?line ok1 = wcheck(<<3>>), - ?line ok2 = wcheck(<<1,2,3>>), - ?line ok3 = wcheck(<<4>>), - ?line {error,<<1,2,3,4>>} = wcheck(<<1,2,3,4>>), - ?line {error,<<>>} = wcheck(<<>>), + ok1 = wcheck(<<3>>), + ok2 = wcheck(<<1,2,3>>), + ok3 = wcheck(<<4>>), + {error,<<1,2,3,4>>} = wcheck(<<1,2,3,4>>), + {error,<<>>} = wcheck(<<>>), ok. wcheck(<<A>>) when A==3-> @@ -203,24 +205,24 @@ wcheck(Other) -> bin_tail(Config) when is_list(Config) -> S = <<"abcde">>, - ?line $a = bin_tail_c(S, 0), - ?line $c = bin_tail_c(S, 2), - ?line $e = bin_tail_c(S, 4), - ?line {'EXIT',_} = (catch bin_tail_c(S, 5)), - ?line {'EXIT',_} = (catch bin_tail_c_var(S, 5)), - - ?line $a = bin_tail_d(S, 0), - ?line $b = bin_tail_d(S, 8), - ?line $d = bin_tail_d(S, 3*8), - ?line {'EXIT',_} = (catch bin_tail_d_dead(S, 1)), - ?line {'EXIT',_} = (catch bin_tail_d_dead(S, 9)), - ?line {'EXIT',_} = (catch bin_tail_d_dead(S, 5*8)), - ?line {'EXIT',_} = (catch bin_tail_d_var(S, 1)), - - ?line ok = bin_tail_e(<<2:2,0:1,1:5>>), - ?line ok = bin_tail_e(<<2:2,1:1,1:5,42:64>>), - ?line error = bin_tail_e(<<3:2,1:1,1:5,42:64>>), - ?line error = bin_tail_e(<<>>), + $a = bin_tail_c(S, 0), + $c = bin_tail_c(S, 2), + $e = bin_tail_c(S, 4), + {'EXIT',_} = (catch bin_tail_c(S, 5)), + {'EXIT',_} = (catch bin_tail_c_var(S, 5)), + + $a = bin_tail_d(S, 0), + $b = bin_tail_d(S, 8), + $d = bin_tail_d(S, 3*8), + {'EXIT',_} = (catch bin_tail_d_dead(S, 1)), + {'EXIT',_} = (catch bin_tail_d_dead(S, 9)), + {'EXIT',_} = (catch bin_tail_d_dead(S, 5*8)), + {'EXIT',_} = (catch bin_tail_d_var(S, 1)), + + ok = bin_tail_e(<<2:2,0:1,1:5>>), + ok = bin_tail_e(<<2:2,1:1,1:5,42:64>>), + error = bin_tail_e(<<3:2,1:1,1:5,42:64>>), + error = bin_tail_e(<<>>), ok. bin_tail_c(Bin, Offset) -> @@ -279,34 +281,34 @@ bin_tail_e_var(Bin) -> end. save_restore(Config) when is_list(Config) -> - ?line 0 = save_restore_1(<<0:2,42:6>>), - ?line {1,3456} = save_restore_1(<<1:2,3456:14>>), - ?line {2,7981234} = save_restore_1(<<2:2,7981234:30>>), - ?line {3,763967493838} = save_restore_1(<<0:2,763967493838:62>>), + 0 = save_restore_1(<<0:2,42:6>>), + {1,3456} = save_restore_1(<<1:2,3456:14>>), + {2,7981234} = save_restore_1(<<2:2,7981234:30>>), + {3,763967493838} = save_restore_1(<<0:2,763967493838:62>>), A = <<" x">>, B = <<".x">>, C = <<"-x">>, - ?line {" ",<<"x">>} = lll(A), - ?line {" ",<<"x">>} = mmm(A), - ?line {" ",<<"x">>} = nnn(A), - ?line {" ",<<"x">>} = ooo(A), + {" ",<<"x">>} = lll(A), + {" ",<<"x">>} = mmm(A), + {" ",<<"x">>} = nnn(A), + {" ",<<"x">>} = ooo(A), - ?line {".",<<"x">>} = lll(B), - ?line {".",<<"x">>} = mmm(B), - ?line {".",<<"x">>} = nnn(B), - ?line {".",<<"x">>} = ooo(B), + {".",<<"x">>} = lll(B), + {".",<<"x">>} = mmm(B), + {".",<<"x">>} = nnn(B), + {".",<<"x">>} = ooo(B), - ?line {"-",<<"x">>} = lll(C), - ?line {"-",<<"x">>} = mmm(C), - ?line {"-",<<"x">>} = nnn(C), - ?line {"-",<<"x">>} = ooo(C), + {"-",<<"x">>} = lll(C), + {"-",<<"x">>} = mmm(C), + {"-",<<"x">>} = nnn(C), + {"-",<<"x">>} = ooo(C), Bin = <<-1:64>>, case bad_float_unpack_match(Bin) of -1 -> ok; - _Other -> ?line ?t:fail(bad_return_value_probably_NaN) + _Other -> ct:fail(bad_return_value_probably_NaN) end. save_restore_1(Bin) -> @@ -335,18 +337,18 @@ bad_float_unpack_match(<<I:64/integer-signed>>) -> I. partitioned_bs_match(Config) when is_list(Config) -> - ?line <<1,2,3>> = partitioned_bs_match(blurf, <<42,1,2,3>>), - ?line error = partitioned_bs_match(10, <<7,8,15,13>>), - ?line error = partitioned_bs_match(100, {a,tuple,is,'not',a,binary}), - ?line ok = partitioned_bs_match(0, <<>>), - ?line fc(partitioned_bs_match, [-1,blurf], + <<1,2,3>> = partitioned_bs_match(blurf, <<42,1,2,3>>), + error = partitioned_bs_match(10, <<7,8,15,13>>), + error = partitioned_bs_match(100, {a,tuple,is,'not',a,binary}), + ok = partitioned_bs_match(0, <<>>), + fc(partitioned_bs_match, [-1,blurf], catch partitioned_bs_match(-1, blurf)), - ?line fc(partitioned_bs_match, [-1,<<1,2,3>>], + fc(partitioned_bs_match, [-1,<<1,2,3>>], catch partitioned_bs_match(-1, <<1,2,3>>)), - ?line {17,<<1,2,3>>} = partitioned_bs_match_2(1, <<17,1,2,3>>), - ?line {7,<<1,2,3>>} = partitioned_bs_match_2(7, <<17,1,2,3>>), + {17,<<1,2,3>>} = partitioned_bs_match_2(1, <<17,1,2,3>>), + {7,<<1,2,3>>} = partitioned_bs_match_2(7, <<17,1,2,3>>), - ?line fc(partitioned_bs_match_2, [4,<<0:17>>], + fc(partitioned_bs_match_2, [4,<<0:17>>], catch partitioned_bs_match_2(4, <<0:17>>)), anything = partitioned_bs_match_3(anything, <<42>>), @@ -399,25 +401,25 @@ function_clause_2(<<_:4>>) -> ok. unit(Config) when is_list(Config) -> - ?line 42 = peek1(<<42>>), - ?line 43 = peek1(<<43,1,2>>), - ?line 43 = peek1(<<43,1,2,(-1):1>>), - ?line 43 = peek1(<<43,1,2,(-1):2>>), - ?line 43 = peek1(<<43,1,2,(-1):7>>), - - ?line 99 = peek8(<<99>>), - ?line 100 = peek8(<<100,101>>), - ?line fc(peek8, [<<100,101,0:1>>], catch peek8(<<100,101,0:1>>)), - - ?line 37484 = peek16(<<37484:16>>), - ?line 37489 = peek16(<<37489:16,5566:16>>), - ?line fc(peek16, [<<8>>], catch peek16(<<8>>)), - ?line fc(peek16, [<<42:15>>], catch peek16(<<42:15>>)), - ?line fc(peek16, [<<1,2,3,4,5>>], catch peek16(<<1,2,3,4,5>>)), - - ?line 127 = peek7(<<127:7>>), - ?line 100 = peek7(<<100:7,19:7>>), - ?line fc(peek7, [<<1,2>>], catch peek7(<<1,2>>)), + 42 = peek1(<<42>>), + 43 = peek1(<<43,1,2>>), + 43 = peek1(<<43,1,2,(-1):1>>), + 43 = peek1(<<43,1,2,(-1):2>>), + 43 = peek1(<<43,1,2,(-1):7>>), + + 99 = peek8(<<99>>), + 100 = peek8(<<100,101>>), + fc(peek8, [<<100,101,0:1>>], catch peek8(<<100,101,0:1>>)), + + 37484 = peek16(<<37484:16>>), + 37489 = peek16(<<37489:16,5566:16>>), + fc(peek16, [<<8>>], catch peek16(<<8>>)), + fc(peek16, [<<42:15>>], catch peek16(<<42:15>>)), + fc(peek16, [<<1,2,3,4,5>>], catch peek16(<<1,2,3,4,5>>)), + + 127 = peek7(<<127:7>>), + 100 = peek7(<<100:7,19:7>>), + fc(peek7, [<<1,2>>], catch peek7(<<1,2>>)), ok. peek1(<<B:8,_/bitstring>>) -> B. @@ -429,7 +431,7 @@ peek8(<<B:8,_/binary>>) -> B. peek16(<<B:16,_/binary-unit:16>>) -> B. shared_sub_bins(Config) when is_list(Config) -> - ?line {15,[<<>>,<<5>>,<<4,5>>,<<3,4,5>>,<<2,3,4,5>>]} = sum(<<1,2,3,4,5>>, [], 0), + {15,[<<>>,<<5>>,<<4,5>>,<<3,4,5>>,<<2,3,4,5>>]} = sum(<<1,2,3,4,5>>, [], 0), ok. sum(<<B,T/binary>>, Acc, Sum) -> @@ -438,7 +440,7 @@ sum(<<>>, Last, Sum) -> {Sum,Last}. bin_and_float(Config) when is_list(Config) -> - ?line 14.0 = bin_and_float(<<1.0/float,2.0/float,3.0/float>>, 0.0), + 14.0 = bin_and_float(<<1.0/float,2.0/float,3.0/float>>, 0.0), ok. bin_and_float(<<X/float,Y/float,Z/float,T/binary>>, Sum) when is_float(X), @@ -448,10 +450,10 @@ bin_and_float(<<X/float,Y/float,Z/float,T/binary>>, Sum) when is_float(X), bin_and_float(<<>>, Sum) -> Sum. dec_subidentifiers(Config) when is_list(Config) -> - ?line {[],<<1,2,3>>} = + {[],<<1,2,3>>} = do_dec_subidentifiers(<<1:1,42:7,1:1,99:7,1,2,3>>, 0, [], 2), - ?line {[5389],<<1,2,3>>} = do_dec_subidentifiers(<<1:1,42:7,0:1,13:7,1,2,3>>, 0, [], 2), - ?line {[3,2,1],not_a_binary} = dec_subidentifiers(not_a_binary, any, [1,2,3], 0), + {[5389],<<1,2,3>>} = do_dec_subidentifiers(<<1:1,42:7,0:1,13:7,1,2,3>>, 0, [], 2), + {[3,2,1],not_a_binary} = dec_subidentifiers(not_a_binary, any, [1,2,3], 0), ok. do_dec_subidentifiers(Buffer, Av, Al, Len) -> @@ -507,18 +509,18 @@ skip_optional_tag(_, _) -> missing. wfbm(Config) when is_list(Config) -> %% check_for_dot_or_space and get_tail is from wfbm4 by Steve Vinoski, %% with modifications. - ?line {nomatch,0} = check_for_dot_or_space(<<" ">>), - ?line {nomatch,0} = check_for_dot_or_space(<<" abc">>), - ?line {ok,<<"abcde">>} = check_for_dot_or_space(<<"abcde 34555">>), - ?line {nomatch,0} = check_for_dot_or_space(<<".gurka">>), - ?line {nomatch,1} = check_for_dot_or_space(<<"g.urka">>), - - ?line nomatch = get_tail(<<>>), - ?line {ok,<<"2007/10/23/blurf">>} = get_tail(<<"200x/2007/10/23/blurf ">>), - ?line {skip,?DATELEN+5} = get_tail(<<"200x/2007/10/23/blurf.">>), - ?line nomatch = get_tail(<<"200y.2007.10.23.blurf ">>), - ?line {'EXIT',_} = (catch get_tail({no,binary,at,all})), - ?line {'EXIT',_} = (catch get_tail(no_binary)), + {nomatch,0} = check_for_dot_or_space(<<" ">>), + {nomatch,0} = check_for_dot_or_space(<<" abc">>), + {ok,<<"abcde">>} = check_for_dot_or_space(<<"abcde 34555">>), + {nomatch,0} = check_for_dot_or_space(<<".gurka">>), + {nomatch,1} = check_for_dot_or_space(<<"g.urka">>), + + nomatch = get_tail(<<>>), + {ok,<<"2007/10/23/blurf">>} = get_tail(<<"200x/2007/10/23/blurf ">>), + {skip,?DATELEN+5} = get_tail(<<"200x/2007/10/23/blurf.">>), + nomatch = get_tail(<<"200y.2007.10.23.blurf ">>), + {'EXIT',_} = (catch get_tail({no,binary,at,all})), + {'EXIT',_} = (catch get_tail(no_binary)), ok. check_for_dot_or_space(Bin) -> @@ -551,13 +553,13 @@ get_tail(Bin) -> end. degenerated_match(Config) when is_list(Config) -> - ?line error = degenerated_match_1(<<>>), - ?line 1 = degenerated_match_1(<<1:1>>), - ?line 2 = degenerated_match_1(<<42,43>>), + error = degenerated_match_1(<<>>), + 1 = degenerated_match_1(<<1:1>>), + 2 = degenerated_match_1(<<42,43>>), - ?line error = degenerated_match_2(<<>>), - ?line no_split = degenerated_match_2(<<1,2>>), - ?line {<<1,2,3,4>>,<<5>>} = degenerated_match_2(<<1,2,3,4,5>>), + error = degenerated_match_2(<<>>), + no_split = degenerated_match_2(<<1,2>>), + {<<1,2,3,4>>,<<5>>} = degenerated_match_2(<<1,2,3,4,5>>), ok. @@ -574,25 +576,25 @@ degenerated_match_2(Bin) -> end. bs_sum(Config) when is_list(Config) -> - ?line 0 = bs_sum_1([]), - ?line 0 = bs_sum_1(<<>>), - ?line 42 = bs_sum_1([42]), - ?line 1 = bs_sum_1(<<1>>), - ?line 10 = bs_sum_1([1,2,3,4]), - ?line 15 = bs_sum_1(<<1,2,3,4,5>>), - ?line 21 = bs_sum_1([1,2,3|<<4,5,6>>]), - ?line 15 = bs_sum_1([1,2,3|{4,5}]), - ?line 6 = bs_sum_1([1,2,3|zero]), - ?line 6 = bs_sum_1([1,2,3|0]), - ?line 7 = bs_sum_1([1,2,3|one]), - - ?line fc(catch bs_sum_1({too,big,tuple})), - ?line fc(catch bs_sum_1([1,2,3|{too,big,tuple}])), - - ?line [] = sneaky_alias(<<>>), - ?line [559,387655] = sneaky_alias(id(<<559:32,387655:32>>)), - ?line fc(sneaky_alias, [<<1>>], catch sneaky_alias(id(<<1>>))), - ?line fc(sneaky_alias, [[1,2,3,4]], catch sneaky_alias(lists:seq(1, 4))), + 0 = bs_sum_1([]), + 0 = bs_sum_1(<<>>), + 42 = bs_sum_1([42]), + 1 = bs_sum_1(<<1>>), + 10 = bs_sum_1([1,2,3,4]), + 15 = bs_sum_1(<<1,2,3,4,5>>), + 21 = bs_sum_1([1,2,3|<<4,5,6>>]), + 15 = bs_sum_1([1,2,3|{4,5}]), + 6 = bs_sum_1([1,2,3|zero]), + 6 = bs_sum_1([1,2,3|0]), + 7 = bs_sum_1([1,2,3|one]), + + fc(catch bs_sum_1({too,big,tuple})), + fc(catch bs_sum_1([1,2,3|{too,big,tuple}])), + + [] = sneaky_alias(<<>>), + [559,387655] = sneaky_alias(id(<<559:32,387655:32>>)), + fc(sneaky_alias, [<<1>>], catch sneaky_alias(id(<<1>>))), + fc(sneaky_alias, [[1,2,3,4]], catch sneaky_alias(lists:seq(1, 4))), ok. bs_sum_1(<<H,T/binary>>) -> H+bs_sum_1(T); @@ -608,31 +610,31 @@ sneaky_alias(<<>>=L) -> binary_to_list(L); sneaky_alias(<<From:32,L/binary>>) -> [From|sneaky_alias(L)]. coverage(Config) when is_list(Config) -> - ?line 0 = coverage_fold(fun(B, A) -> A+B end, 0, <<>>), - ?line 6 = coverage_fold(fun(B, A) -> A+B end, 0, <<1,2,3>>), - ?line fc(catch coverage_fold(fun(B, A) -> + 0 = coverage_fold(fun(B, A) -> A+B end, 0, <<>>), + 6 = coverage_fold(fun(B, A) -> A+B end, 0, <<1,2,3>>), + fc(catch coverage_fold(fun(B, A) -> A+B end, 0, [a,b,c])), - ?line {<<42.0:64/float>>,float} = coverage_build(<<>>, <<42>>, float), - ?line {<<>>,not_a_tuple} = coverage_build(<<>>, <<>>, not_a_tuple), - ?line {<<16#76,"abc",16#A9,"abc">>,{x,42,43}} = + {<<42.0:64/float>>,float} = coverage_build(<<>>, <<42>>, float), + {<<>>,not_a_tuple} = coverage_build(<<>>, <<>>, not_a_tuple), + {<<16#76,"abc",16#A9,"abc">>,{x,42,43}} = coverage_build(<<>>, <<16#7,16#A>>, {x,y,z}), - ?line [<<2>>,<<1>>] = coverage_bc(<<1,2>>, []), + [<<2>>,<<1>>] = coverage_bc(<<1,2>>, []), - ?line {x,<<"abc">>,z} = coverage_setelement(<<2,"abc">>, {x,y,z}), + {x,<<"abc">>,z} = coverage_setelement(<<2,"abc">>, {x,y,z}), - ?line [42] = coverage_apply(<<42>>, [coverage_id]), - ?line 42 = coverage_external(<<42>>), + [42] = coverage_apply(<<42>>, [coverage_id]), + 42 = coverage_external(<<42>>), - ?line do_coverage_bin_to_term_list([]), - ?line do_coverage_bin_to_term_list([lists:seq(0, 10),{a,b,c},<<23:42>>]), - ?line fc(coverage_bin_to_term_list, [<<0,0,0,7>>], + do_coverage_bin_to_term_list([]), + do_coverage_bin_to_term_list([lists:seq(0, 10),{a,b,c},<<23:42>>]), + fc(coverage_bin_to_term_list, [<<0,0,0,7>>], catch do_coverage_bin_to_term_list_1(<<7:32>>)), - ?line <<>> = coverage_per_key(<<4:32>>), - ?line <<$a,$b,$c>> = coverage_per_key(<<7:32,"abc">>), + <<>> = coverage_per_key(<<4:32>>), + <<$a,$b,$c>> = coverage_per_key(<<7:32,"abc">>), ok. @@ -725,9 +727,9 @@ coverage_per_key(<<BinSize:32,Bin/binary>> = B) -> Bin. multiple_uses(Config) when is_list(Config) -> - ?line {344,62879,345,<<245,159,1,89>>} = multiple_uses_1(<<1,88,245,159,1,89>>), - ?line true = multiple_uses_2(<<0,0,197,18>>), - ?line <<42,43>> = multiple_uses_3(<<0,0,42,43>>, fun id/1), + {344,62879,345,<<245,159,1,89>>} = multiple_uses_1(<<1,88,245,159,1,89>>), + true = multiple_uses_2(<<0,0,197,18>>), + <<42,43>> = multiple_uses_3(<<0,0,42,43>>, fun id/1), ok. multiple_uses_1(<<X:16,Tail/binary>>) -> @@ -750,8 +752,8 @@ multiple_uses_cmp(<<Y:16>>, <<Y:16>>) -> true; multiple_uses_cmp(<<_:16>>, <<_:16>>) -> false. zero_label(Config) when is_list(Config) -> - ?line <<"nosemouth">> = read_pols(<<"FACE","nose","mouth">>), - ?line <<"CE">> = read_pols(<<"noFACE">>), + <<"nosemouth">> = read_pols(<<"FACE","nose","mouth">>), + <<"CE">> = read_pols(<<"noFACE">>), ok. read_pols(Data) -> @@ -779,14 +781,14 @@ matching_meets_construction(Config) when is_list(Config) -> Bin = id(<<"abc">>), Len = id(2), Tail0 = id(<<1,2,3,4,5>>), - ?line <<_:Len/binary,Tail/binary>> = Tail0, - ?line Res = <<Tail/binary,Bin/binary>>, - ?line <<3,4,5,"abc">> = Res, - ?line {'EXIT',{badarg,_}} = (catch matching_meets_construction_1(<<"Abc">>)), - ?line {'EXIT',{badarg,_}} = (catch matching_meets_construction_2(<<"Abc">>)), - ?line <<"Bbc">> = matching_meets_construction_3(<<"Abc">>), - - ?line <<1,2>> = encode_octet_string(<<1,2,3>>, 2), + <<_:Len/binary,Tail/binary>> = Tail0, + Res = <<Tail/binary,Bin/binary>>, + <<3,4,5,"abc">> = Res, + {'EXIT',{badarg,_}} = (catch matching_meets_construction_1(<<"Abc">>)), + {'EXIT',{badarg,_}} = (catch matching_meets_construction_2(<<"Abc">>)), + <<"Bbc">> = matching_meets_construction_3(<<"Abc">>), + + <<1,2>> = encode_octet_string(<<1,2,3>>, 2), ok. matching_meets_construction_1(<<"A",H/binary>>) -> <<"B",H>>. @@ -799,14 +801,14 @@ encode_octet_string(<<OctetString/binary>>, Len) -> <<OctetString:Len/binary-unit:8>>. simon(Config) when is_list(Config) -> - ?line one = simon(blurf, <<>>), - ?line two = simon(0, <<42>>), - ?line fc(simon, [17,<<1>>], catch simon(17, <<1>>)), - ?line fc(simon, [0,<<1,2,3>>], catch simon(0, <<1,2,3>>)), - - ?line one = simon2(blurf, <<9>>), - ?line two = simon2(0, <<9,1>>), - ?line fc(simon2, [0,<<9,10,11>>], catch simon2(0, <<9,10,11>>)), + one = simon(blurf, <<>>), + two = simon(0, <<42>>), + fc(simon, [17,<<1>>], catch simon(17, <<1>>)), + fc(simon, [0,<<1,2,3>>], catch simon(0, <<1,2,3>>)), + + one = simon2(blurf, <<9>>), + two = simon2(0, <<9,1>>), + fc(simon2, [0,<<9,10,11>>], catch simon2(0, <<9,10,11>>)), ok. simon(_, <<>>) -> one; @@ -818,10 +820,10 @@ simon2(0, <<_:16>>) -> two. %% OTP-7113: Crash in v3_codegen. matching_and_andalso(Config) when is_list(Config) -> - ?line ok = matching_and_andalso_1(<<1,2,3>>, 3), - ?line {'EXIT',{function_clause,_}} = (catch matching_and_andalso_1(<<1,2,3>>, -8)), - ?line {'EXIT',{function_clause,_}} = (catch matching_and_andalso_1(<<1,2,3>>, blurf)), - ?line {'EXIT',{function_clause,_}} = (catch matching_and_andalso_1(<<1,2,3>>, 19)), + ok = matching_and_andalso_1(<<1,2,3>>, 3), + {'EXIT',{function_clause,_}} = (catch matching_and_andalso_1(<<1,2,3>>, -8)), + {'EXIT',{function_clause,_}} = (catch matching_and_andalso_1(<<1,2,3>>, blurf)), + {'EXIT',{function_clause,_}} = (catch matching_and_andalso_1(<<1,2,3>>, 19)), {"abc",<<"xyz">>} = matching_and_andalso_2("abc", <<"-xyz">>), {"abc",<<"">>} = matching_and_andalso_2("abc", <<($a-1)>>), @@ -854,7 +856,7 @@ otp_7188(Config) when is_list(Config) -> 0,0,0,0,0,0,50,48,48,48,50,48,48,48,32,45,32,66,101,115, 116,32,79,102,32,32,32,32,32,32,32,32,32,32,32,32,32,32, 32,32,12>>, - ?line {ok,{"ID3v1", + {ok,{"ID3v1", [{title,<<68,117,154,105,232,107,121>>}, {artist,<<"Daniel Landa">>}, {album,<<"Best Of">>}]}} = parse_v1_or_v11_tag(MP3). @@ -898,11 +900,11 @@ skip_blanks_and_zero(L) -> -record(rec_otp_7233, {key, val}). otp_7233(Config) when is_list(Config) -> - ?line otp_7233_1(#rec_otp_7233{key = <<"XXabcde">>,val=[{"xxxxxxxx",42}]}), - ?line [<<"XXabcde">>,{"xxxxxxxx",42}] = get(io_format), + otp_7233_1(#rec_otp_7233{key = <<"XXabcde">>,val=[{"xxxxxxxx",42}]}), + [<<"XXabcde">>,{"xxxxxxxx",42}] = get(io_format), erase(io_format), - ?line otp_7233_1(#rec_otp_7233{key = <<"XXabcde">>,val=[]}), - ?line undefined = get(io_format), + otp_7233_1(#rec_otp_7233{key = <<"XXabcde">>,val=[]}), + undefined = get(io_format), ok. otp_7233_1(Rec) -> @@ -910,32 +912,34 @@ otp_7233_1(Rec) -> case K of <<"XX">> -> Value = Rec#rec_otp_7233.val, - case lists:keysearch("xxxxxxxx", 1, Value) of - {value,T} -> put(io_format, [Rec#rec_otp_7233.key,T]); - false -> ok + case lists:keyfind("xxxxxxxx", 1, Value) of + false -> + ok; + T -> + put(io_format, [Rec#rec_otp_7233.key,T]) end; _ -> ok end. otp_7240(Config) when is_list(Config) -> - ?line a = otp_7240_a(0, <<>>), - ?line b = otp_7240_a(1, 2), + a = otp_7240_a(0, <<>>), + b = otp_7240_a(1, 2), - ?line a = otp_7240_b(anything, <<>>), - ?line b = otp_7240_b(1, {x,y}), + a = otp_7240_b(anything, <<>>), + b = otp_7240_b(1, {x,y}), - ?line a = otp_7240_c(anything, <<>>), - ?line b = otp_7240_c(1, <<2>>), + a = otp_7240_c(anything, <<>>), + b = otp_7240_c(1, <<2>>), - ?line a = otp_7240_d(anything, <<>>), - ?line b = otp_7240_d(again, <<2>>), + a = otp_7240_d(anything, <<>>), + b = otp_7240_d(again, <<2>>), - ?line a = otp_7240_e(anything, <<>>), - ?line b = otp_7240_e(1, 41), + a = otp_7240_e(anything, <<>>), + b = otp_7240_e(1, 41), - ?line a = otp_7240_f(anything, <<>>), - ?line b = otp_7240_f(1, {}), + a = otp_7240_f(anything, <<>>), + b = otp_7240_f(1, {}), ok. @@ -958,15 +962,15 @@ otp_7240_f(_, <<>>) -> a; otp_7240_f(1, B) when is_tuple(B) -> b. otp_7498(Config) when is_list(Config) -> - ?line <<1,2,3>> = otp_7498_foo(<<1,2,3>>, 0), - ?line <<2,3>> = otp_7498_foo(<<1,2,3>>, 1), - ?line <<1,2,3>> = otp_7498_foo(<<1,2,3>>, 2), + <<1,2,3>> = otp_7498_foo(<<1,2,3>>, 0), + <<2,3>> = otp_7498_foo(<<1,2,3>>, 1), + <<1,2,3>> = otp_7498_foo(<<1,2,3>>, 2), - ?line <<1,2,3>> = otp_7498_bar(<<1,2,3>>, 0), - ?line <<2,3>> = otp_7498_bar(<<1,2,3>>, 1), - ?line <<1,2,3>> = otp_7498_bar(<<1,2,3>>, 2), - ?line <<>> = otp_7498_bar(<<>>, 2), - ?line <<1,2,3>> = otp_7498_bar(<<1,2,3>>, 3), + <<1,2,3>> = otp_7498_bar(<<1,2,3>>, 0), + <<2,3>> = otp_7498_bar(<<1,2,3>>, 1), + <<1,2,3>> = otp_7498_bar(<<1,2,3>>, 2), + <<>> = otp_7498_bar(<<>>, 2), + <<1,2,3>> = otp_7498_bar(<<1,2,3>>, 3), ok. @@ -995,19 +999,19 @@ match_string(Config) when is_list(Config) -> %% check the coverage for the v3_kernel module. case erlang:system_info(endian) of little -> - ?line do_match_string_native(<<$a,0,$b,0>>); + do_match_string_native(<<$a,0,$b,0>>); big -> - ?line do_match_string_native(<<0,$a,0,$b>>) + do_match_string_native(<<0,$a,0,$b>>) end, - ?line do_match_string_big(<<0,$a,0,$b>>), - ?line do_match_string_little(<<$a,0,$b,0>>), + do_match_string_big(<<0,$a,0,$b>>), + do_match_string_little(<<$a,0,$b,0>>), - ?line do_match_string_big_signed(<<255,255>>), - ?line do_match_string_little_signed(<<255,255>>), + do_match_string_big_signed(<<255,255>>), + do_match_string_little_signed(<<255,255>>), - ?line plain = no_match_string_opt(<<"abc">>), - ?line strange = no_match_string_opt(<<$a:9,$b:9,$c:9>>), + plain = no_match_string_opt(<<"abc">>), + strange = no_match_string_opt(<<$a:9,$b:9,$c:9>>), ok. @@ -1028,13 +1032,13 @@ no_match_string_opt(<<$a:9,$b:9,$c:9>>) -> strange. %% OTP-7591: A zero-width segment in matching would crash the compiler. zero_width(Config) when is_list(Config) -> - ?line <<Len:16/little, Str:Len/binary, 0:0>> = <<2, 0, $h, $i, 0:0>>, - ?line 2 = Len, - ?line Str = <<"hi">>, + <<Len:16/little, Str:Len/binary, 0:0>> = <<2, 0, $h, $i, 0:0>>, + 2 = Len, + Str = <<"hi">>, %% Match sure that values that cannot fit in a segment will not match. case id(<<0:8>>) of - <<256:8>> -> ?line ?t:fail(); + <<256:8>> -> ct:fail(should_not_match); _ -> ok end, ok. @@ -1043,14 +1047,14 @@ zero_width(Config) when is_list(Config) -> %% OTP_7650: A invalid size for binary segments could crash the compiler. bad_size(Config) when is_list(Config) -> Tuple = {a,b,c}, - ?line {'EXIT',{{badmatch,<<>>},_}} = (catch <<32:Tuple>> = id(<<>>)), + {'EXIT',{{badmatch,<<>>},_}} = (catch <<32:Tuple>> = id(<<>>)), Binary = <<1,2,3>>, - ?line {'EXIT',{{badmatch,<<>>},_}} = (catch <<32:Binary>> = id(<<>>)), + {'EXIT',{{badmatch,<<>>},_}} = (catch <<32:Binary>> = id(<<>>)), ok. haystack(Config) when is_list(Config) -> - ?line <<0:10/unit:8>> = haystack_1(<<0:10/unit:8>>), - ?line [<<0:10/unit:8>>, + <<0:10/unit:8>> = haystack_1(<<0:10/unit:8>>), + [<<0:10/unit:8>>, <<0:20/unit:8>>] = haystack_2(<<1:8192>>), ok. @@ -1085,10 +1089,10 @@ fc(_, Args, {'EXIT',{{case_clause,ActualArgs},_}}) %% Cover the clause handling bs_context to binary in %% beam_block:initialized_regs/2. cover_beam_bool(Config) when is_list(Config) -> - ?line ok = do_cover_beam_bool(<<>>, 3), - ?line <<19>> = do_cover_beam_bool(<<19>>, 2), - ?line <<42>> = do_cover_beam_bool(<<42>>, 1), - ?line <<17>> = do_cover_beam_bool(<<13,17>>, 0), + ok = do_cover_beam_bool(<<>>, 3), + <<19>> = do_cover_beam_bool(<<19>>, 2), + <<42>> = do_cover_beam_bool(<<42>>, 1), + <<17>> = do_cover_beam_bool(<<13,17>>, 0), ok. do_cover_beam_bool(Bin, X) when X > 0 -> @@ -1293,6 +1297,96 @@ do_unsafe_branch_caching(<<Code/integer, Bin/binary>>) -> _ -> Bin2 end. +bad_literals(_Config) -> + Mod = list_to_atom(?MODULE_STRING ++ "_" ++ + atom_to_list(?FUNCTION_NAME)), + S = [signed_lit_match(V, Sz) || V <- lists:seq(-8, 8), + Sz <- [0,1,2,3]] ++ + [unsigned_lit_match(V, Sz) || V <- lists:seq(-2, 8), + Sz <- [0,1,2]] ++ + [unicode_match(V) || + V <- [-100,-1,0,1,2|lists:seq(16#10FFFC, 16#110004)]], + Code = ?Q(["-module('@Mod@').\n" + "-export([f/0]).\n" + "f() ->\n" + "_@S,\n" + "ok.\n"]), + merl:print(Code), + Opts = test_lib:opt_opts(?MODULE), + {ok,_} = merl:compile_and_load(Code, Opts), + Mod:f(), + + {'EXIT',<<42>>} = (catch bad_literals_1()), + + Sz = id(8), + {'EXIT',{{badmatch,_},_}} = (catch <<-1:Sz>> = <<-1>>), + ok. + +bad_literals_1() -> + BadSz = bad, + case case <<42>> of + <<42:BadSz>> -> ok; + Val -> exit(Val) + end of + ok -> ok; + error -> error + end. + +signed_lit_match(V, Sz) -> + case <<V:Sz>> of + <<V:Sz/signed>> -> + ?Q("<<_@V@:_@Sz@/signed>> = <<_@V@:_@Sz@>>"); + _ -> + ?Q(["case <<_@V@:_@Sz@>> of\n", + " <<_@V@:_@Sz@/signed>> ->\n", + " ct:fail(should_not_match);\n", + " _ ->\n", + " ok\n", + "end\n"]) + end. + +unsigned_lit_match(V, Sz) -> + case <<V:Sz>> of + <<V:Sz/unsigned>> -> + ?Q("<<_@V@:_@Sz@>> = <<_@V@:_@Sz@>>"); + _ -> + ?Q(["case <<_@V@:_@Sz@>> of\n", + " <<_@V@:_@Sz@/unsigned>> ->\n", + " ct:fail(should_not_match);\n", + " _ ->\n", + " ok\n", + "end\n"]) + end. + +unicode_match(V) -> + try <<V/utf8>> of + <<V/utf8>> -> + ?Q(["<<_@V@/utf8>> = <<_@V@/utf8>>,\n", + "<<_@V@/utf16>> = <<_@V@/utf16>>,\n", + "<<_@V@/utf32>> = <<_@V@/utf32>>\n"]) + catch + error:badarg -> + ?Q(["case <<_@V@:32>> of\n", + " <<_@V@/utf32>> ->\n", + " ct:fail(should_not_match);\n", + " _ ->\n", + " ok\n", + "end\n"]) + end. + +%% Test a few legal but rare cases. + +good_literals(_Config) -> + Sz = id(64), + + %% Variable size. + <<42:Sz>> = id(<<42:Sz>>), + <<42.0:Sz/float>> = id(<<42:Sz/float>>), + + %% unit > 1 + <<16#cafebeef:4/unit:8>> = id(<<16#cafebeef:32>>), + ok. + check(F, R) -> R = F(). diff --git a/lib/compiler/test/bs_utf_SUITE.erl b/lib/compiler/test/bs_utf_SUITE.erl index ffe8de00d4..518e89a9cb 100644 --- a/lib/compiler/test/bs_utf_SUITE.erl +++ b/lib/compiler/test/bs_utf_SUITE.erl @@ -53,14 +53,14 @@ end_per_group(_GroupName, Config) -> utf8_roundtrip(Config) when is_list(Config) -> - ?line [utf8_roundtrip_1(P) || P <- utf_data()], + [utf8_roundtrip_1(P) || P <- utf_data()], ok. utf8_roundtrip_1({Str,Bin,Bin}) -> - ?line Str = utf8_to_list(Bin), - ?line Bin = list_to_utf8(Str), - ?line [ok = utf8_guard(C, <<42,C/utf8>>) || C <- Str], - ?line [error = utf8_guard(C, <<C/utf8>>) || C <- Str], + Str = utf8_to_list(Bin), + Bin = list_to_utf8(Str), + [ok = utf8_guard(C, <<42,C/utf8>>) || C <- Str], + [error = utf8_guard(C, <<C/utf8>>) || C <- Str], ok. utf8_guard(C, Bin) when <<42,C/utf8>> =:= Bin -> ok; @@ -90,14 +90,14 @@ utf8_len(<<_/utf8,T/binary>>, N) -> utf8_len(<<>>, N) -> N. utf16_roundtrip(Config) when is_list(Config) -> - ?line {Str,Big,Big,Little,Little} = utf16_data(), - ?line 4 = utf16_big_len(Big), - ?line 4 = utf16_little_len(Little), - ?line Str = big_utf16_to_list(Big), - ?line Str = little_utf16_to_list(Little), + {Str,Big,Big,Little,Little} = utf16_data(), + 4 = utf16_big_len(Big), + 4 = utf16_little_len(Little), + Str = big_utf16_to_list(Big), + Str = little_utf16_to_list(Little), - ?line Big = list_to_big_utf16(Str), - ?line Little = list_to_little_utf16(Str), + Big = list_to_big_utf16(Str), + Little = list_to_little_utf16(Str), ok. @@ -138,14 +138,14 @@ little_utf16_to_list(<<H/little-utf16,T/binary>>) -> little_utf16_to_list(<<>>) -> []. utf32_roundtrip(Config) when is_list(Config) -> - ?line {Str,Big,Big,Little,Little} = utf32_data(), - ?line 4 = utf32_big_len(Big), - ?line 4 = utf32_little_len(Little), - ?line Str = big_utf32_to_list(Big), - ?line Str = little_utf32_to_list(Little), + {Str,Big,Big,Little,Little} = utf32_data(), + 4 = utf32_big_len(Big), + 4 = utf32_little_len(Little), + Str = big_utf32_to_list(Big), + Str = little_utf32_to_list(Little), - ?line Big = list_to_big_utf32(Str), - ?line Little = list_to_little_utf32(Str), + Big = list_to_big_utf32(Str), + Little = list_to_little_utf32(Str), ok. @@ -187,7 +187,7 @@ little_utf32_to_list(<<>>) -> []. guard(Config) when is_list(Config) -> - ?line error = do_guard(16#D800), + error = do_guard(16#D800), ok. do_guard(C) when byte_size(<<C/utf8>>) =/= 42 -> ok; @@ -199,13 +199,13 @@ do_guard(_) -> error. %% the delayed creation of sub-binaries works. extreme_tripping(Config) when is_list(Config) -> - ?line Unicode = lists:seq(0, 1024), - ?line Utf8 = unicode_to_utf8(Unicode, <<>>), - ?line Utf16 = utf8_to_utf16(Utf8, <<>>), - ?line Utf32 = utf8_to_utf32(Utf8, <<>>), - ?line Utf32 = utf16_to_utf32(Utf16, <<>>), - ?line Utf8 = utf32_to_utf8(Utf32, <<>>), - ?line Unicode = utf32_to_unicode(Utf32), + Unicode = lists:seq(0, 1024), + Utf8 = unicode_to_utf8(Unicode, <<>>), + Utf16 = utf8_to_utf16(Utf8, <<>>), + Utf32 = utf8_to_utf32(Utf8, <<>>), + Utf32 = utf16_to_utf32(Utf16, <<>>), + Utf8 = utf32_to_utf8(Utf32, <<>>), + Unicode = utf32_to_unicode(Utf32), ok. unicode_to_utf8([C|T], Bin) -> @@ -233,58 +233,58 @@ utf32_to_unicode(<<C/utf32,T/binary>>) -> utf32_to_unicode(<<>>) -> []. literals(Config) when is_list(Config) -> - ?line abc_utf8 = match_literal(<<"abc"/utf8>>), - ?line abc_utf8 = match_literal(<<$a,$b,$c>>), - - ?line abc_utf16be = match_literal(<<"abc"/utf16>>), - ?line abc_utf16be = match_literal(<<$a:16,$b:16,$c:16>>), - ?line abc_utf16le = match_literal(<<"abc"/little-utf16>>), - ?line abc_utf16le = match_literal(<<$a:16/little,$b:16/little,$c:16/little>>), - - ?line abc_utf32be = match_literal(<<"abc"/utf32>>), - ?line abc_utf32be = match_literal(<<$a:32,$b:32,$c:32>>), - ?line abc_utf32le = match_literal(<<"abc"/little-utf32>>), - ?line abc_utf32le = match_literal(<<$a:32/little,$b:32/little,$c:32/little>>), - - ?line bjorn_utf8 = match_literal(<<"bj\366rn"/utf8>>), - ?line bjorn_utf8 = match_literal(<<$b,$j,195,182,$r,$n>>), - - ?line bjorn_utf16be = match_literal(<<"bj\366rn"/utf16>>), - ?line bjorn_utf16be = match_literal(<<$b:16,$j:16,246:16,$r:16,$n:16>>), - ?line bjorn_utf16le = match_literal(<<"bj\366rn"/little-utf16>>), - ?line bjorn_utf16le = match_literal(<<$b:16/little,$j:16/little, + abc_utf8 = match_literal(<<"abc"/utf8>>), + abc_utf8 = match_literal(<<$a,$b,$c>>), + + abc_utf16be = match_literal(<<"abc"/utf16>>), + abc_utf16be = match_literal(<<$a:16,$b:16,$c:16>>), + abc_utf16le = match_literal(<<"abc"/little-utf16>>), + abc_utf16le = match_literal(<<$a:16/little,$b:16/little,$c:16/little>>), + + abc_utf32be = match_literal(<<"abc"/utf32>>), + abc_utf32be = match_literal(<<$a:32,$b:32,$c:32>>), + abc_utf32le = match_literal(<<"abc"/little-utf32>>), + abc_utf32le = match_literal(<<$a:32/little,$b:32/little,$c:32/little>>), + + bjorn_utf8 = match_literal(<<"bj\366rn"/utf8>>), + bjorn_utf8 = match_literal(<<$b,$j,195,182,$r,$n>>), + + bjorn_utf16be = match_literal(<<"bj\366rn"/utf16>>), + bjorn_utf16be = match_literal(<<$b:16,$j:16,246:16,$r:16,$n:16>>), + bjorn_utf16le = match_literal(<<"bj\366rn"/little-utf16>>), + bjorn_utf16le = match_literal(<<$b:16/little,$j:16/little, 246:16/little,$r:16/little, $n:16/little>>), - ?line <<244,143,191,191>> = <<16#10ffff/utf8>>, + <<244,143,191,191>> = <<16#10ffff/utf8>>, %% Invalid literals. I = 0, - ?line {'EXIT',{badarg,_}} = (catch <<(-1)/utf8,I/utf8>>), - ?line {'EXIT',{badarg,_}} = (catch <<(-1)/utf16,I/utf8>>), - ?line {'EXIT',{badarg,_}} = (catch <<(-1)/little-utf16,I/utf8>>), - ?line {'EXIT',{badarg,_}} = (catch <<(-1)/utf32,I/utf8>>), - ?line {'EXIT',{badarg,_}} = (catch <<(-1)/little-utf32,I/utf8>>), - ?line {'EXIT',{badarg,_}} = (catch <<16#D800/utf8,I/utf8>>), - ?line {'EXIT',{badarg,_}} = (catch <<16#D800/utf16,I/utf8>>), - ?line {'EXIT',{badarg,_}} = (catch <<16#D800/little-utf16,I/utf8>>), - ?line {'EXIT',{badarg,_}} = (catch <<16#D800/utf32,I/utf8>>), - ?line {'EXIT',{badarg,_}} = (catch <<16#D800/little-utf32,I/utf8>>), + {'EXIT',{badarg,_}} = (catch <<(-1)/utf8,I/utf8>>), + {'EXIT',{badarg,_}} = (catch <<(-1)/utf16,I/utf8>>), + {'EXIT',{badarg,_}} = (catch <<(-1)/little-utf16,I/utf8>>), + {'EXIT',{badarg,_}} = (catch <<(-1)/utf32,I/utf8>>), + {'EXIT',{badarg,_}} = (catch <<(-1)/little-utf32,I/utf8>>), + {'EXIT',{badarg,_}} = (catch <<16#D800/utf8,I/utf8>>), + {'EXIT',{badarg,_}} = (catch <<16#D800/utf16,I/utf8>>), + {'EXIT',{badarg,_}} = (catch <<16#D800/little-utf16,I/utf8>>), + {'EXIT',{badarg,_}} = (catch <<16#D800/utf32,I/utf8>>), + {'EXIT',{badarg,_}} = (catch <<16#D800/little-utf32,I/utf8>>), B = 16#10FFFF+1, - ?line {'EXIT',{badarg,_}} = (catch <<B/utf8>>), - ?line {'EXIT',{badarg,_}} = (catch <<B/utf16>>), - ?line {'EXIT',{badarg,_}} = (catch <<B/little-utf16>>), - ?line {'EXIT',{badarg,_}} = (catch <<B/utf32>>), - ?line {'EXIT',{badarg,_}} = (catch <<B/little-utf32>>), + {'EXIT',{badarg,_}} = (catch <<B/utf8>>), + {'EXIT',{badarg,_}} = (catch <<B/utf16>>), + {'EXIT',{badarg,_}} = (catch <<B/little-utf16>>), + {'EXIT',{badarg,_}} = (catch <<B/utf32>>), + {'EXIT',{badarg,_}} = (catch <<B/little-utf32>>), %% Matching of bad literals. - ?line error = bad_literal_match(<<237,160,128>>), %16#D800 in UTF-8 - ?line error = bad_literal_match(<<244,144,128,128>>), %16#110000 in UTF-8 + error = bad_literal_match(<<237,160,128>>), %16#D800 in UTF-8 + error = bad_literal_match(<<244,144,128,128>>), %16#110000 in UTF-8 - ?line error = bad_literal_match(<<16#D800:32>>), - ?line error = bad_literal_match(<<16#110000:32>>), - ?line error = bad_literal_match(<<16#D800:32/little>>), - ?line error = bad_literal_match(<<16#110000:32/little>>), + error = bad_literal_match(<<16#D800:32>>), + error = bad_literal_match(<<16#110000:32>>), + error = bad_literal_match(<<16#D800:32/little>>), + error = bad_literal_match(<<16#110000:32/little>>), ok. @@ -307,13 +307,13 @@ bad_literal_match(_) -> error. coverage(Config) when is_list(Config) -> %% Cover bit syntax matching optimizations in v3_kernel. - ?line 0 = coverage_1(<<4096/utf8,65536/utf8,0>>), - ?line 1 = coverage_1(<<4096/utf8,65536/utf8,1>>), + 0 = coverage_1(<<4096/utf8,65536/utf8,0>>), + 1 = coverage_1(<<4096/utf8,65536/utf8,1>>), - ?line 0 = coverage_2(<<4096/utf8,65536/utf8,0>>), - ?line 1 = coverage_2(<<1024/utf8,1025/utf8,1>>), + 0 = coverage_2(<<4096/utf8,65536/utf8,0>>), + 1 = coverage_2(<<1024/utf8,1025/utf8,1>>), - ?line fc(catch coverage_3(1)), + fc(catch coverage_3(1)), %% Cover beam_flatten (combining the heap allocation in %% a subsequent test_heap instruction into the bs_init2 diff --git a/lib/compiler/test/compilation_SUITE.erl b/lib/compiler/test/compilation_SUITE.erl index 6bff5e55f2..76b7e852f1 100644 --- a/lib/compiler/test/compilation_SUITE.erl +++ b/lib/compiler/test/compilation_SUITE.erl @@ -24,7 +24,9 @@ -compile(export_all). -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,10}}]. all() -> test_lib:recompile(?MODULE), @@ -164,11 +166,9 @@ split({int, N}, <<N:16,B:N/binary,T/binary>>) -> ?comp(on_load). ?comp(on_load_inline). -beam_compiler_7(doc) -> - "Code snippet submitted from Ulf Wiger which fails in R3 Beam."; -beam_compiler_7(suite) -> []; +%% Code snippet submitted from Ulf Wiger which fails in R3 Beam. beam_compiler_7(Config) when is_list(Config) -> - ?line done = empty(2, false). + done = empty(2, false). empty(N, Toggle) when N > 0 -> %% R3 Beam copies the second argument to the first before call. @@ -194,16 +194,17 @@ redundant_case_1(4) -> d; redundant_case_1(_) -> d. failure(Module, Conf) -> - ?line Src = filename:join(?config(data_dir, Conf), atom_to_list(Module)), - ?line Out = ?config(priv_dir,Conf), - ?line io:format("Compiling: ~ts\n", [Src]), - ?line CompRc = compile:file(Src, [{outdir,Out},return,time]), - ?line io:format("Result: ~p\n",[CompRc]), - ?line case CompRc of - error -> ok; - {error,Errors,_} -> check_errors(Errors); - _ -> test_server:fail({no_error, CompRc}) - end, + Src = filename:join(proplists:get_value(data_dir, Conf), + atom_to_list(Module)), + Out = proplists:get_value(priv_dir, Conf), + io:format("Compiling: ~ts\n", [Src]), + CompRc = compile:file(Src, [{outdir,Out},return,time]), + io:format("Result: ~p\n",[CompRc]), + case CompRc of + error -> ok; + {error,Errors,_} -> check_errors(Errors); + _ -> ct:fail({no_error, CompRc}) + end, ok. check_errors([{_,Eds}|T]) -> @@ -224,7 +225,7 @@ check_error_1(Str0) -> io:format("~s\n", [Str]), case Str of "internal"++_=Str -> - ?t:fail(internal_compiler_error); + ct:fail(internal_compiler_error); _ -> ok end. @@ -234,51 +235,51 @@ check_error_1(Str0) -> try_it(Module, Conf) -> %% Change 'false' to 'true' to start a new node for every module. try_it(false, Module, Conf). - + try_it(StartNode, Module, Conf) -> - ?line OtherOpts = [], %Can be changed to [time] if needed - ?line Src = filename:join(?config(data_dir, Conf), atom_to_list(Module)), - ?line Out = ?config(priv_dir,Conf), - ?line io:format("Compiling: ~s\n", [Src]), - ?line CompRc0 = compile:file(Src, [clint,{outdir,Out},report, + try_it(StartNode, Module, {minutes,10}, Conf). + +try_it(StartNode, Module, Timetrap, Conf) -> + OtherOpts = [], %Can be changed to [time] if needed + Src = filename:join(proplists:get_value(data_dir, Conf), + atom_to_list(Module)), + Out = proplists:get_value(priv_dir,Conf), + io:format("Compiling: ~s\n", [Src]), + CompRc0 = compile:file(Src, [clint,{outdir,Out},report, bin_opt_info|OtherOpts]), - ?line io:format("Result: ~p\n",[CompRc0]), - ?line {ok,_Mod} = CompRc0, + io:format("Result: ~p\n",[CompRc0]), + {ok,_Mod} = CompRc0, - ?line Dog = test_server:timetrap(test_server:minutes(10)), Node = case StartNode of false -> node(); true -> - ?line Pa = "-pa " ++ filename:dirname(code:which(?MODULE)), - ?line {ok,Node0} = start_node(compiler, Pa), + Pa = "-pa " ++ filename:dirname(code:which(?MODULE)), + {ok,Node0} = start_node(compiler, Pa), Node0 end, - ?line ok = rpc:call(Node, ?MODULE, load_and_call, [Out, Module]), - ?line load_and_call(Out, Module), - ?line test_server:timetrap_cancel(Dog), + ok = rpc:call(Node, ?MODULE, load_and_call, [Out, Module]), + load_and_call(Out, Module), - ?line NewDog = test_server:timetrap(test_server:minutes(10)), - ?line io:format("Compiling (without optimization): ~s\n", [Src]), - ?line CompRc1 = compile:file(Src, + ct:timetrap(Timetrap), + io:format("Compiling (without optimization): ~s\n", [Src]), + CompRc1 = compile:file(Src, [no_copt,no_postopt,{outdir,Out},report|OtherOpts]), - ?line io:format("Result: ~p\n",[CompRc1]), - ?line {ok,_Mod} = CompRc1, - ?line ok = rpc:call(Node, ?MODULE, load_and_call, [Out, Module]), - ?line test_server:timetrap_cancel(NewDog), + io:format("Result: ~p\n",[CompRc1]), + {ok,_Mod} = CompRc1, + ok = rpc:call(Node, ?MODULE, load_and_call, [Out, Module]), - ?line LastDog = test_server:timetrap(test_server:minutes(10)), - ?line io:format("Compiling (with old inliner): ~s\n", [Src]), - ?line CompRc2 = compile:file(Src, [{outdir,Out},report,bin_opt_info, + ct:timetrap(Timetrap), + io:format("Compiling (with old inliner): ~s\n", [Src]), + CompRc2 = compile:file(Src, [{outdir,Out},report,bin_opt_info, {inline,1000}|OtherOpts]), - ?line io:format("Result: ~p\n",[CompRc2]), - ?line {ok,_Mod} = CompRc2, - ?line ok = rpc:call(Node, ?MODULE, load_and_call, [Out, Module]), - ?line test_server:timetrap_cancel(LastDog), + io:format("Result: ~p\n",[CompRc2]), + {ok,_Mod} = CompRc2, + ok = rpc:call(Node, ?MODULE, load_and_call, [Out, Module]), - AsmDog = test_server:timetrap(test_server:minutes(10)), + ct:timetrap(Timetrap), io:format("Compiling (from assembly): ~s\n", [Src]), {ok,_} = compile:file(Src, [to_asm,{outdir,Out},report|OtherOpts]), Asm = filename:join(Out, lists:concat([Module, ".S"])), @@ -286,28 +287,26 @@ try_it(StartNode, Module, Conf) -> io:format("Result: ~p\n",[CompRc3]), {ok,_} = CompRc3, ok = rpc:call(Node, ?MODULE, load_and_call, [Out, Module]), - test_server:timetrap_cancel(AsmDog), case StartNode of false -> ok; - true -> ?line test_server:stop_node(Node) + true -> test_server:stop_node(Node) end, - ?line test_server:timetrap_cancel(LastDog), ok. load_and_call(Out, Module) -> - ?line io:format("Loading...\n",[]), - ?line {module,Module} = code:load_abs(filename:join(Out, Module)), + io:format("Loading...\n",[]), + {module,Module} = code:load_abs(filename:join(Out, Module)), - ?line io:format("Calling...\n",[]), + io:format("Calling...\n",[]), %% Call M:M, and expect ok back, that's our interface - ?line CallRc = Module:Module(), - ?line io:format("Got value: ~p\n",[CallRc]), + CallRc = Module:Module(), + io:format("Got value: ~p\n",[CallRc]), - ?line ok = CallRc, + ok = CallRc, %% Smoke-test of beam disassembler. - ?line test_lib:smoke_disasm(Module), + test_lib:smoke_disasm(Module), _ = code:delete(Module), _ = code:purge(Module), @@ -330,7 +329,7 @@ start_node(Name, Args) -> {ok, Node} -> {ok, Node}; Error -> - ?line test_server:fail(Error) + ct:fail(Error) end. from(H, [H | T]) -> T; @@ -338,84 +337,78 @@ from(H, [_ | T]) -> from(H, T); from(_, []) -> []. -vsn_1(doc) -> - "Test generation of 'vsn' attribute"; -vsn_1(suite) -> []; +%% Test generation of 'vsn' attribute. vsn_1(Conf) when is_list(Conf) -> - ?line M = vsn_1, - - ?line compile_load(M, ?config(data_dir, Conf), Conf), - ?line Vsn1 = get_vsn(M), - ?line timer:sleep(1000), - - ?line compile_load(M, ?config(data_dir, Conf), Conf), - ?line Vsn2 = get_vsn(M), - - ?line compile_load(M, filename:join(?config(data_dir, Conf), "other"), - Conf), - ?line Vsn3 = get_vsn(M), - ?line if - Vsn1 == Vsn2, Vsn2 == Vsn3 -> - ok; - true -> - test_server:fail({vsn, Vsn1, Vsn2, Vsn3}) - end, + M = vsn_1, + + compile_load(M, proplists:get_value(data_dir, Conf), Conf), + Vsn1 = get_vsn(M), + timer:sleep(1000), + + compile_load(M, proplists:get_value(data_dir, Conf), Conf), + Vsn2 = get_vsn(M), + + compile_load(M, filename:join(proplists:get_value(data_dir, Conf), + "other"), + Conf), + Vsn3 = get_vsn(M), + if + Vsn1 == Vsn2, Vsn2 == Vsn3 -> + ok; + true -> + ct:fail({vsn, Vsn1, Vsn2, Vsn3}) + end, ok. -vsn_2(doc) -> - "Test overriding of generation of 'vsn' attribute"; -vsn_2(suite) -> []; +%% Test overriding of generation of 'vsn' attribute. vsn_2(Conf) when is_list(Conf) -> - ?line M = vsn_2, - - ?line compile_load(M, ?config(data_dir, Conf), Conf), - ?line Vsn = get_vsn(M), - ?line case Vsn of - [34] -> - ok; - _ -> - test_server:fail({vsn, Vsn}) - end, + M = vsn_2, + + compile_load(M, proplists:get_value(data_dir, Conf), Conf), + Vsn = get_vsn(M), + case Vsn of + [34] -> + ok; + _ -> + ct:fail({vsn, Vsn}) + end, ok. -vsn_3(doc) -> - "Test that different code yields different generated 'vsn'"; -vsn_3(suite) -> []; +%% Test that different code yields different generated 'vsn'. vsn_3(Conf) when is_list(Conf) -> - ?line M = vsn_3, - - ?line compile_load(M, ?config(data_dir, Conf), Conf), - ?line Vsn1 = get_vsn(M), - - ?line compile_load(M, filename:join(?config(data_dir, Conf), "other"), - Conf), - ?line Vsn2 = get_vsn(M), - ?line if - Vsn1 /= Vsn2 -> - ok; - true -> - test_server:fail({vsn, Vsn1, Vsn2}) - end, + M = vsn_3, + + compile_load(M, proplists:get_value(data_dir, Conf), Conf), + Vsn1 = get_vsn(M), + + compile_load(M, filename:join(proplists:get_value(data_dir, Conf), + "other"), + Conf), + Vsn2 = get_vsn(M), + if + Vsn1 /= Vsn2 -> + ok; + true -> + ct:fail({vsn, Vsn1, Vsn2}) + end, ok. get_vsn(M) -> - {value, {vsn, V}} = lists:keysearch(vsn, 1, M:module_info(attributes)), + {vsn,V} = lists:keyfind(vsn, 1, M:module_info(attributes)), V. long_string(Config) when is_list(Config) -> %% The test must complete in one minute - it should be plenty of time. - ?line Dog = test_server:timetrap(test_server:minutes(1)), - ?line try_it(long_string, Config), - ?line test_server:timetrap_cancel(Dog), + try_it(false, long_string, {minutes,1}, Config), ok. compile_load(Module, Dir, Conf) -> - ?line Src = filename:join(Dir, atom_to_list(Module)), - ?line Out = ?config(priv_dir,Conf), - ?line CompRc = compile:file(Src, [{outdir,Out}]), - ?line {ok, Module} = CompRc, - ?line code:purge(Module), - ?line {module, Module} = + Src = filename:join(Dir, atom_to_list(Module)), + Out = proplists:get_value(priv_dir,Conf), + CompRc = compile:file(Src, [{outdir,Out}]), + {ok, Module} = CompRc, + code:purge(Module), + {module, Module} = code:load_abs(filename:join(Out, atom_to_list(Module))), ok. @@ -428,9 +421,9 @@ self_compile_old_inliner(Config) when is_list(Config) -> self_compile_1(Config, "old", [verbose,{inline,500}]). self_compile_1(Config, Prefix, Opts) -> - Dog = test_server:timetrap(test_server:minutes(40)), + ct:timetrap({minutes,40}), - Priv = ?config(priv_dir,Config), + Priv = proplists:get_value(priv_dir,Config), Version = compiler_version(), %% Compile the compiler. (In this node to get better coverage.) @@ -449,11 +442,10 @@ self_compile_1(Config, Prefix, Opts) -> %% be equal (except for beam_asm that contains the compiler version). compare_compilers(CompA, CompB), - test_server:timetrap_cancel(Dog), ok. self_compile_node(CompilerDir, OutDir, Version, Opts) -> - Dog = test_server:timetrap(test_server:minutes(15)), + ct:timetrap({minutes,15}), Pa = "-pa " ++ filename:dirname(code:which(?MODULE)) ++ " -pa " ++ CompilerDir, Files = compiler_src(), @@ -462,11 +454,11 @@ self_compile_node(CompilerDir, OutDir, Version, Opts) -> %% because it will load the same cover-compiled code as on this %% node. Use a shielded node to prevent the cover server from %% being started. - ?t:run_on_shielded_node( - fun() -> - compile_compiler(Files, OutDir, Version, Opts) - end, Pa), - test_server:timetrap_cancel(Dog), + test_server:run_on_shielded_node( + fun() -> + compile_compiler(Files, OutDir, Version, Opts) + end, Pa), + ok. compile_compiler(Files, OutDir, Version, InlineOpts) -> @@ -619,11 +611,11 @@ otp_7345(ObjRef, _RdEnv, Args) -> %% Check the generation of the string table. string_table(Config) when is_list(Config) -> - ?line DataDir = ?config(data_dir, Config), - ?line File = filename:join(DataDir, "string_table.erl"), - ?line {ok,string_table,Beam,[]} = compile:file(File, [return, binary]), - ?line {ok,{string_table,[StringTableChunk]}} = beam_lib:chunks(Beam, ["StrT"]), - ?line {"StrT", <<"stringtable">>} = StringTableChunk, + DataDir = proplists:get_value(data_dir, Config), + File = filename:join(DataDir, "string_table.erl"), + {ok,string_table,Beam,[]} = compile:file(File, [return, binary]), + {ok,{string_table,[StringTableChunk]}} = beam_lib:chunks(Beam, ["StrT"]), + {"StrT", <<"stringtable">>} = StringTableChunk, ok. otp_8949_a(Config) when is_list(Config) -> @@ -650,8 +642,8 @@ do_otp_8949_a() -> otp_8949_b(Config) when is_list(Config) -> self() ! something, - ?line value = otp_8949_b([], false), - ?line {'EXIT',_} = (catch otp_8949_b([], true)), + value = otp_8949_b([], false), + {'EXIT',_} = (catch otp_8949_b([], true)), ok. %% Would cause an endless loop in beam_utils. diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl index c69e0ac408..b2e9558cba 100644 --- a/lib/compiler/test/compile_SUITE.erl +++ b/lib/compiler/test/compile_SUITE.erl @@ -71,58 +71,55 @@ end_per_group(_GroupName, Config) -> %% Test that the Application file has no `basic' errors."; app_test(Config) when is_list(Config) -> - ?line ?t:app_test(compiler). + test_server:app_test(compiler). %% Test that the Application upgrade file has no `basic' errors."; appup_test(Config) when is_list(Config) -> - ok = ?t:appup_test(compiler). + ok = test_server:appup_test(compiler). %% Tests that we can compile and run a simple Erlang program, %% using compile:file/1. file_1(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:minutes(5)), - process_flag(trap_exit, true), {Simple, Target} = get_files(Config, simple, "file_1"), - ?line {ok, Cwd} = file:get_cwd(), - ?line ok = file:set_cwd(filename:dirname(Target)), + {ok, Cwd} = file:get_cwd(), + ok = file:set_cwd(filename:dirname(Target)), %% Native from BEAM without compilation info. - ?line {ok,simple} = compile:file(Simple, [slim]), %Smoke test only. - ?line {ok,simple} = compile:file(Target, [native,from_beam]), %Smoke test. + {ok,simple} = compile:file(Simple, [slim]), %Smoke test only. + {ok,simple} = compile:file(Target, [native,from_beam]), %Smoke test. %% Native from BEAM with compilation info. - ?line {ok,simple} = compile:file(Simple), %Smoke test only. - ?line {ok,simple} = compile:file(Target, [native,from_beam]), %Smoke test. + {ok,simple} = compile:file(Simple), %Smoke test only. + {ok,simple} = compile:file(Target, [native,from_beam]), %Smoke test. - ?line {ok,simple} = compile:file(Simple, [native,report]), %Smoke test. + {ok,simple} = compile:file(Simple, [native,report]), %Smoke test. - ?line compile_and_verify(Simple, Target, []), - ?line compile_and_verify(Simple, Target, [native]), - ?line compile_and_verify(Simple, Target, [debug_info]), - ?line {ok,simple} = compile:file(Simple, [no_line_info]), %Coverage + compile_and_verify(Simple, Target, []), + compile_and_verify(Simple, Target, [native]), + compile_and_verify(Simple, Target, [debug_info]), + {ok,simple} = compile:file(Simple, [no_line_info]), %Coverage {ok,simple} = compile:file(Simple, [{eprof,beam_z}]), %Coverage - ?line ok = file:set_cwd(Cwd), - ?line true = exists(Target), - ?line passed = run(Target, test, []), + ok = file:set_cwd(Cwd), + true = exists(Target), + passed = run(Target, test, []), %% Cleanup. - ?line ok = file:delete(Target), - ?line ok = file:del_dir(filename:dirname(Target)), + ok = file:delete(Target), + ok = file:del_dir(filename:dirname(Target)), %% There should not be any messages in the messages. receive Any -> - ?t:fail({unexpected,Any}) + ct:fail({unexpected,Any}) after 10 -> ok end, - ?line test_server:timetrap_cancel(Dog), ok. forms_2(Config) when is_list(Config) -> @@ -146,118 +143,110 @@ forms_2(Config) when is_list(Config) -> ok. module_mismatch(Config) when is_list(Config) -> - ?line DataDir = ?config(data_dir, Config), - ?line File = filename:join(DataDir, "wrong_module_name.erl"), + DataDir = proplists:get_value(data_dir, Config), + File = filename:join(DataDir, "wrong_module_name.erl"), {error,[{"wrong_module_name.beam", [{none,compile,{module_name,arne,"wrong_module_name"}}]}], []} = compile:file(File, [return]), - ?line error = compile:file(File, [report]), + error = compile:file(File, [report]), - ?line {ok,arne,[]} = compile:file(File, + {ok,arne,[]} = compile:file(File, [return,no_error_module_mismatch]), ok. big_file(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:minutes(5)), {Big,Target} = get_files(Config, big, "big_file"), ok = file:set_cwd(filename:dirname(Target)), - ?line compile_and_verify(Big, Target, []), - ?line compile_and_verify(Big, Target, [debug_info]), - ?line compile_and_verify(Big, Target, [no_postopt]), + compile_and_verify(Big, Target, []), + compile_and_verify(Big, Target, [debug_info]), + compile_and_verify(Big, Target, [no_postopt]), %% Cleanup. - ?line ok = file:delete(Target), - ?line test_server:timetrap_cancel(Dog), + ok = file:delete(Target), ok. %% Tests that the {outdir, Dir} option works. outdir(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(60)), {Simple, Target} = get_files(Config, simple, "outdir"), - ?line {ok, simple} = compile:file(Simple, [{outdir, filename:dirname(Target)}]), - ?line true = exists(Target), - ?line passed = run(Target, test, []), - ?line ok = file:delete(Target), - ?line ok = file:del_dir(filename:dirname(Target)), - ?line test_server:timetrap_cancel(Dog), + {ok, simple} = compile:file(Simple, [{outdir, filename:dirname(Target)}]), + true = exists(Target), + passed = run(Target, test, []), + ok = file:delete(Target), + ok = file:del_dir(filename:dirname(Target)), ok. %% Tests that the binary option works. binary(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(60)), {Simple, Target} = get_files(Config, simple, "binary"), - ?line {ok, simple, Binary} = compile:file(Simple, [binary]), - ?line code:load_binary(simple, Target, Binary), - ?line passed = simple:test(), - ?line true = code:delete(simple), - ?line false = code:purge(simple), - ?line ok = file:del_dir(filename:dirname(Target)), - ?line test_server:timetrap_cancel(Dog), + {ok, simple, Binary} = compile:file(Simple, [binary]), + code:load_binary(simple, Target, Binary), + passed = simple:test(), + true = code:delete(simple), + false = code:purge(simple), + ok = file:del_dir(filename:dirname(Target)), ok. %% Tests that the dependencies-Makefile-related options work. makedep(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(60)), {Simple,Target} = get_files(Config, simple, "makedep"), - ?line DataDir = ?config(data_dir, Config), - ?line SimpleRootname = filename:rootname(Simple), - ?line IncludeDir = filename:join(filename:dirname(Simple), "include"), - ?line IncludeOptions = [ - {d,need_foo}, - {d,foo_value,42}, - {d,include_generated}, - {i,IncludeDir} - ], + DataDir = proplists:get_value(data_dir, Config), + SimpleRootname = filename:rootname(Simple), + IncludeDir = filename:join(filename:dirname(Simple), "include"), + IncludeOptions = [ + {d,need_foo}, + {d,foo_value,42}, + {d,include_generated}, + {i,IncludeDir} + ], %% Basic rule. - ?line BasicMf1Name = SimpleRootname ++ "-basic1.mk", - ?line {ok,BasicMf1} = file:read_file(BasicMf1Name), - ?line {ok,_,Mf1} = compile:file(Simple, [binary,makedep]), - ?line BasicMf1 = makedep_canonicalize_result(Mf1, DataDir), + BasicMf1Name = SimpleRootname ++ "-basic1.mk", + {ok,BasicMf1} = file:read_file(BasicMf1Name), + {ok,_,Mf1} = compile:file(Simple, [binary,makedep]), + BasicMf1 = makedep_canonicalize_result(Mf1, DataDir), %% Basic rule with one existing header. - ?line BasicMf2Name = SimpleRootname ++ "-basic2.mk", - ?line {ok,BasicMf2} = file:read_file(BasicMf2Name), - ?line {ok,_,Mf2} = compile:file(Simple, [binary,makedep|IncludeOptions]), - ?line BasicMf2 = makedep_canonicalize_result(Mf2, DataDir), + BasicMf2Name = SimpleRootname ++ "-basic2.mk", + {ok,BasicMf2} = file:read_file(BasicMf2Name), + {ok,_,Mf2} = compile:file(Simple, [binary,makedep|IncludeOptions]), + BasicMf2 = makedep_canonicalize_result(Mf2, DataDir), %% Rule with one existing header and one missing header. - ?line MissingMfName = SimpleRootname ++ "-missing.mk", - ?line {ok,MissingMf} = file:read_file(MissingMfName), - ?line {ok,_,Mf3} = compile:file(Simple, + MissingMfName = SimpleRootname ++ "-missing.mk", + {ok,MissingMf} = file:read_file(MissingMfName), + {ok,_,Mf3} = compile:file(Simple, [binary,makedep,makedep_add_missing|IncludeOptions]), - ?line MissingMf = makedep_canonicalize_result(Mf3, DataDir), + MissingMf = makedep_canonicalize_result(Mf3, DataDir), %% Rule with modified target. - ?line TargetMf1Name = SimpleRootname ++ "-target1.mk", - ?line {ok,TargetMf1} = file:read_file(TargetMf1Name), - ?line {ok,_,Mf4} = compile:file(Simple, + TargetMf1Name = SimpleRootname ++ "-target1.mk", + {ok,TargetMf1} = file:read_file(TargetMf1Name), + {ok,_,Mf4} = compile:file(Simple, [binary,makedep,{makedep_target,"$target"}|IncludeOptions]), - ?line TargetMf1 = makedep_modify_target( + TargetMf1 = makedep_modify_target( makedep_canonicalize_result(Mf4, DataDir), "$$target"), %% Rule with quoted modified target. - ?line TargetMf2Name = SimpleRootname ++ "-target2.mk", - ?line {ok,TargetMf2} = file:read_file(TargetMf2Name), - ?line {ok,_,Mf5} = compile:file(Simple, + TargetMf2Name = SimpleRootname ++ "-target2.mk", + {ok,TargetMf2} = file:read_file(TargetMf2Name), + {ok,_,Mf5} = compile:file(Simple, [binary,makedep,{makedep_target,"$target"},makedep_quote_target| IncludeOptions]), - ?line TargetMf2 = makedep_modify_target( + TargetMf2 = makedep_modify_target( makedep_canonicalize_result(Mf5, DataDir), "$$target"), %% Basic rule written to some file. - ?line {ok,_} = compile:file(Simple, + {ok,_} = compile:file(Simple, [makedep,{makedep_output,Target}|IncludeOptions]), - ?line {ok,Mf6} = file:read_file(Target), - ?line BasicMf2 = makedep_canonicalize_result(Mf6, DataDir), + {ok,Mf6} = file:read_file(Target), + BasicMf2 = makedep_canonicalize_result(Mf6, DataDir), %% Rule with creating phony target. - ?line PhonyMfName = SimpleRootname ++ "-phony.mk", - ?line {ok,PhonyMf} = file:read_file(PhonyMfName), - ?line {ok,_,Mf7} = compile:file(Simple, + PhonyMfName = SimpleRootname ++ "-phony.mk", + {ok,PhonyMf} = file:read_file(PhonyMfName), + {ok,_,Mf7} = compile:file(Simple, [binary,makedep,makedep_phony|IncludeOptions]), - ?line PhonyMf = makedep_canonicalize_result(Mf7, DataDir), + PhonyMf = makedep_canonicalize_result(Mf7, DataDir), - ?line ok = file:delete(Target), - ?line ok = file:del_dir(filename:dirname(Target)), - ?line test_server:timetrap_cancel(Dog), + ok = file:delete(Target), + ok = file:del_dir(filename:dirname(Target)), ok. makedep_canonicalize_result(Mf, DataDir) -> @@ -277,30 +266,26 @@ makedep_modify_target(Mf, Target) -> %% Tests that conditional compilation, defining values, including files work. cond_and_ifdef(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(60)), {Simple, Target} = get_files(Config, simple, "cond_and_ifdef"), - ?line IncludeDir = filename:join(filename:dirname(Simple), "include"), - ?line Options = [{outdir, filename:dirname(Target)}, + IncludeDir = filename:join(filename:dirname(Simple), "include"), + Options = [{outdir, filename:dirname(Target)}, {d, need_foo}, {d, foo_value, 42}, {i, IncludeDir}, report], - ?line {ok, simple} = compile:file(Simple, Options), - ?line true = exists(Target), - ?line {hiker, 42} = run(Target, foo, []), - ?line ok = file:delete(Target), - ?line ok = file:del_dir(filename:dirname(Target)), - ?line test_server:timetrap_cancel(Dog), + {ok, simple} = compile:file(Simple, Options), + true = exists(Target), + {hiker, 42} = run(Target, foo, []), + ok = file:delete(Target), + ok = file:del_dir(filename:dirname(Target)), ok. listings(Config) when is_list(Config) -> - Dog = test_server:timetrap(test_server:minutes(8)), - DataDir = ?config(data_dir, Config), - PrivDir = ?config(priv_dir, Config), + DataDir = proplists:get_value(data_dir, Config), + PrivDir = proplists:get_value(priv_dir, Config), ok = do_file_listings(DataDir, PrivDir, [ "simple", "small", "small_maps" ]), - test_server:timetrap_cancel(Dog), ok. do_file_listings(_, _, []) -> ok; @@ -357,152 +342,146 @@ do_file_listings(DataDir, PrivDir, [File|Files]) -> do_file_listings(DataDir,PrivDir,Files). listings_big(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:minutes(10)), {Big,Target} = get_files(Config, big, listings_big), TargetDir = filename:dirname(Target), - ?line do_listing(Big, TargetDir, 'S'), - ?line do_listing(Big, TargetDir, 'E'), - ?line do_listing(Big, TargetDir, 'P'), - ?line do_listing(Big, TargetDir, dkern, ".kernel"), + do_listing(Big, TargetDir, 'S'), + do_listing(Big, TargetDir, 'E'), + do_listing(Big, TargetDir, 'P'), + do_listing(Big, TargetDir, dkern, ".kernel"), TargetNoext = filename:rootname(Target, code:objfile_extension()), {ok,big} = compile:file(TargetNoext, [from_asm,{outdir,TargetDir}]), %% Cleanup. ok = file:delete(Target), - ?line lists:foreach(fun(F) -> ok = file:delete(F) end, - filelib:wildcard(filename:join(TargetDir, "*"))), - ?line ok = file:del_dir(TargetDir), - ?line test_server:timetrap_cancel(Dog), + lists:foreach(fun(F) -> ok = file:delete(F) end, + filelib:wildcard(filename:join(TargetDir, "*"))), + ok = file:del_dir(TargetDir), ok. other_output(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:minutes(8)), {Simple,_Target} = get_files(Config, simple, "other_output"), io:put_chars("to_pp"), - ?line {ok,[],PP} = compile:file(Simple, [to_pp,binary,time]), - ?line [] = [E || E <- PP, - begin - case element(1, E) of - attribute -> false; - function -> false; - eof -> false - end - end], + {ok,[],PP} = compile:file(Simple, [to_pp,binary,time]), + [] = [E || E <- PP, + begin + case element(1, E) of + attribute -> false; + function -> false; + eof -> false + end + end], io:put_chars("to_exp (file)"), - ?line {ok,simple,Expand} = compile:file(Simple, [to_exp,binary,time]), - ?line case Expand of - {simple,Exports,Forms} when is_list(Exports), is_list(Forms) -> ok - end, + {ok,simple,Expand} = compile:file(Simple, [to_exp,binary,time]), + case Expand of + {simple,Exports,Forms} when is_list(Exports), is_list(Forms) -> ok + end, io:put_chars("to_exp (forms)"), - ?line {ok,simple,Expand} = compile:forms(PP, [to_exp,binary,time]), + {ok,simple,Expand} = compile:forms(PP, [to_exp,binary,time]), io:put_chars("to_core (file)"), - ?line {ok,simple,Core} = compile:file(Simple, [to_core,binary,time]), - ?line c_module = element(1, Core), - ?line {ok,_} = core_lint:module(Core), + {ok,simple,Core} = compile:file(Simple, [to_core,binary,time]), + c_module = element(1, Core), + {ok,_} = core_lint:module(Core), io:put_chars("to_core (forms)"), - ?line {ok,simple,Core} = compile:forms(PP, [to_core,binary,time]), + {ok,simple,Core} = compile:forms(PP, [to_core,binary,time]), io:put_chars("to_kernel (file)"), - ?line {ok,simple,Kernel} = compile:file(Simple, [to_kernel,binary,time]), - ?line k_mdef = element(1, Kernel), + {ok,simple,Kernel} = compile:file(Simple, [to_kernel,binary,time]), + k_mdef = element(1, Kernel), io:put_chars("to_kernel (forms)"), - ?line {ok,simple,Kernel} = compile:forms(PP, [to_kernel,binary,time]), + {ok,simple,Kernel} = compile:forms(PP, [to_kernel,binary,time]), io:put_chars("to_asm (file)"), - ?line {ok,simple,Asm} = compile:file(Simple, [to_asm,binary,time]), - ?line {simple,_,_,_,_} = Asm, + {ok,simple,Asm} = compile:file(Simple, [to_asm,binary,time]), + {simple,_,_,_,_} = Asm, io:put_chars("to_asm (forms)"), - ?line {ok,simple,Asm} = compile:forms(PP, [to_asm,binary,time]), + {ok,simple,Asm} = compile:forms(PP, [to_asm,binary,time]), - ?line test_server:timetrap_cancel(Dog), ok. encrypted_abstr(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:minutes(10)), {Simple,Target} = get_files(Config, simple, "encrypted_abstr"), Res = case has_crypto() of false -> %% No crypto. - ?line encrypted_abstr_no_crypto(Simple, Target), + encrypted_abstr_no_crypto(Simple, Target), {comment,"The crypto application is missing or broken"}; true -> %% Simulate not having crypto by removing %% the crypto application from the path. - ?line OldPath = code:get_path(), + OldPath = code:get_path(), try - ?line NewPath = OldPath -- [filename:dirname(code:which(crypto))], - ?line (catch crypto:stop()), - ?line code:delete(crypto), - ?line code:purge(crypto), - ?line code:set_path(NewPath), - ?line encrypted_abstr_no_crypto(Simple, Target) + NewPath = OldPath -- [filename:dirname(code:which(crypto))], + (catch crypto:stop()), + code:delete(crypto), + code:purge(crypto), + code:set_path(NewPath), + encrypted_abstr_no_crypto(Simple, Target) after code:set_path(OldPath) end, %% Now run the tests that require crypto. - ?line encrypted_abstr_1(Simple, Target), - ?line ok = file:delete(Target), - ?line ok = file:del_dir(filename:dirname(Target)) + encrypted_abstr_1(Simple, Target), + ok = file:delete(Target), + ok = file:del_dir(filename:dirname(Target)) end, %% Cleanup. - ?line test_server:timetrap_cancel(Dog), Res. encrypted_abstr_1(Simple, Target) -> - ?line TargetDir = filename:dirname(Target), - ?line Key = "ablurf123BX#$;3", - ?line install_crypto_key(Key), - ?line {ok,simple} = compile:file(Simple, + TargetDir = filename:dirname(Target), + Key = "ablurf123BX#$;3", + install_crypto_key(Key), + {ok,simple} = compile:file(Simple, [debug_info,{debug_info_key,Key}, {outdir,TargetDir}]), - ?line verify_abstract(Target), + verify_abstract(Target), - ?line {ok,simple} = compile:file(Simple, + {ok,simple} = compile:file(Simple, [{debug_info_key,Key}, {outdir,TargetDir}]), - ?line verify_abstract(Target), + verify_abstract(Target), - ?line {ok,simple} = compile:file(Simple, + {ok,simple} = compile:file(Simple, [debug_info,{debug_info_key,{des3_cbc,Key}}, {outdir,TargetDir}]), - ?line verify_abstract(Target), + verify_abstract(Target), - ?line {ok,{simple,[{compile_info,CInfo}]}} = + {ok,{simple,[{compile_info,CInfo}]}} = beam_lib:chunks(Target, [compile_info]), - ?line {value,{_,Opts}} = lists:keysearch(options, 1, CInfo), - ?line {value,{_,'********'}} = lists:keysearch(debug_info_key, 1, Opts), + {_,Opts} = lists:keyfind(options, 1, CInfo), + {_,'********'} = lists:keyfind(debug_info_key, 1, Opts), %% Try some illegal forms of crypto keys. - ?line error = compile:file(Simple, + error = compile:file(Simple, [debug_info,{debug_info_key,{blurf,"ss"}},report]), - ?line error = compile:file(Simple, + error = compile:file(Simple, [debug_info,{debug_info_key,{blurf,1,"ss"}},report]), - ?line error = compile:file(Simple, + error = compile:file(Simple, [debug_info,{debug_info_key,42},report]), %% Place the crypto key in .erlang.crypt. - ?line beam_lib:clear_crypto_key_fun(), - ?line {ok,OldCwd} = file:get_cwd(), - ?line ok = file:set_cwd(TargetDir), - - ?line error = compile:file(Simple, [encrypt_debug_info,report]), - - ?line NewKey = "better use another key here", - ?line write_crypt_file(["[{debug_info,des3_cbc,simple,\"",NewKey,"\"}].\n"]), - ?line {ok,simple} = compile:file(Simple, [encrypt_debug_info,report]), - ?line verify_abstract("simple.beam"), - ?line ok = file:delete(".erlang.crypt"), - ?line beam_lib:clear_crypto_key_fun(), - ?line {error,beam_lib,{key_missing_or_invalid,"simple.beam",abstract_code}} = + beam_lib:clear_crypto_key_fun(), + {ok,OldCwd} = file:get_cwd(), + ok = file:set_cwd(TargetDir), + + error = compile:file(Simple, [encrypt_debug_info,report]), + + NewKey = "better use another key here", + write_crypt_file(["[{debug_info,des3_cbc,simple,\"",NewKey,"\"}].\n"]), + {ok,simple} = compile:file(Simple, [encrypt_debug_info,report]), + verify_abstract("simple.beam"), + ok = file:delete(".erlang.crypt"), + beam_lib:clear_crypto_key_fun(), + {error,beam_lib,{key_missing_or_invalid,"simple.beam",abstract_code}} = beam_lib:chunks("simple.beam", [abstract_code]), - ?line ok = file:set_cwd(OldCwd), + ok = file:set_cwd(OldCwd), %% Test key compatibility by reading a BEAM file produced before %% the update to the new crypto functions. @@ -523,9 +502,9 @@ write_crypt_file(Contents0) -> encrypted_abstr_no_crypto(Simple, Target) -> io:format("simpe: ~p~n", [Simple]), - ?line TargetDir = filename:dirname(Target), - ?line Key = "ablurf123BX#$;3", - ?line error = compile:file(Simple, + TargetDir = filename:dirname(Target), + Key = "ablurf123BX#$;3", + error = compile:file(Simple, [debug_info,{debug_info_key,Key}, {outdir,TargetDir},report]), ok. @@ -553,7 +532,7 @@ install_crypto_key(Key) -> %% Miscellanous tests, mainly to get better coverage. cover(Config) when is_list(Config) -> - ?line io:format("~p\n", [compile:options()]), + io:format("~p\n", [compile:options()]), ok. do_listing(Source, TargetDir, Type) -> @@ -564,7 +543,7 @@ do_listing(Source, TargetDir, Type, Ext) -> [Source, TargetDir, Type, Ext]), case compile:file(Source, [Type, time, {outdir, TargetDir}]) of {ok, _} -> ok; - Other -> test_server:fail({unexpected_result, Other}) + Other -> ct:fail({unexpected_result, Other}) end, SourceBase = filename:rootname(filename:basename(Source)), @@ -574,8 +553,8 @@ do_listing(Source, TargetDir, Type, Ext) -> get_files(Config, Module, OutputName) -> code:delete(Module), code:purge(Module), - DataDir = ?config(data_dir, Config), - PrivDir = ?config(priv_dir, Config), + DataDir = proplists:get_value(data_dir, Config), + PrivDir = proplists:get_value(priv_dir, Config), Src = filename:join(DataDir, atom_to_list(Module)), TargetDir = filename:join(PrivDir, OutputName), ok = file:make_dir(TargetDir), @@ -584,11 +563,11 @@ get_files(Config, Module, OutputName) -> {Src, Target}. run(Target, Func, Args) -> - ?line Module = list_to_atom(filename:rootname(filename:basename(Target))), - ?line {module, Module} = code:load_abs(filename:rootname(Target)), - ?line Result = (catch apply(Module, Func, Args)), - ?line true = code:delete(Module), - ?line false = code:purge(Module), + Module = list_to_atom(filename:rootname(filename:basename(Target))), + {module, Module} = code:load_abs(filename:rootname(Target)), + Result = (catch apply(Module, Func, Args)), + true = code:delete(Module), + false = code:purge(Module), Result. exists(Name) -> @@ -599,26 +578,26 @@ exists(Name) -> strict_record(Config) when is_list(Config) -> - ?line Priv = ?config(priv_dir, Config), - ?line file:set_cwd(?config(data_dir, Config)), - ?line Opts = [{outdir,Priv},report_errors], + Priv = proplists:get_value(priv_dir, Config), + ok = file:set_cwd(proplists:get_value(data_dir, Config)), + Opts = [{outdir,Priv},report_errors], M = record_access, - ?line {ok,M} = c:c(M, [strict_record_tests|Opts]), - ?line Turtle = test_strict(), + {ok,M} = c:c(M, [strict_record_tests|Opts]), + Turtle = test_strict(), - ?line {ok,M} = c:c(M, [no_strict_record_tests|Opts]), - ?line Turtle = test_sloppy(), + {ok,M} = c:c(M, [no_strict_record_tests|Opts]), + Turtle = test_sloppy(), %% The option first given wins. - ?line {ok,M} = c:c(M, [no_strict_record_tests,strict_record_tests|Opts]), - ?line Turtle = test_sloppy(), - ?line {ok,M} = c:c(M, [strict_record_tests,no_strict_record_tests|Opts]), - ?line Turtle = test_strict(), + {ok,M} = c:c(M, [no_strict_record_tests,strict_record_tests|Opts]), + Turtle = test_sloppy(), + {ok,M} = c:c(M, [strict_record_tests,no_strict_record_tests|Opts]), + Turtle = test_strict(), %% Default (possibly influenced by ERL_COMPILER_OPTIONS). - ?line {ok,M} = c:c(M, [{outdir,Priv},report_errors]), - ?line try + {ok,M} = c:c(M, [{outdir,Priv},report_errors]), + try {1,2} = record_access:test(Turtle), {comment,"Default: no_strict_record_tests"} catch @@ -628,7 +607,7 @@ strict_record(Config) when is_list(Config) -> test_strict() -> Turtle = record_access:turtle(), - ?line try + try record_access:test(Turtle) catch error:{badrecord,tortoise} -> @@ -642,19 +621,19 @@ test_sloppy() -> Turtle. missing_testheap(Config) when is_list(Config) -> - DataDir = ?config(data_dir, Config), - PrivDir = ?config(priv_dir, Config), + DataDir = proplists:get_value(data_dir, Config), + PrivDir = proplists:get_value(priv_dir, Config), Opts = [{outdir,PrivDir}], OldPath = code:get_path(), try code:add_patha(PrivDir), c:c(filename:join(DataDir, "missing_testheap1"), Opts), c:c(filename:join(DataDir, "missing_testheap2"), Opts), - ?line ok = test(fun() -> - missing_testheap1:f({a,self()},{state,true,b}) - end, {a,b}), - ?line ok = test(fun() -> - missing_testheap2:f({a,self()},16#80000000) end, + ok = test(fun() -> + missing_testheap1:f({a,self()},{state,true,b}) + end, {a,b}), + ok = test(fun() -> + missing_testheap2:f({a,self()},16#80000000) end, bigger) after code:set_path(OldPath), @@ -675,7 +654,7 @@ test(Iter, Fun, Result, Filler) -> test(Iter-1, Fun, Result, [0|Filler]); {result, Other} -> io:format("Expected ~p; got ~p~n", [Result, Other]), - test_server:fail() + ct:fail(failed) end. init(ReplyTo, Fun, _Filler) -> @@ -683,8 +662,8 @@ init(ReplyTo, Fun, _Filler) -> env(Config) when is_list(Config) -> {Simple,Target} = get_files(Config, simple, env), - ?line {ok,Cwd} = file:get_cwd(), - ?line ok = file:set_cwd(filename:dirname(Target)), + {ok,Cwd} = file:get_cwd(), + ok = file:set_cwd(filename:dirname(Target)), true = os:putenv("ERL_COMPILER_OPTIONS", "binary"), try @@ -699,23 +678,23 @@ env(Config) when is_list(Config) -> env_1(Simple, Target) -> %% file - ?line {ok,simple,<<_/binary>>} = compile:file(Simple), - ?line {ok,simple} = compile:noenv_file(Simple, [debug_info]), - ?line true = exists(Target), - ?line {ok,{simple,[{abstract_code,Abstr0}]}} = + {ok,simple,<<_/binary>>} = compile:file(Simple), + {ok,simple} = compile:noenv_file(Simple, [debug_info]), + true = exists(Target), + {ok,{simple,[{abstract_code,Abstr0}]}} = beam_lib:chunks(Target, [abstract_code]), - ?line {raw_abstract_v1,Forms} = Abstr0, + {raw_abstract_v1,Forms} = Abstr0, %% forms - ?line true = os:putenv("ERL_COMPILER_OPTIONS", "strong_validation"), - ?line {ok,simple} = compile:forms(Forms), - ?line {ok,simple,<<"FOR1",_/binary>>} = compile:noenv_forms(Forms, []), + true = os:putenv("ERL_COMPILER_OPTIONS", "strong_validation"), + {ok,simple} = compile:forms(Forms), + {ok,simple,<<"FOR1",_/binary>>} = compile:noenv_forms(Forms, []), %% output_generated - ?line false = compile:output_generated([]), - ?line true = compile:noenv_output_generated([]), + false = compile:output_generated([]), + true = compile:noenv_output_generated([]), - ?line ok = file:delete(Target), + ok = file:delete(Target), ok. @@ -723,7 +702,7 @@ env_1(Simple, Target) -> %% compile the generated Core Erlang files. core(Config) when is_list(Config) -> - PrivDir = ?config(priv_dir, Config), + PrivDir = proplists:get_value(priv_dir, Config), Outdir = filename:join(PrivDir, "core"), ok = file:make_dir(Outdir), @@ -786,15 +765,13 @@ compile_forms(Forms, Opts) -> %% run .S through the compiler again. asm(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:minutes(20)), - ?line PrivDir = ?config(priv_dir, Config), - ?line Outdir = filename:join(PrivDir, "asm"), - ?line ok = file:make_dir(Outdir), - - ?line Wc = filename:join(filename:dirname(code:which(?MODULE)), "*.beam"), - ?line TestBeams = filelib:wildcard(Wc), - ?line Res = test_lib:p_run(fun(F) -> do_asm(F, Outdir) end, TestBeams), - ?line test_server:timetrap_cancel(Dog), + PrivDir = proplists:get_value(priv_dir, Config), + Outdir = filename:join(PrivDir, "asm"), + ok = file:make_dir(Outdir), + + Wc = filename:join(filename:dirname(code:which(?MODULE)), "*.beam"), + TestBeams = filelib:wildcard(Wc), + Res = test_lib:p_run(fun(F) -> do_asm(F, Outdir) end, TestBeams), Res. @@ -822,7 +799,7 @@ do_asm(Beam, Outdir) -> end. sys_pre_attributes(Config) -> - DataDir = ?config(data_dir, Config), + DataDir = proplists:get_value(data_dir, Config), File = filename:join(DataDir, "attributes.erl"), Mod = attributes, CommonOpts = [binary,report,verbose, @@ -854,8 +831,8 @@ sys_pre_attributes(Config) -> %% Test the dialyzer option to cover more code. dialyzer(Config) -> - Priv = ?config(priv_dir, Config), - file:set_cwd(?config(data_dir, Config)), + Priv = proplists:get_value(priv_dir, Config), + ok = file:set_cwd(proplists:get_value(data_dir, Config)), Opts = [{outdir,Priv},report_errors], M = dialyzer_test, {ok,M} = c:c(M, [dialyzer|Opts]), diff --git a/lib/compiler/test/core_SUITE.erl b/lib/compiler/test/core_SUITE.erl index ddc4c7af5e..22f6443a77 100644 --- a/lib/compiler/test/core_SUITE.erl +++ b/lib/compiler/test/core_SUITE.erl @@ -35,15 +35,14 @@ N(Config) when is_list(Config) -> try_it(N, Config)). init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) -> - Dog = test_server:timetrap(?t:minutes(5)), - [{watchdog,Dog}|Config]. + Config. end_per_testcase(Case, Config) when is_atom(Case), is_list(Config) -> - Dog = ?config(watchdog, Config), - ?t:timetrap_cancel(Dog), ok. -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,5}}]. all() -> test_lib:recompile(?MODULE), @@ -86,7 +85,8 @@ end_per_group(_GroupName, Config) -> try_it(Mod, Conf) -> - Src = filename:join(?config(data_dir, Conf), atom_to_list(Mod)), + Src = filename:join(proplists:get_value(data_dir, Conf), + atom_to_list(Mod)), compile_and_load(Src, []), compile_and_load(Src, [no_copt]). diff --git a/lib/compiler/test/core_fold_SUITE.erl b/lib/compiler/test/core_fold_SUITE.erl index 36faea1363..ee2a2c523f 100644 --- a/lib/compiler/test/core_fold_SUITE.erl +++ b/lib/compiler/test/core_fold_SUITE.erl @@ -61,8 +61,8 @@ end_per_group(_GroupName, Config) -> t_element(Config) when is_list(Config) -> X = make_ref(), - ?line X = id(element(1, {X,y,z})), - ?line b = id(element(2, {a,b,c,d})), + X = id(element(1, {X,y,z})), + b = id(element(2, {a,b,c,d})), (fun() -> case {a,#{k=>X}} of {a,#{k:=X}}=Tuple -> @@ -73,21 +73,21 @@ t_element(Config) when is_list(Config) -> %% No optimization, but should work. Tuple = id({x,y,z}), Pos = id(3), - ?line x = id(element(1, Tuple)), - ?line c = id(element(Pos, {a,b,c,d})), - ?line X = id(element(Pos, {a,b,X,d})), - ?line z = id(element(Pos, Tuple)), + x = id(element(1, Tuple)), + c = id(element(Pos, {a,b,c,d})), + X = id(element(Pos, {a,b,X,d})), + z = id(element(Pos, Tuple)), %% Calls that will fail. - ?line {'EXIT',{badarg,_}} = (catch element(5, {a,b,c,d})), - ?line {'EXIT',{badarg,_}} = (catch element(5, {a,b,X,d})), - ?line {'EXIT',{badarg,_}} = (catch element(5.0, {a,b,X,d})), + {'EXIT',{badarg,_}} = (catch element(5, {a,b,c,d})), + {'EXIT',{badarg,_}} = (catch element(5, {a,b,X,d})), + {'EXIT',{badarg,_}} = (catch element(5.0, {a,b,X,d})), {'EXIT',{badarg,_}} = (catch element(2, not_a_tuple)), {'EXIT',{badarg,_}} = (catch element(2, [])), {'EXIT',{badarg,_}} = (catch element(2, Tuple == 3)), case id({a,b,c}) of {_,_,_}=Tup -> - ?line {'EXIT',{badarg,_}} = (catch element(4, Tup)) + {'EXIT',{badarg,_}} = (catch element(4, Tup)) end, {'EXIT',{badarg,_}} = (catch element(1, tuple_size(Tuple))), @@ -96,16 +96,16 @@ t_element(Config) when is_list(Config) -> setelement(Config) when is_list(Config) -> X = id(b), New = id([1,2,3]), - ?line {y,b,c} = id(setelement(1, {a,b,c}, y)), - ?line {y,b,c} = id(setelement(1, {a,X,c}, y)), - ?line {a,y,c} = id(setelement(2, {a,X,c}, y)), - ?line {a,[1,2,3],c} = id(setelement(2, {a,b,c}, New)), - ?line {a,[1,2,3],c} = id(setelement(2, {a,X,c}, New)), - ?line {a,b,[1,2,3]} = id(setelement(3, {a,b,c}, New)), - ?line {a,b,[1,2,3]} = id(setelement(3, {a,X,c}, New)), + {y,b,c} = id(setelement(1, {a,b,c}, y)), + {y,b,c} = id(setelement(1, {a,X,c}, y)), + {a,y,c} = id(setelement(2, {a,X,c}, y)), + {a,[1,2,3],c} = id(setelement(2, {a,b,c}, New)), + {a,[1,2,3],c} = id(setelement(2, {a,X,c}, New)), + {a,b,[1,2,3]} = id(setelement(3, {a,b,c}, New)), + {a,b,[1,2,3]} = id(setelement(3, {a,X,c}, New)), - ?line {'EXIT',{badarg,_}} = (catch setelement_crash({a,b,c,d,e,f})), - ?line error = setelement_crash_2({a,b,c,d,e,f}, <<42>>), + {'EXIT',{badarg,_}} = (catch setelement_crash({a,b,c,d,e,f})), + error = setelement_crash_2({a,b,c,d,e,f}, <<42>>), {'EXIT',{badarg,_}} = (catch setelement(1, not_a_tuple, New)), {'EXIT',{badarg,_}} = (catch setelement(3, {a,b}, New)), @@ -132,19 +132,19 @@ setelement_crash_2(Tuple, Bin) -> t_length(Config) when is_list(Config) -> Blurf = id({blurf,a,b}), Tail = id([42,43,44,45]), - ?line 0 = id(length([])), - ?line 1 = id(length([x])), - ?line 2 = id(length([x,Blurf])), - ?line 4 = id(length([x,Blurf,a,b])), + 0 = id(length([])), + 1 = id(length([x])), + 2 = id(length([x,Blurf])), + 4 = id(length([x,Blurf,a,b])), %% No or partial optimization. - ?line 4 = length(Tail), - ?line 5 = id(length([x|Tail])), + 4 = length(Tail), + 5 = id(length([x|Tail])), %% Will fail. - ?line {'EXIT',{badarg,_}} = (catch id(length([a,b|c]))), - ?line {'EXIT',{badarg,_}} = (catch id(length([a,Blurf|c]))), - ?line {'EXIT',{badarg,_}} = (catch id(length(atom))), + {'EXIT',{badarg,_}} = (catch id(length([a,b|c]))), + {'EXIT',{badarg,_}} = (catch id(length([a,Blurf|c]))), + {'EXIT',{badarg,_}} = (catch id(length(atom))), ok. @@ -156,34 +156,34 @@ t_length(Config) when is_list(Config) -> append(Config) when is_list(Config) -> A = id(0), - ?line [a,b,c,d,e,f,g,h,i,j,k] = id(?APPEND([a,b,c,d,e,f],[g,h,i,j,k])), - ?line [a,b,c,d,e] = id(?APPEND([a,b,c],id([d,e]))), - ?line [0,1,2,3,4,5,6] = id(?APPEND([A,1,2,3],[4,5,6])), - ?line {'EXIT',{badarg,_}} = (catch id(?APPEND([A|blurf],[4,5,6]))), + [a,b,c,d,e,f,g,h,i,j,k] = id(?APPEND([a,b,c,d,e,f],[g,h,i,j,k])), + [a,b,c,d,e] = id(?APPEND([a,b,c],id([d,e]))), + [0,1,2,3,4,5,6] = id(?APPEND([A,1,2,3],[4,5,6])), + {'EXIT',{badarg,_}} = (catch id(?APPEND([A|blurf],[4,5,6]))), ok. t_apply(Config) when is_list(Config) -> - ?line ok = apply(?MODULE, foo, []), - ?line 4 = apply(?MODULE, foo, [3]), - ?line 7 = apply(?MODULE, foo, [3,4]), - ?line 12 = apply(?MODULE, foo, [id(8),4]), - ?line 21 = apply(?MODULE, foo, [8,id(9),4]), - ?line 20 = apply(?MODULE, foo, [8,8,id(4)]), - ?line 24 = apply(?MODULE, foo, [id(10),10,4]), + ok = apply(?MODULE, foo, []), + 4 = apply(?MODULE, foo, [3]), + 7 = apply(?MODULE, foo, [3,4]), + 12 = apply(?MODULE, foo, [id(8),4]), + 21 = apply(?MODULE, foo, [8,id(9),4]), + 20 = apply(?MODULE, foo, [8,8,id(4)]), + 24 = apply(?MODULE, foo, [id(10),10,4]), M = id(?MODULE), - ?line ok = apply(M, foo, []), - ?line 4 = apply(M, foo, [3]), - ?line 16.0 = apply(M, foo, [12.0,4]), + ok = apply(M, foo, []), + 4 = apply(M, foo, [3]), + 16.0 = apply(M, foo, [12.0,4]), %% Will fail. - ?line {'EXIT',{badarg,_}} = (catch apply([a,b,c], foo, [])), - ?line {'EXIT',{badarg,_}} = (catch apply(42, foo, [])), - ?line {'EXIT',{badarg,_}} = (catch apply(?MODULE, 45, [xx])), - ?line {'EXIT',{badarg,_}} = (catch apply(?MODULE, foo, {a,b})), - ?line {'EXIT',{badarg,_}} = (catch apply(M, M, [1009|10010])), - ?line {'EXIT',{badarg,_}} = (catch apply(?MODULE, foo, [10000|9999])), - ?line {'EXIT',{badarg,_}} = (catch apply(?MODULE, foo, a)), + {'EXIT',{badarg,_}} = (catch apply([a,b,c], foo, [])), + {'EXIT',{badarg,_}} = (catch apply(42, foo, [])), + {'EXIT',{badarg,_}} = (catch apply(?MODULE, 45, [xx])), + {'EXIT',{badarg,_}} = (catch apply(?MODULE, foo, {a,b})), + {'EXIT',{badarg,_}} = (catch apply(M, M, [1009|10010])), + {'EXIT',{badarg,_}} = (catch apply(?MODULE, foo, [10000|9999])), + {'EXIT',{badarg,_}} = (catch apply(?MODULE, foo, a)), ok. @@ -210,13 +210,13 @@ bifs(Config) when is_list(Config) -> -define(CMP_DIFF(A0, B), (fun(A) -> false = A == B, true = A /= B end)(id(A0))). eq(Config) when is_list(Config) -> - ?line ?CMP_SAME([a,b,c], [a,b,c]), - ?line ?CMP_SAME([42.0], [42.0]), - ?line ?CMP_SAME([42], [42]), - ?line ?CMP_SAME([42.0], [42]), + ?CMP_SAME([a,b,c], [a,b,c]), + ?CMP_SAME([42.0], [42.0]), + ?CMP_SAME([42], [42]), + ?CMP_SAME([42.0], [42]), - ?line ?CMP_DIFF(a, [a]), - ?line ?CMP_DIFF(a, {1,2,3}), + ?CMP_DIFF(a, [a]), + ?CMP_DIFF(a, {1,2,3}), ?CMP_SAME(#{a=>1.0,b=>2}, #{b=>2.0,a=>1}), ?CMP_SAME(#{a=>[1.0],b=>[2]}, #{b=>[2.0],a=>[1]}), @@ -232,7 +232,7 @@ eq(Config) when is_list(Config) -> %% OTP-7117. nested_call_in_case(Config) when is_list(Config) -> - PrivDir = ?config(priv_dir, Config), + PrivDir = proplists:get_value(priv_dir, Config), Dir = test_lib:get_data_dir(Config), Core = filename:join(Dir, "nested_call_in_case"), Opts = [from_core,{outdir,PrivDir}|test_lib:opt_opts(?MODULE)], @@ -265,12 +265,12 @@ do_guard_try_catch(K, V) -> -record(cover_opt_guard_try, {list=[]}). coverage(Config) when is_list(Config) -> - ?line {'EXIT',{{case_clause,{a,b,c}},_}} = + {'EXIT',{{case_clause,{a,b,c}},_}} = (catch cover_will_match_list_type({a,b,c})), - ?line {'EXIT',{{case_clause,{a,b,c,d}},_}} = + {'EXIT',{{case_clause,{a,b,c,d}},_}} = (catch cover_will_match_list_type({a,b,c,d})), - ?line a = cover_remove_non_vars_alias({a,b,c}), - ?line error = cover_will_match_lit_list(), + a = cover_remove_non_vars_alias({a,b,c}), + error = cover_will_match_lit_list(), {ok,[a]} = cover_is_safe_bool_expr(a), ok = cover_opt_guard_try(#cover_opt_guard_try{list=[a]}), @@ -347,7 +347,7 @@ bsm_an_inlined(<<_:8>>, _) -> ok; bsm_an_inlined(_, _) -> error. unused_multiple_values_error(Config) when is_list(Config) -> - PrivDir = ?config(priv_dir, Config), + PrivDir = proplists:get_value(priv_dir, Config), Dir = test_lib:get_data_dir(Config), Core = filename:join(Dir, "unused_multiple_values_error"), Opts = [no_copt,clint,return,from_core,{outdir,PrivDir} diff --git a/lib/compiler/test/error_SUITE.erl b/lib/compiler/test/error_SUITE.erl index f4662ec7b2..dd2e766599 100644 --- a/lib/compiler/test/error_SUITE.erl +++ b/lib/compiler/test/error_SUITE.erl @@ -65,7 +65,7 @@ bif_clashes(Config) when is_list(Config) -> [return_warnings], {error, [{4, erl_lint,{call_to_redefined_old_bif,{length,1}}}], []} }], - ?line [] = run(Config, Ts), + [] = run(Config, Ts), Ts1 = [{bif_clashes2, <<" -export([t/0]). @@ -76,7 +76,7 @@ bif_clashes(Config) when is_list(Config) -> [return_warnings], {error, [{3, erl_lint,{redefine_old_bif_import,{length,1}}}], []} }], - ?line [] = run(Config, Ts1), + [] = run(Config, Ts1), Ts00 = [{bif_clashes3, <<" -export([t/0]). @@ -89,7 +89,7 @@ bif_clashes(Config) when is_list(Config) -> ">>, [return_warnings], []}], - ?line [] = run(Config, Ts00), + [] = run(Config, Ts00), Ts11 = [{bif_clashes4, <<" -export([t/0]). @@ -100,7 +100,7 @@ bif_clashes(Config) when is_list(Config) -> ">>, [return_warnings], []}], - ?line [] = run(Config, Ts11), + [] = run(Config, Ts11), Ts000 = [{bif_clashes5, <<" -export([t/0]). @@ -113,7 +113,7 @@ bif_clashes(Config) when is_list(Config) -> [return_warnings], {warning, [{4, erl_lint,{call_to_redefined_bif,{binary_part,3}}}]} }], - ?line [] = run(Config, Ts000), + [] = run(Config, Ts000), Ts111 = [{bif_clashes6, <<" -export([t/0]). @@ -124,7 +124,7 @@ bif_clashes(Config) when is_list(Config) -> [return_warnings], {warning, [{3, erl_lint,{redefine_bif_import,{binary_part,3}}}]} }], - ?line [] = run(Config, Ts111), + [] = run(Config, Ts111), Ts2 = [{bif_clashes7, <<" -export([t/0]). @@ -139,7 +139,7 @@ bif_clashes(Config) when is_list(Config) -> {error, [{7,erl_lint,{define_import,{length,1}}}], []} }], - ?line [] = run2(Config, Ts2), + [] = run2(Config, Ts2), Ts3 = [{bif_clashes8, <<" -export([t/1]). @@ -153,7 +153,7 @@ bif_clashes(Config) when is_list(Config) -> {error, [{4,erl_lint,{illegal_guard_local_call,{length,1}}}], []} }], - ?line [] = run2(Config, Ts3), + [] = run2(Config, Ts3), Ts4 = [{bif_clashes9, <<" -export([t/1]). @@ -166,7 +166,7 @@ bif_clashes(Config) when is_list(Config) -> {error, [{5,erl_lint,{illegal_guard_local_call,{length,1}}}], []} }], - ?line [] = run2(Config, Ts4), + [] = run2(Config, Ts4), ok. @@ -175,23 +175,23 @@ bif_clashes(Config) when is_list(Config) -> %% Tests that a head mismatch is reported on the correct line (OTP-2125). head_mismatch_line(Config) when is_list(Config) -> - ?line [E|_] = get_compilation_errors(Config, "head_mismatch_line"), - ?line {26, Mod, Reason} = E, - ?line Mod:format_error(Reason), + [E|_] = get_compilation_errors(Config, "head_mismatch_line"), + {26, Mod, Reason} = E, + Mod:format_error(Reason), ok. %% Compiles a test file and returns the list of errors. get_compilation_errors(Config, Filename) -> - ?line DataDir = ?config(data_dir, Config), - ?line File = filename:join(DataDir, Filename), - ?line {error, [{_Name, E}|_], []} = compile:file(File, [return_errors]), + DataDir = proplists:get_value(data_dir, Config), + File = filename:join(DataDir, Filename), + {error, [{_Name, E}|_], []} = compile:file(File, [return_errors]), E. warnings_as_errors(Config) when is_list(Config) -> - ?line TestFile = test_filename(Config), - ?line BeamFile = filename:rootname(TestFile, ".erl") ++ ".beam", - ?line OutDir = ?config(priv_dir, Config), + TestFile = test_filename(Config), + BeamFile = filename:rootname(TestFile, ".erl") ++ ".beam", + OutDir = proplists:get_value(priv_dir, Config), Ts1 = [{warnings_as_errors, <<" @@ -203,8 +203,8 @@ warnings_as_errors(Config) when is_list(Config) -> {error, [], [{3,erl_lint,{unused_var,'A'}}]} }], - ?line [] = run(Ts1, TestFile, write_beam), - ?line false = filelib:is_regular(BeamFile), + [] = run(Ts1, TestFile, write_beam), + false = filelib:is_regular(BeamFile), Ts2 = [{warning_unused_var, <<" @@ -216,9 +216,9 @@ warnings_as_errors(Config) when is_list(Config) -> {warning, [{3,erl_lint,{unused_var,'A'}}]} }], - ?line [] = run(Ts2, TestFile, write_beam), - ?line true = filelib:is_regular(BeamFile), - ?line ok = file:delete(BeamFile), + [] = run(Ts2, TestFile, write_beam), + true = filelib:is_regular(BeamFile), + ok = file:delete(BeamFile), ok. @@ -295,7 +295,7 @@ bad_utf8(Config) -> run(Config, Tests) -> - ?line File = test_filename(Config), + File = test_filename(Config), run(Tests, File, dont_write_beam). run(Tests, File, WriteBeam) -> @@ -304,7 +304,7 @@ run(Tests, File, WriteBeam) -> E -> BadL; Bad -> - ?t:format("~nTest ~p failed. Expected~n ~p~n" + io:format("~nTest ~p failed. Expected~n ~p~n" "but got~n ~p~n", [N, E, Bad]), fail() end @@ -312,7 +312,7 @@ run(Tests, File, WriteBeam) -> lists:foldl(F, [], Tests). run2(Config, Tests) -> - ?line File = test_filename(Config), + File = test_filename(Config), run2(Tests, File, dont_write_beam). run2(Tests, File, WriteBeam) -> @@ -321,7 +321,7 @@ run2(Tests, File, WriteBeam) -> E -> BadL; Bad -> - ?t:format("~nTest ~p failed. Expected~n ~p~n" + io:format("~nTest ~p failed. Expected~n ~p~n" "but got~n ~p~n", [N, E, Bad]), fail() end @@ -338,56 +338,45 @@ filter(X) -> test_filename(Conf) -> Filename = ["errors_test_",test_lib:uniq(),".erl"], - DataDir = ?config(priv_dir, Conf), + DataDir = proplists:get_value(priv_dir, Conf), filename:join(DataDir, Filename). run_test(Test0, File, Warnings, WriteBeam) -> ModName = filename:rootname(filename:basename(File), ".erl"), Mod = list_to_atom(ModName), Test = ["-module(",ModName,"). ",Test0], - ?line Opts = case WriteBeam of - dont_write_beam -> - [binary,return_errors|Warnings]; - write_beam -> - [return_errors|Warnings] - end, - ?line ok = file:write_file(File, Test), + Opts = case WriteBeam of + dont_write_beam -> + [binary,return_errors|Warnings]; + write_beam -> + [return_errors|Warnings] + end, + ok = file:write_file(File, Test), %% Compile once just to print all errors and warnings. - ?line compile:file(File, [binary,report|Warnings]), + compile:file(File, [binary,report|Warnings]), %% Test result of compilation. io:format("~p\n", [Opts]), - ?line Res = case compile:file(File, Opts) of - {ok,Mod,_,[{_File,Ws}]} -> - %io:format("compile:file(~s,~p) ->~n~p~n", - % [File,Opts,Ws]), - {warning,Ws}; - {ok,Mod,_,[]} -> - %io:format("compile:file(~s,~p) ->~n~p~n", - % [File,Opts,Ws]), - []; - {ok,Mod,[{_File,Ws}]} -> - {warning,Ws}; - {ok,Mod,[]} -> - []; - {error,[{XFile,Es}],Ws} = _ZZ when is_list(XFile) -> - %io:format("compile:file(~s,~p) ->~n~p~n", - % [File,Opts,_ZZ]), - {error,Es,Ws}; - {error,[{XFile,Es1},{XFile,Es2}],Ws} = _ZZ - when is_list(XFile) -> - %io:format("compile:file(~s,~p) ->~n~p~n", - % [File,Opts,_ZZ]), - {error,Es1++Es2,Ws}; - {error,Es,[{_File,Ws}]} = _ZZ-> - %io:format("compile:file(~s,~p) ->~n~p~n", - % [File,Opts,_ZZ]), - {error,Es,Ws} - end, + Res = case compile:file(File, Opts) of + {ok,Mod,_,[{_File,Ws}]} -> + {warning,Ws}; + {ok,Mod,_,[]} -> + []; + {ok,Mod,[{_File,Ws}]} -> + {warning,Ws}; + {ok,Mod,[]} -> + []; + {error,[{XFile,Es}],Ws} = _ZZ when is_list(XFile) -> + {error,Es,Ws}; + {error,[{XFile,Es1},{XFile,Es2}],Ws} = _ZZ + when is_list(XFile) -> + {error,Es1++Es2,Ws}; + {error,Es,[{_File,Ws}]} = _ZZ-> + {error,Es,Ws} + end, file:delete(File), Res. fail() -> - io:format("failed~n"), - ?t:fail(). + ct:fail(failed). diff --git a/lib/compiler/test/float_SUITE.erl b/lib/compiler/test/float_SUITE.erl index 60efe4f228..771016812b 100644 --- a/lib/compiler/test/float_SUITE.erl +++ b/lib/compiler/test/float_SUITE.erl @@ -51,11 +51,11 @@ end_per_group(_GroupName, Config) -> %% Shows the effect of pending exceptions on the x86. pending(Config) when is_list(Config) -> - ?line case catch float_mul(1, 1.1e300, 3.14e300) of - {'EXIT',{badarith,_}} -> ok; - Other -> ?t:fail({expected_exception,Other}) - end, - ?line 0.0 = float_sub(2.0). + case catch float_mul(1, 1.1e300, 3.14e300) of + {'EXIT',{badarith,_}} -> ok; + Other -> ct:fail({expected_exception,Other}) + end, + 0.0 = float_sub(2.0). float_sub(A)-> catch A - 2.0. @@ -69,11 +69,11 @@ float_mul(Iter, A, B) when is_float(A), is_float(B) -> %% Thanks to Mikael Pettersson and Tobias Lindahl (HiPE). bif_calls(Config) when is_list(Config) -> - ?line {'EXIT',{badarith,_}} = (catch bad_arith(2.0, 1.7)), - ?line {'EXIT',{badarith,_}} = (catch bad_arith_again(2.0, [])), - ?line {'EXIT',{badarith,_}} = (catch bad_arith_xor(2.0, [])), - ?line {'EXIT',{badarith,_}} = (catch bad_arith_hd(2.0, [])), - ?line {'EXIT',{badarith,_}} = (catch bad_negate(2.0, 1.7)), + {'EXIT',{badarith,_}} = (catch bad_arith(2.0, 1.7)), + {'EXIT',{badarith,_}} = (catch bad_arith_again(2.0, [])), + {'EXIT',{badarith,_}} = (catch bad_arith_xor(2.0, [])), + {'EXIT',{badarith,_}} = (catch bad_arith_hd(2.0, [])), + {'EXIT',{badarith,_}} = (catch bad_negate(2.0, 1.7)), ok. bad_arith(X, Y) when is_float(X) -> @@ -114,51 +114,51 @@ bad_negate(X, Y) when is_float(X) -> math_functions(Config) when is_list(Config) -> %% Mostly silly coverage. - ?line 0.0 = math:tan(0), - ?line 0.0 = math:atan2(0, 1), - ?line 0.0 = math:sinh(0), - ?line 1.0 = math:cosh(0), - ?line 0.0 = math:tanh(0), + 0.0 = math:tan(0), + 0.0 = math:atan2(0, 1), + 0.0 = math:sinh(0), + 1.0 = math:cosh(0), + 0.0 = math:tanh(0), 1.0 = math:log2(2), - ?line 1.0 = math:log10(10), - ?line -1.0 = math:cos(math:pi()), - ?line 1.0 = math:exp(0), - ?line 1.0 = math:pow(math:pi(), 0), - ?line 0.0 = math:log(1), - ?line 0.0 = math:asin(0), - ?line 0.0 = math:acos(1), - ?line ?OPTIONAL(0.0, math:asinh(0)), - ?line ?OPTIONAL(0.0, math:acosh(1)), - ?line ?OPTIONAL(0.0, math:atanh(0)), - ?line ?OPTIONAL(0.0, math:erf(0)), - ?line ?OPTIONAL(1.0, math:erfc(0)), - - ?line 0.0 = math:tan(id(0)), - ?line 0.0 = math:atan2(id(0), 1), - ?line 0.0 = math:sinh(id(0)), - ?line 1.0 = math:cosh(id(0)), - ?line 0.0 = math:tanh(id(0)), + 1.0 = math:log10(10), + -1.0 = math:cos(math:pi()), + 1.0 = math:exp(0), + 1.0 = math:pow(math:pi(), 0), + 0.0 = math:log(1), + 0.0 = math:asin(0), + 0.0 = math:acos(1), + ?OPTIONAL(0.0, math:asinh(0)), + ?OPTIONAL(0.0, math:acosh(1)), + ?OPTIONAL(0.0, math:atanh(0)), + ?OPTIONAL(0.0, math:erf(0)), + ?OPTIONAL(1.0, math:erfc(0)), + + 0.0 = math:tan(id(0)), + 0.0 = math:atan2(id(0), 1), + 0.0 = math:sinh(id(0)), + 1.0 = math:cosh(id(0)), + 0.0 = math:tanh(id(0)), 1.0 = math:log2(id(2)), - ?line 1.0 = math:log10(id(10)), - ?line 1.0 = math:exp(id(0)), - ?line 0.0 = math:log(id(1)), - ?line 0.0 = math:asin(id(0)), - ?line 0.0 = math:acos(id(1)), - ?line ?OPTIONAL(0.0, math:asinh(id(0))), - ?line ?OPTIONAL(0.0, math:acosh(id(1))), - ?line ?OPTIONAL(0.0, math:atanh(id(0))), - ?line ?OPTIONAL(0.0, math:erf(id(0))), - ?line ?OPTIONAL(1.0, math:erfc(id(0))), + 1.0 = math:log10(id(10)), + 1.0 = math:exp(id(0)), + 0.0 = math:log(id(1)), + 0.0 = math:asin(id(0)), + 0.0 = math:acos(id(1)), + ?OPTIONAL(0.0, math:asinh(id(0))), + ?OPTIONAL(0.0, math:acosh(id(1))), + ?OPTIONAL(0.0, math:atanh(id(0))), + ?OPTIONAL(0.0, math:erf(id(0))), + ?OPTIONAL(1.0, math:erfc(id(0))), %% Only for coverage (of beam_type.erl). - ?line {'EXIT',{undef,_}} = (catch math:fnurfla(0)), - ?line {'EXIT',{undef,_}} = (catch math:fnurfla(0, 0)), - ?line {'EXIT',{badarg,_}} = (catch float(kalle)), - ?line {'EXIT',{badarith,_}} = (catch name/1), + {'EXIT',{undef,_}} = (catch math:fnurfla(0)), + {'EXIT',{undef,_}} = (catch math:fnurfla(0, 0)), + {'EXIT',{badarg,_}} = (catch float(kalle)), + {'EXIT',{badarith,_}} = (catch name/1), ok. mixed_float_and_int(Config) when is_list(Config) -> - ?line 129.0 = pc(77, 23, 5), + 129.0 = pc(77, 23, 5), ok. pc(Cov, NotCov, X) -> diff --git a/lib/compiler/test/fun_SUITE.erl b/lib/compiler/test/fun_SUITE.erl index c6cc5b17b3..77559ae2e6 100644 --- a/lib/compiler/test/fun_SUITE.erl +++ b/lib/compiler/test/fun_SUITE.erl @@ -60,9 +60,8 @@ l1() -> ?T((begin G = fun(1=0) -> ok end, {'EXIT',_} = (catch G(2)), ok end), ok) ]. -test1(suite) -> []; test1(Config) when is_list(Config) -> - ?line lists:foreach(fun one_test/1, eval_list(l1(), [])), + lists:foreach(fun one_test/1, eval_list(l1(), [])), ok. evaluate(Str, Vars) -> @@ -93,7 +92,7 @@ one_test({C, E, Str, Correct}) -> true -> io:format("ERROR: Compiled: ~p. Expected ~p. Got ~p.~n", [Str, Correct, C]), - test_server:fail(comp) + ct:fail(comp) end, if E == Correct -> @@ -101,7 +100,7 @@ one_test({C, E, Str, Correct}) -> true -> io:format("ERROR: Interpreted: ~p. Expected ~p. Got ~p.~n", [Str, Correct, E]), - test_server:fail(comp) + ct:fail(comp) end. -record(b, {c}). @@ -109,9 +108,9 @@ one_test({C, E, Str, Correct}) -> %% OTP-7102. (Thanks to Simon Cornish.) overwritten_fun(Config) when is_list(Config) -> - ?line {a2,a} = overwritten_fun_1(a), - ?line {a2,{b,c}} = overwritten_fun_1(#b{c=c}), - ?line one = overwritten_fun_1(#b{c=[]}), + {a2,a} = overwritten_fun_1(a), + {a2,{b,c}} = overwritten_fun_1(#b{c=c}), + one = overwritten_fun_1(#b{c=[]}), ok. overwritten_fun_1(A) -> @@ -153,8 +152,8 @@ otp_7202_func() -> no_value. bif_fun(Config) when is_list(Config) -> - ?line F = fun abs/1, - ?line 5 = F(-5), + F = fun abs/1, + 5 = F(-5), ok. -define(APPLY(M, F, A), (fun(Fun) -> {ok,{a,b}} = Fun({a,b}) end)(fun M:F/A)). diff --git a/lib/compiler/test/guard_SUITE.erl b/lib/compiler/test/guard_SUITE.erl index 5391771dad..129db039e1 100644 --- a/lib/compiler/test/guard_SUITE.erl +++ b/lib/compiler/test/guard_SUITE.erl @@ -69,23 +69,23 @@ end_per_group(_GroupName, Config) -> misc(Config) when is_list(Config) -> - ?line 42 = case id(42) of - X when -X -> ok; - X -> X - end, - ?line {a,b,c} = misc_1([{{a,b,c}},{[4]},{[3]},{-2}]), - ?line none = misc_1([{{a,b,c}},{[4]},{[3]},{-3}]), - ?line none = misc_1([{{a,b,c}},{[4]},{[7]},{-2}]), - ?line none = misc_1([{{a,b,c}},{[4]},{[3]},{[1,2,3]}]), - - ?line {ok,buf,<<>>} = get_data({o,true,raw}, 0, buf), - ?line {ok,buf,<<>>} = get_data({o,true,raw}, 42, buf), - ?line {ok,buf,<<>>} = get_data({o,false,raw}, 0, buf), - ?line error = get_data({o,false,raw}, 42, buf), - ?line {ok,buf,<<>>} = get_data({o,true,0}, 0, buf), - ?line {ok,buf,<<>>} = get_data({o,true,0}, 42, buf), - ?line {ok,buf,<<>>} = get_data({o,false,0}, 0, buf), - ?line error = get_data({o,false,0}, 42, buf), + 42 = case id(42) of + X when -X -> ok; + X -> X + end, + {a,b,c} = misc_1([{{a,b,c}},{[4]},{[3]},{-2}]), + none = misc_1([{{a,b,c}},{[4]},{[3]},{-3}]), + none = misc_1([{{a,b,c}},{[4]},{[7]},{-2}]), + none = misc_1([{{a,b,c}},{[4]},{[3]},{[1,2,3]}]), + + {ok,buf,<<>>} = get_data({o,true,raw}, 0, buf), + {ok,buf,<<>>} = get_data({o,true,raw}, 42, buf), + {ok,buf,<<>>} = get_data({o,false,raw}, 0, buf), + error = get_data({o,false,raw}, 42, buf), + {ok,buf,<<>>} = get_data({o,true,0}, 0, buf), + {ok,buf,<<>>} = get_data({o,true,0}, 42, buf), + {ok,buf,<<>>} = get_data({o,false,0}, 0, buf), + error = get_data({o,false,0}, 42, buf), ok. @@ -107,11 +107,11 @@ get_data({o,Active,Raw}, BytesToRead, Buffer) end. const_cond(Config) when is_list(Config) -> - ?line ok = const_cond({}, 0), - ?line ok = const_cond({a}, 1), - ?line error = const_cond({a,b}, 3), - ?line error = const_cond({a}, 0), - ?line error = const_cond({a,b}, 1), + ok = const_cond({}, 0), + ok = const_cond({a}, 1), + error = const_cond({a,b}, 3), + error = const_cond({a}, 0), + error = const_cond({a,b}, 1), ok. const_cond(T, Sz) -> @@ -132,80 +132,80 @@ basic_not(Config) when is_list(Config) -> D = id(5), ATuple = {False,True,Glurf}, - ?line check(fun() -> if not false -> ok; true -> error end end, ok), - ?line check(fun() -> if not true -> ok; true -> error end end, error), - ?line check(fun() -> if not False -> ok; true -> error end end, ok), - ?line check(fun() -> if not True -> ok; true -> error end end, error), + check(fun() -> if not false -> ok; true -> error end end, ok), + check(fun() -> if not true -> ok; true -> error end end, error), + check(fun() -> if not False -> ok; true -> error end end, ok), + check(fun() -> if not True -> ok; true -> error end end, error), - ?line check(fun() -> if A > B -> gt; A < B -> lt; A == B -> eq end end, lt), - ?line check(fun() -> if A > C -> gt; A < C -> lt; A == C -> eq end end, gt), - ?line check(fun() -> if A > D -> gt; A < D -> lt; A == D -> eq end end, eq), + check(fun() -> if A > B -> gt; A < B -> lt; A == B -> eq end end, lt), + check(fun() -> if A > C -> gt; A < C -> lt; A == C -> eq end end, gt), + check(fun() -> if A > D -> gt; A < D -> lt; A == D -> eq end end, eq), - ?line check(fun() -> if not (7 > 453) -> le; not (7 < 453) -> ge; - not (7 == 453) -> ne; true -> eq end end, le), - ?line check(fun() -> if not (7 > -8) -> le; not (7 < -8) -> ge; - not (7 == -8) -> ne; true -> eq end end, ge), - ?line check(fun() -> if not (7 > 7) -> le; not (7 < 7) -> ge; - not (7 == 7) -> ne; true -> eq end end, le), + check(fun() -> if not (7 > 453) -> le; not (7 < 453) -> ge; + not (7 == 453) -> ne; true -> eq end end, le), + check(fun() -> if not (7 > -8) -> le; not (7 < -8) -> ge; + not (7 == -8) -> ne; true -> eq end end, ge), + check(fun() -> if not (7 > 7) -> le; not (7 < 7) -> ge; + not (7 == 7) -> ne; true -> eq end end, le), - ?line check(fun() -> if not (A > B) -> le; not (A < B) -> ge; - not (A == B) -> ne; true -> eq end end, le), - ?line check(fun() -> if not (A > C) -> le; not (A < C) -> ge; - not (A == C) -> ne; true -> eq end end, ge), - ?line check(fun() -> if not (A > D) -> le; not (A < D) -> ge; - not (A == D) -> ne; true -> eq end end, le), + check(fun() -> if not (A > B) -> le; not (A < B) -> ge; + not (A == B) -> ne; true -> eq end end, le), + check(fun() -> if not (A > C) -> le; not (A < C) -> ge; + not (A == C) -> ne; true -> eq end end, ge), + check(fun() -> if not (A > D) -> le; not (A < D) -> ge; + not (A == D) -> ne; true -> eq end end, le), - ?line check(fun() -> if not element(1, ATuple) -> ok; true -> error end end, ok), - ?line check(fun() -> if not element(2, ATuple) -> ok; true -> error end end, error), - ?line check(fun() -> if not element(3, ATuple) -> ok; true -> error end end, error), + check(fun() -> if not element(1, ATuple) -> ok; true -> error end end, ok), + check(fun() -> if not element(2, ATuple) -> ok; true -> error end end, error), + check(fun() -> if not element(3, ATuple) -> ok; true -> error end end, error), - ?line check(fun() -> if not glurf -> ok; true -> error end end, error), - ?line check(fun() -> if not Glurf -> ok; true -> error end end, error), + check(fun() -> if not glurf -> ok; true -> error end end, error), + check(fun() -> if not Glurf -> ok; true -> error end end, error), ok. complex_not(Config) when is_list(Config) -> ATuple = id({false,true,gurka}), - ?line check(fun() -> if not(element(1, ATuple)) -> ok; true -> error end end, ok), - ?line check(fun() -> if not(element(2, ATuple)) -> ok; true -> error end end, error), + check(fun() -> if not(element(1, ATuple)) -> ok; true -> error end end, ok), + check(fun() -> if not(element(2, ATuple)) -> ok; true -> error end end, error), - ?line check(fun() -> if not(element(3, ATuple) == gurka) -> ok; - true -> error end end, error), - ?line check(fun() -> if not(element(3, ATuple) =/= gurka) -> ok; - true -> error end end, ok), + check(fun() -> if not(element(3, ATuple) == gurka) -> ok; + true -> error end end, error), + check(fun() -> if not(element(3, ATuple) =/= gurka) -> ok; + true -> error end end, ok), - ?line check(fun() -> if {a,not(element(2, ATuple))} == {a,false} -> ok; - true -> error end end, ok), - ?line check(fun() -> if {a,not(element(1, ATuple))} == {a,false} -> ok; - true -> error end end, error), + check(fun() -> if {a,not(element(2, ATuple))} == {a,false} -> ok; + true -> error end end, ok), + check(fun() -> if {a,not(element(1, ATuple))} == {a,false} -> ok; + true -> error end end, error), - ?line check(fun() -> if not(element(1, ATuple) or element(3, ATuple)) -> ok; - true -> error end end, error), + check(fun() -> if not(element(1, ATuple) or element(3, ATuple)) -> ok; + true -> error end end, error), %% orelse - ?line check(fun() -> if not(element(1, ATuple) orelse element(3, ATuple)) -> ok; - true -> error end end, error), + check(fun() -> if not(element(1, ATuple) orelse element(3, ATuple)) -> ok; + true -> error end end, error), ok. nested_nots(Config) when is_list(Config) -> - ?line true = nested_not_1(0, 0), - ?line true = nested_not_1(0, 1), - ?line true = nested_not_1(a, b), - ?line true = nested_not_1(10, 0), - ?line false = nested_not_1(z, a), - ?line false = nested_not_1(3.4, {anything,goes}), - ?line false = nested_not_1(3.4, atom), - ?line true = nested_not_1(3.0, [list]), - - ?line true = nested_not_2(false, false, 42), - ?line true = nested_not_2(false, true, 42), - ?line true = nested_not_2(true, false, 42), - ?line true = nested_not_2(true, true, 42), - ?line true = nested_not_2(false, false, atom), - ?line false = nested_not_2(false, true, atom), - ?line false = nested_not_2(true, false, atom), - ?line false = nested_not_2(true, true, atom), + true = nested_not_1(0, 0), + true = nested_not_1(0, 1), + true = nested_not_1(a, b), + true = nested_not_1(10, 0), + false = nested_not_1(z, a), + false = nested_not_1(3.4, {anything,goes}), + false = nested_not_1(3.4, atom), + true = nested_not_1(3.0, [list]), + + true = nested_not_2(false, false, 42), + true = nested_not_2(false, true, 42), + true = nested_not_2(true, false, 42), + true = nested_not_2(true, true, 42), + true = nested_not_2(false, false, atom), + false = nested_not_2(false, true, atom), + false = nested_not_2(true, false, atom), + false = nested_not_2(true, true, atom), ok. nested_not_1(X, Y) when not (((X>Y) or not(is_atom(X))) and @@ -227,112 +227,112 @@ semicolon(Config) when is_list(Config) -> %% True/false combined using ';' (literal atoms). - ?line check(fun() -> if true; false -> ok end end, ok), - ?line check(fun() -> if false; true -> ok end end, ok), - ?line check(fun() -> if true; true -> ok end end, ok), - ?line check(fun() -> if false; false -> ok; true -> error end end, error), - ?line check(fun() -> - {'EXIT',{if_clause,_}} = (catch if false; false -> ok end), - exit - end, exit), + check(fun() -> if true; false -> ok end end, ok), + check(fun() -> if false; true -> ok end end, ok), + check(fun() -> if true; true -> ok end end, ok), + check(fun() -> if false; false -> ok; true -> error end end, error), + check(fun() -> + {'EXIT',{if_clause,_}} = (catch if false; false -> ok end), + exit + end, exit), %% True/false combined used ';'. True = id(true), False = id(false), - ?line check(fun() -> if True; False -> ok end end, ok), - ?line check(fun() -> if False; True -> ok end end, ok), - ?line check(fun() -> if True; True -> ok end end, ok), - ?line check(fun() -> if False; False -> ok; true -> error end end, error), - ?line check(fun() -> - {'EXIT',{if_clause,_}} = (catch if False; False -> ok end), - exit - end, exit), + check(fun() -> if True; False -> ok end end, ok), + check(fun() -> if False; True -> ok end end, ok), + check(fun() -> if True; True -> ok end end, ok), + check(fun() -> if False; False -> ok; true -> error end end, error), + check(fun() -> + {'EXIT',{if_clause,_}} = (catch if False; False -> ok end), + exit + end, exit), %% Combine true/false with a non-boolean value. Glurf = id(glurf), - ?line check(fun() -> if True; Glurf -> ok end end, ok), - ?line check(fun() -> if Glurf; True -> ok end end, ok), - ?line check(fun() -> if Glurf; Glurf -> ok; true -> error end end, error), - ?line check(fun() -> if False; Glurf -> ok; true -> error end end, error), - ?line check(fun() -> if Glurf; False -> ok; true -> error end end, error), - ?line check(fun() -> - {'EXIT',{if_clause,_}} = (catch if Glurf; Glurf -> ok end), - exit - end, exit), + check(fun() -> if True; Glurf -> ok end end, ok), + check(fun() -> if Glurf; True -> ok end end, ok), + check(fun() -> if Glurf; Glurf -> ok; true -> error end end, error), + check(fun() -> if False; Glurf -> ok; true -> error end end, error), + check(fun() -> if Glurf; False -> ok; true -> error end end, error), + check(fun() -> + {'EXIT',{if_clause,_}} = (catch if Glurf; Glurf -> ok end), + exit + end, exit), %% Combine true/false with errors. ATuple = id({false,true,gurka}), - ?line check(fun() -> if True; element(42, ATuple) -> ok end end, ok), - ?line check(fun() -> if element(42, ATuple); True -> ok end end, ok), - ?line check(fun() -> if element(42, ATuple); element(42, ATuple) -> ok; - true -> error end end, error), - ?line check(fun() -> if False; element(42, ATuple) -> ok; - true -> error end end, error), - ?line check(fun() -> if element(42, ATuple); - False -> ok; true -> error end end, error), - ?line check(fun() -> - {'EXIT',{if_clause,_}} = - (catch if element(42, ATuple); - element(42, ATuple) -> ok end), - exit - end, exit), + check(fun() -> if True; element(42, ATuple) -> ok end end, ok), + check(fun() -> if element(42, ATuple); True -> ok end end, ok), + check(fun() -> if element(42, ATuple); element(42, ATuple) -> ok; + true -> error end end, error), + check(fun() -> if False; element(42, ATuple) -> ok; + true -> error end end, error), + check(fun() -> if element(42, ATuple); + False -> ok; true -> error end end, error), + check(fun() -> + {'EXIT',{if_clause,_}} = + (catch if element(42, ATuple); + element(42, ATuple) -> ok end), + exit + end, exit), ok. complex_semicolon(Config) when is_list(Config) -> - ?line ok = csemi1(int, {blurf}), - ?line ok = csemi1(string, {blurf}), - ?line ok = csemi1(float, [a]), - ?line error = csemi1(35, 42), + ok = csemi1(int, {blurf}), + ok = csemi1(string, {blurf}), + ok = csemi1(float, [a]), + error = csemi1(35, 42), %% 2 - ?line ok = csemi2({}, {a,b,c}), - ?line ok = csemi2({1,3.5}, {a,b,c}), - ?line ok = csemi2(dum, {a,b,c}), + ok = csemi2({}, {a,b,c}), + ok = csemi2({1,3.5}, {a,b,c}), + ok = csemi2(dum, {a,b,c}), - ?line ok = csemi2({45,-19.3}, {}), - ?line ok = csemi2({45,-19.3}, {dum}), - ?line ok = csemi2({45,-19.3}, {dum,dum}), + ok = csemi2({45,-19.3}, {}), + ok = csemi2({45,-19.3}, {dum}), + ok = csemi2({45,-19.3}, {dum,dum}), - ?line error = csemi2({45}, {dum}), - ?line error = csemi2([], {dum}), - ?line error = csemi2({dum}, []), - ?line error = csemi2([], []), + error = csemi2({45}, {dum}), + error = csemi2([], {dum}), + error = csemi2({dum}, []), + error = csemi2([], []), %% 3 - ?line csemi3(fun csemi3a/4), - ?line csemi3(fun csemi3b/4), - ?line csemi3(fun csemi3c/4), + csemi3(fun csemi3a/4), + csemi3(fun csemi3b/4), + csemi3(fun csemi3c/4), %% 4 - ?line csemi4(fun csemi4a/4), - ?line csemi4(fun csemi4b/4), - ?line csemi4(fun csemi4c/4), - ?line csemi4(fun csemi4d/4), + csemi4(fun csemi4a/4), + csemi4(fun csemi4b/4), + csemi4(fun csemi4c/4), + csemi4(fun csemi4d/4), %% 4, 'orelse' instead of 'or' - ?line csemi4_orelse(fun csemi4_orelse_a/4), - ?line csemi4_orelse(fun csemi4_orelse_b/4), - ?line csemi4_orelse(fun csemi4_orelse_c/4), - ?line csemi4_orelse(fun csemi4_orelse_d/4), + csemi4_orelse(fun csemi4_orelse_a/4), + csemi4_orelse(fun csemi4_orelse_b/4), + csemi4_orelse(fun csemi4_orelse_c/4), + csemi4_orelse(fun csemi4_orelse_d/4), %% 5 - ?line error = csemi5(0, 0), - ?line ok = csemi5(5, 0), - ?line ok = csemi5(4, -4), - ?line ok = csemi5(10, -4), + error = csemi5(0, 0), + ok = csemi5(5, 0), + ok = csemi5(4, -4), + ok = csemi5(10, -4), %% 6 - ?line error = csemi6({a}, 0), - ?line ok = csemi6({a,b}, 0), - ?line ok = csemi6({}, 3), - ?line ok = csemi6({a,b,c}, 3), + error = csemi6({a}, 0), + ok = csemi6({a,b}, 0), + ok = csemi6({}, 3), + ok = csemi6({a,b,c}, 3), %% 7 error = csemi7(#{a=>1}, 1, 0), @@ -427,7 +427,7 @@ csemi4_orelse(Test) -> ok = Test({}, 2, blurf, 0), ok = Test({}, 2, {1}, 2), - ?line error = Test([], 1, {}, 0), + error = Test([], 1, {}, 0), ok. @@ -460,72 +460,72 @@ comma(Config) when is_list(Config) -> %% ',' combinations of literal true/false. - ?line check(fun() -> if true, false -> ok; true -> error end end, error), - ?line check(fun() -> if false, true -> ok; true -> error end end, error), - ?line check(fun() -> if true, true -> ok end end, ok), - ?line check(fun() -> if false, false -> ok; true -> error end end, error), - ?line check(fun() -> - {'EXIT',{if_clause,_}} = - (catch if true, false -> ok; - false, true -> ok; - false, false -> ok - end), - exit - end, exit), + check(fun() -> if true, false -> ok; true -> error end end, error), + check(fun() -> if false, true -> ok; true -> error end end, error), + check(fun() -> if true, true -> ok end end, ok), + check(fun() -> if false, false -> ok; true -> error end end, error), + check(fun() -> + {'EXIT',{if_clause,_}} = + (catch if true, false -> ok; + false, true -> ok; + false, false -> ok + end), + exit + end, exit), %% ',' combinations of true/false in variables. True = id(true), False = id(false), - ?line check(fun() -> if True, False -> ok; true -> error end end, error), - ?line check(fun() -> if False, True -> ok; true -> error end end, error), - ?line check(fun() -> if True, True -> ok end end, ok), - ?line check(fun() -> if False, False -> ok; true -> error end end, error), - ?line check(fun() -> - {'EXIT',{if_clause,_}} = - (catch if True, False -> ok; - False, True -> ok; - False, False -> ok - end), - exit - end, exit), + check(fun() -> if True, False -> ok; true -> error end end, error), + check(fun() -> if False, True -> ok; true -> error end end, error), + check(fun() -> if True, True -> ok end end, ok), + check(fun() -> if False, False -> ok; true -> error end end, error), + check(fun() -> + {'EXIT',{if_clause,_}} = + (catch if True, False -> ok; + False, True -> ok; + False, False -> ok + end), + exit + end, exit), %% ',' combinations of true/false, and non-boolean in variables. Glurf = id(glurf), - ?line check(fun() -> if True, Glurf -> ok; true -> error end end, error), - ?line check(fun() -> if Glurf, True -> ok; true -> error end end, error), - ?line check(fun() -> if True, True -> ok end end, ok), - ?line check(fun() -> if Glurf, Glurf -> ok; true -> error end end, error), - ?line check(fun() -> - {'EXIT',{if_clause,_}} = - (catch if True, Glurf -> ok; - Glurf, True -> ok; - Glurf, Glurf -> ok - end), - exit - end, exit), + check(fun() -> if True, Glurf -> ok; true -> error end end, error), + check(fun() -> if Glurf, True -> ok; true -> error end end, error), + check(fun() -> if True, True -> ok end end, ok), + check(fun() -> if Glurf, Glurf -> ok; true -> error end end, error), + check(fun() -> + {'EXIT',{if_clause,_}} = + (catch if True, Glurf -> ok; + Glurf, True -> ok; + Glurf, Glurf -> ok + end), + exit + end, exit), %% ',' combinations of true/false with errors. ATuple = id({a,b,c}), - ?line check(fun() -> if True, element(42, ATuple) -> ok; - true -> error end end, error), - ?line check(fun() -> if element(42, ATuple), True -> ok; - true -> error end end, error), - ?line check(fun() -> if True, True -> ok end end, ok), - ?line check(fun() -> if element(42, ATuple), element(42, ATuple) -> ok; - true -> error end end, error), - ?line check(fun() -> - {'EXIT',{if_clause,_}} = - (catch if True, element(42, ATuple) -> ok; - element(42, ATuple), True -> ok; - element(42, ATuple), element(42, ATuple) -> ok - end), - exit - end, exit), + check(fun() -> if True, element(42, ATuple) -> ok; + true -> error end end, error), + check(fun() -> if element(42, ATuple), True -> ok; + true -> error end end, error), + check(fun() -> if True, True -> ok end end, ok), + check(fun() -> if element(42, ATuple), element(42, ATuple) -> ok; + true -> error end end, error), + check(fun() -> + {'EXIT',{if_clause,_}} = + (catch if True, element(42, ATuple) -> ok; + element(42, ATuple), True -> ok; + element(42, ATuple), element(42, ATuple) -> ok + end), + exit + end, exit), ok. @@ -535,35 +535,35 @@ or_guard(Config) when is_list(Config) -> Glurf = id(glurf), %% 'or' combinations of literal true/false. - ?line check(fun() -> if true or false -> ok end end, ok), - ?line check(fun() -> if false or true -> ok end end, ok), - ?line check(fun() -> if true or true -> ok end end, ok), - ?line check(fun() -> if false or false -> ok; true -> error end end, error), + check(fun() -> if true or false -> ok end end, ok), + check(fun() -> if false or true -> ok end end, ok), + check(fun() -> if true or true -> ok end end, ok), + check(fun() -> if false or false -> ok; true -> error end end, error), - ?line check(fun() -> if glurf or true -> ok; true -> error end end, error), - ?line check(fun() -> if true or glurf -> ok; true -> error end end, error), - ?line check(fun() -> if glurf or glurf -> ok; true -> error end end, error), + check(fun() -> if glurf or true -> ok; true -> error end end, error), + check(fun() -> if true or glurf -> ok; true -> error end end, error), + check(fun() -> if glurf or glurf -> ok; true -> error end end, error), - ?line check(fun() -> - {'EXIT',{if_clause,_}} = (catch if false or false -> ok end), - exit - end, exit), + check(fun() -> + {'EXIT',{if_clause,_}} = (catch if false or false -> ok end), + exit + end, exit), %% 'or' combinations using variables containing true/false. - ?line check(fun() -> if True or False -> ok end end, ok), - ?line check(fun() -> if False or True -> ok end end, ok), - ?line check(fun() -> if True or True -> ok end end, ok), - ?line check(fun() -> if False or False -> ok; true -> error end end, error), + check(fun() -> if True or False -> ok end end, ok), + check(fun() -> if False or True -> ok end end, ok), + check(fun() -> if True or True -> ok end end, ok), + check(fun() -> if False or False -> ok; true -> error end end, error), - ?line check(fun() -> if True or Glurf -> ok; true -> error end end, error), - ?line check(fun() -> if Glurf or True -> ok; true -> error end end, error), - ?line check(fun() -> if Glurf or Glurf -> ok; true -> error end end, error), + check(fun() -> if True or Glurf -> ok; true -> error end end, error), + check(fun() -> if Glurf or True -> ok; true -> error end end, error), + check(fun() -> if Glurf or Glurf -> ok; true -> error end end, error), - ?line check(fun() -> - {'EXIT',{if_clause,_}} = (catch if False or False -> ok end), - exit - end, exit), + check(fun() -> + {'EXIT',{if_clause,_}} = (catch if False or False -> ok end), + exit + end, exit), ok. @@ -572,142 +572,142 @@ more_or_guards(Config) when is_list(Config) -> False = id(false), ATuple = id({false,true,gurka}), - ?line check(fun() -> - if element(42, ATuple) or False -> ok; - true -> error end - end, error), - - ?line check(fun() -> - if False or element(42, ATuple) -> ok; - true -> error end - end, error), - - ?line check(fun() -> - if element(18, ATuple) or element(42, ATuple) -> ok; - true -> error end - end, error), - - ?line check(fun() -> - if True or element(42, ATuple) -> ok; - true -> error end - end, error), - - ?line check(fun() -> - if element(42, ATuple) or True -> ok; - true -> error end - end, error), - - ?line check(fun() -> - if element(1, ATuple) or element(42, ATuple) or True -> ok; - true -> error end - end, error), - - ?line check(fun() -> - if element(1, ATuple) or True or element(42, ATuple) -> ok; - true -> error end - end, error), - - ?line check(fun() -> - if - (<<False:8>> == <<0>>) or element(2, ATuple) -> ok; - true -> error end - end, error), - - ?line check(fun() -> - if - element(2, ATuple) or (<<True:8>> == <<1>>) -> ok; - true -> error end - end, error), - - ?line check(fun() -> - if element(2, ATuple) or element(42, ATuple) -> ok; - true -> error end - end, error), - - ?line check(fun() -> - if - element(1, ATuple) or - element(2, ATuple) or - element(19, ATuple) -> ok; - true -> error end - end, error), + check(fun() -> + if element(42, ATuple) or False -> ok; + true -> error end + end, error), + + check(fun() -> + if False or element(42, ATuple) -> ok; + true -> error end + end, error), + + check(fun() -> + if element(18, ATuple) or element(42, ATuple) -> ok; + true -> error end + end, error), + + check(fun() -> + if True or element(42, ATuple) -> ok; + true -> error end + end, error), + + check(fun() -> + if element(42, ATuple) or True -> ok; + true -> error end + end, error), + + check(fun() -> + if element(1, ATuple) or element(42, ATuple) or True -> ok; + true -> error end + end, error), + + check(fun() -> + if element(1, ATuple) or True or element(42, ATuple) -> ok; + true -> error end + end, error), + + check(fun() -> + if + (<<False:8>> == <<0>>) or element(2, ATuple) -> ok; + true -> error end + end, error), + + check(fun() -> + if + element(2, ATuple) or (<<True:8>> == <<1>>) -> ok; + true -> error end + end, error), + + check(fun() -> + if element(2, ATuple) or element(42, ATuple) -> ok; + true -> error end + end, error), + + check(fun() -> + if + element(1, ATuple) or + element(2, ATuple) or + element(19, ATuple) -> ok; + true -> error end + end, error), ok. complex_or_guards(Config) when is_list(Config) -> %% complex_or_1/2 - ?line ok = complex_or_1({a,b,c,d}, {1,2,3}), - ?line ok = complex_or_1({a,b,c,d}, {1}), - ?line ok = complex_or_1({a}, {1,2,3}), - ?line error = complex_or_1({a}, {1}), + ok = complex_or_1({a,b,c,d}, {1,2,3}), + ok = complex_or_1({a,b,c,d}, {1}), + ok = complex_or_1({a}, {1,2,3}), + error = complex_or_1({a}, {1}), - ?line error = complex_or_1(1, 2), - ?line error = complex_or_1([], {a,b,c,d}), - ?line error = complex_or_1({a,b,c,d}, []), + error = complex_or_1(1, 2), + error = complex_or_1([], {a,b,c,d}), + error = complex_or_1({a,b,c,d}, []), %% complex_or_2/1 - ?line ok = complex_or_2({true,{}}), - ?line ok = complex_or_2({false,{a}}), - ?line ok = complex_or_2({false,{a,b,c}}), - ?line ok = complex_or_2({true,{a,b,c,d}}), + ok = complex_or_2({true,{}}), + ok = complex_or_2({false,{a}}), + ok = complex_or_2({false,{a,b,c}}), + ok = complex_or_2({true,{a,b,c,d}}), - ?line error = complex_or_2({blurf,{a,b,c}}), + error = complex_or_2({blurf,{a,b,c}}), - ?line error = complex_or_2({true}), - ?line error = complex_or_2({true,no_tuple}), - ?line error = complex_or_2({true,[]}), + error = complex_or_2({true}), + error = complex_or_2({true,no_tuple}), + error = complex_or_2({true,[]}), %% complex_or_3/2 - ?line ok = complex_or_3({true}, {}), - ?line ok = complex_or_3({false}, {a}), - ?line ok = complex_or_3({false}, {a,b,c}), - ?line ok = complex_or_3({true}, {a,b,c,d}), - ?line ok = complex_or_3({false}, <<1,2,3>>), - ?line ok = complex_or_3({true}, <<1,2,3,4>>), + ok = complex_or_3({true}, {}), + ok = complex_or_3({false}, {a}), + ok = complex_or_3({false}, {a,b,c}), + ok = complex_or_3({true}, {a,b,c,d}), + ok = complex_or_3({false}, <<1,2,3>>), + ok = complex_or_3({true}, <<1,2,3,4>>), - ?line error = complex_or_3(blurf, {a,b,c}), + error = complex_or_3(blurf, {a,b,c}), - ?line error = complex_or_3({false}, <<1,2,3,4>>), - ?line error = complex_or_3([], <<1,2>>), - ?line error = complex_or_3({true}, 45), - ?line error = complex_or_3(<<>>, <<>>), + error = complex_or_3({false}, <<1,2,3,4>>), + error = complex_or_3([], <<1,2>>), + error = complex_or_3({true}, 45), + error = complex_or_3(<<>>, <<>>), %% complex_or_4/2 - ?line ok = complex_or_4(<<1,2,3>>, {true}), - ?line ok = complex_or_4(<<1,2,3>>, {false}), - ?line ok = complex_or_4(<<1,2,3>>, {true}), - ?line ok = complex_or_4({1,2,3}, {true}), - ?line error = complex_or_4({1,2,3,4}, {false}), + ok = complex_or_4(<<1,2,3>>, {true}), + ok = complex_or_4(<<1,2,3>>, {false}), + ok = complex_or_4(<<1,2,3>>, {true}), + ok = complex_or_4({1,2,3}, {true}), + error = complex_or_4({1,2,3,4}, {false}), - ?line error = complex_or_4(<<1,2,3,4>>, []), - ?line error = complex_or_4([], {true}), + error = complex_or_4(<<1,2,3,4>>, []), + error = complex_or_4([], {true}), %% complex_or_5/2 - ?line ok = complex_or_5(<<1>>, {false}), - ?line ok = complex_or_5(<<1,2,3>>, {true}), - ?line ok = complex_or_5(<<1,2,3,4>>, {false}), - ?line ok = complex_or_5({1,2,3}, {false}), - ?line ok = complex_or_5({1,2,3,4}, {false}), + ok = complex_or_5(<<1>>, {false}), + ok = complex_or_5(<<1,2,3>>, {true}), + ok = complex_or_5(<<1,2,3,4>>, {false}), + ok = complex_or_5({1,2,3}, {false}), + ok = complex_or_5({1,2,3,4}, {false}), - ?line error = complex_or_5(blurf, {false}), - ?line error = complex_or_5(<<1>>, klarf), - ?line error = complex_or_5(blurf, klarf), + error = complex_or_5(blurf, {false}), + error = complex_or_5(<<1>>, klarf), + error = complex_or_5(blurf, klarf), %% complex_or_6/2 - ?line ok = complex_or_6({true,true}, {1,2,3,4}), - ?line ok = complex_or_6({true,true}, <<1,2,3,4>>), - ?line ok = complex_or_6({false,false}, <<1,2,3,4>>), - ?line ok = complex_or_6({false,true}, <<1>>), - ?line ok = complex_or_6({true,false}, {1}), - ?line ok = complex_or_6({true,true}, {1}), + ok = complex_or_6({true,true}, {1,2,3,4}), + ok = complex_or_6({true,true}, <<1,2,3,4>>), + ok = complex_or_6({false,false}, <<1,2,3,4>>), + ok = complex_or_6({false,true}, <<1>>), + ok = complex_or_6({true,false}, {1}), + ok = complex_or_6({true,true}, {1}), - ?line error = complex_or_6({false,false}, {1}), + error = complex_or_6({false,false}, {1}), - ?line error = complex_or_6({true}, {1,2,3,4}), - ?line error = complex_or_6({}, {1,2,3,4}), - ?line error = complex_or_6([], {1,2,3,4}), - ?line error = complex_or_6([], {1,2,3,4}), - ?line error = complex_or_6({true,false}, klurf), + error = complex_or_6({true}, {1,2,3,4}), + error = complex_or_6({}, {1,2,3,4}), + error = complex_or_6([], {1,2,3,4}), + error = complex_or_6([], {1,2,3,4}), + error = complex_or_6({true,false}, klurf), ok. @@ -753,79 +753,79 @@ and_guard(Config) when is_list(Config) -> %% 'and' combinations of literal true/false. - ?line check(fun() -> if true and false -> ok; true -> error end end, error), - ?line check(fun() -> if false and true -> ok; true -> error end end, error), - ?line check(fun() -> if true and true -> ok end end, ok), - ?line check(fun() -> if false and false -> ok; true -> error end end, error), - - ?line check(fun() -> if glurf and true -> ok; true -> error end end, error), - ?line check(fun() -> if true and glurf -> ok; true -> error end end, error), - ?line check(fun() -> if glurf and glurf -> ok; true -> error end end, error), - - ?line check(fun() -> - {'EXIT',{if_clause,_}} = - (catch if true and false -> ok; - false and true -> ok; - false and false -> ok - end), - exit - end, exit), + check(fun() -> if true and false -> ok; true -> error end end, error), + check(fun() -> if false and true -> ok; true -> error end end, error), + check(fun() -> if true and true -> ok end end, ok), + check(fun() -> if false and false -> ok; true -> error end end, error), + + check(fun() -> if glurf and true -> ok; true -> error end end, error), + check(fun() -> if true and glurf -> ok; true -> error end end, error), + check(fun() -> if glurf and glurf -> ok; true -> error end end, error), + + check(fun() -> + {'EXIT',{if_clause,_}} = + (catch if true and false -> ok; + false and true -> ok; + false and false -> ok + end), + exit + end, exit), %% 'and' combinations of true/false in variables. True = id(true), False = id(false), - ?line check(fun() -> if True and False -> ok; true -> error end end, error), - ?line check(fun() -> if False and True -> ok; true -> error end end, error), - ?line check(fun() -> if True and True -> ok end end, ok), - ?line check(fun() -> if False and False -> ok; true -> error end end, error), - ?line check(fun() -> - {'EXIT',{if_clause,_}} = - (catch if True and False -> ok; - False and True -> ok; - False and False -> ok - end), - exit - end, exit), + check(fun() -> if True and False -> ok; true -> error end end, error), + check(fun() -> if False and True -> ok; true -> error end end, error), + check(fun() -> if True and True -> ok end end, ok), + check(fun() -> if False and False -> ok; true -> error end end, error), + check(fun() -> + {'EXIT',{if_clause,_}} = + (catch if True and False -> ok; + False and True -> ok; + False and False -> ok + end), + exit + end, exit), %% 'and' combinations of true/false and a non-boolean in variables. Glurf = id(glurf), - ?line check(fun() -> if True and Glurf -> ok; true -> error end end, error), - ?line check(fun() -> if Glurf and True -> ok; true -> error end end, error), - ?line check(fun() -> if True and True -> ok end end, ok), - ?line check(fun() -> if Glurf and Glurf -> ok; true -> error end end, error), - ?line check(fun() -> - {'EXIT',{if_clause,_}} = - (catch if True and Glurf -> ok; - Glurf and True -> ok; - Glurf and Glurf -> ok - end), - exit - end, exit), + check(fun() -> if True and Glurf -> ok; true -> error end end, error), + check(fun() -> if Glurf and True -> ok; true -> error end end, error), + check(fun() -> if True and True -> ok end end, ok), + check(fun() -> if Glurf and Glurf -> ok; true -> error end end, error), + check(fun() -> + {'EXIT',{if_clause,_}} = + (catch if True and Glurf -> ok; + Glurf and True -> ok; + Glurf and Glurf -> ok + end), + exit + end, exit), %% 'and' combinations of true/false with errors. ATuple = id({a,b,c}), - ?line check(fun() -> if True and element(42, ATuple) -> ok; - true -> error end end, error), - ?line check(fun() -> if element(42, ATuple) and True -> ok; - true -> error end end, error), - ?line check(fun() -> if True and True -> ok end end, ok), - ?line check(fun() -> if element(42, ATuple) and element(42, ATuple) -> ok; - true -> error end end, error), - ?line check(fun() -> - {'EXIT',{if_clause,_}} = - (catch if True and element(42, ATuple) -> ok; - element(42, ATuple) and True -> ok; - element(42, ATuple) and element(42, ATuple) -> ok - end), + check(fun() -> if True and element(42, ATuple) -> ok; + true -> error end end, error), + check(fun() -> if element(42, ATuple) and True -> ok; + true -> error end end, error), + check(fun() -> if True and True -> ok end end, ok), + check(fun() -> if element(42, ATuple) and element(42, ATuple) -> ok; + true -> error end end, error), + check(fun() -> + {'EXIT',{if_clause,_}} = + (catch if True and element(42, ATuple) -> ok; + element(42, ATuple) and True -> ok; + element(42, ATuple) and element(42, ATuple) -> ok + end), exit end, exit), - ?line ok = relprod({'Set',a,b}, {'Set',a,b}), + ok = relprod({'Set',a,b}, {'Set',a,b}), ok = and_same_var(42), {'EXIT',{if_clause,_}} = (catch and_same_var(x)), @@ -844,18 +844,18 @@ relprod(R1, R2) when (erlang:size(R1) =:= 3) and (erlang:element(1,R1) =:= 'Set' xor_guard(Config) when is_list(Config) -> %% 'xor' combinations of literal true/false. - ?line check(fun() -> if true xor false -> ok end end, ok), - ?line check(fun() -> if false xor true -> ok end end, ok), - ?line check(fun() -> if true xor true -> ok; true -> error end end, error), - ?line check(fun() -> if false xor false -> ok; true -> error end end, error), - ?line check(fun() -> - {'EXIT',{if_clause,_}} = (catch if false xor false -> ok end), - exit - end, exit), - ?line check(fun() -> - {'EXIT',{if_clause,_}} = (catch if true xor true -> ok end), - exit - end, exit), + check(fun() -> if true xor false -> ok end end, ok), + check(fun() -> if false xor true -> ok end end, ok), + check(fun() -> if true xor true -> ok; true -> error end end, error), + check(fun() -> if false xor false -> ok; true -> error end end, error), + check(fun() -> + {'EXIT',{if_clause,_}} = (catch if false xor false -> ok end), + exit + end, exit), + check(fun() -> + {'EXIT',{if_clause,_}} = (catch if true xor true -> ok end), + exit + end, exit), %% 'xor' combinations using variables containing true/false. @@ -863,18 +863,18 @@ xor_guard(Config) when is_list(Config) -> True = id(true), False = id(false), - ?line check(fun() -> if True xor False -> ok end end, ok), - ?line check(fun() -> if False xor True -> ok end end, ok), - ?line check(fun() -> if True xor True -> ok; true -> error end end, error), - ?line check(fun() -> if False xor False -> ok; true -> error end end, error), - ?line check(fun() -> - {'EXIT',{if_clause,_}} = (catch if False xor False -> ok end), - exit - end, exit), - ?line check(fun() -> - {'EXIT',{if_clause,_}} = (catch if True xor True -> ok end), - exit - end, exit), + check(fun() -> if True xor False -> ok end end, ok), + check(fun() -> if False xor True -> ok end end, ok), + check(fun() -> if True xor True -> ok; true -> error end end, error), + check(fun() -> if False xor False -> ok; true -> error end end, error), + check(fun() -> + {'EXIT',{if_clause,_}} = (catch if False xor False -> ok end), + exit + end, exit), + check(fun() -> + {'EXIT',{if_clause,_}} = (catch if True xor True -> ok end), + exit + end, exit), ok. @@ -883,53 +883,53 @@ more_xor_guards(Config) when is_list(Config) -> False = id(false), ATuple = id({false,true,gurka}), - ?line check(fun() -> - if element(42, ATuple) xor False -> ok; - true -> error end - end, error), - - ?line check(fun() -> - if False xor element(42, ATuple) xor False -> ok; - true -> error end - end, error), - - ?line check(fun() -> - if element(18, ATuple) xor element(42, ATuple) -> ok; - true -> error end - end, error), - - ?line check(fun() -> - if True xor element(42, ATuple) -> ok; - true -> error end - end, error), - - ?line check(fun() -> - if element(42, ATuple) xor True -> ok; - true -> error end - end, error), + check(fun() -> + if element(42, ATuple) xor False -> ok; + true -> error end + end, error), + + check(fun() -> + if False xor element(42, ATuple) xor False -> ok; + true -> error end + end, error), + + check(fun() -> + if element(18, ATuple) xor element(42, ATuple) -> ok; + true -> error end + end, error), + + check(fun() -> + if True xor element(42, ATuple) -> ok; + true -> error end + end, error), + + check(fun() -> + if element(42, ATuple) xor True -> ok; + true -> error end + end, error), ok. build_in_guard(Config) when is_list(Config) -> SubBin = <<5.0/float>>, - ?line B = <<1,SubBin/binary,3.5/float>>, - ?line if - B =:= <<1,SubBin/binary,3.5/float>> -> ok - end. + B = <<1,SubBin/binary,3.5/float>>, + if + B =:= <<1,SubBin/binary,3.5/float>> -> ok + end. old_guard_tests(Config) when list(Config) -> %% Check that all the old guard tests are still recognized. - ?line list = og(Config), - ?line atom = og(an_atom), - ?line binary = og(<<1,2>>), - ?line float = og(3.14), - ?line integer = og(43), - ?line a_function = og(fun() -> ok end), - ?line pid = og(self()), - ?line reference = og(make_ref()), - ?line tuple = og({}), - - ?line number = on(45.333), - ?line number = on(-19), + list = og(Config), + atom = og(an_atom), + binary = og(<<1,2>>), + float = og(3.14), + integer = og(43), + a_function = og(fun() -> ok end), + pid = og(self()), + reference = og(make_ref()), + tuple = og({}), + + number = on(45.333), + number = on(-19), ok. og(V) when atom(V) -> atom; @@ -948,8 +948,8 @@ on(V) when number(V) -> number; on(_) -> not_number. gbif(Config) when is_list(Config) -> - ?line error = gbif_1(1, {false,true}), - ?line ok = gbif_1(2, {false,true}), + error = gbif_1(1, {false,true}), + ok = gbif_1(2, {false,true}), ok. gbif_1(P, T) when element(P, T) -> ok; @@ -957,57 +957,57 @@ gbif_1(_, _) -> error. t_is_boolean(Config) when is_list(Config) -> - ?line true = is_boolean(true), - ?line true = is_boolean(false), - ?line true = is_boolean(id(true)), - ?line true = is_boolean(id(false)), - - ?line false = is_boolean(glurf), - ?line false = is_boolean(id(glurf)), - - ?line false = is_boolean([]), - ?line false = is_boolean(id([])), - ?line false = is_boolean(42), - ?line false = is_boolean(id(-42)), - - ?line false = is_boolean(math:pi()), - ?line false = is_boolean(384793478934378924978439789873478934897), - - ?line false = is_boolean(id(self())), - ?line false = is_boolean(id({x,y,z})), - ?line false = is_boolean(id([a,b,c])), - ?line false = is_boolean(id(make_ref())), - ?line false = is_boolean(id(<<1,2,3>>)), - ?line false = is_boolean({id(x),y,z}), - ?line false = is_boolean([id(a),b,c]), - - ?line ok = bool(true), - ?line ok = bool(false), - ?line ok = bool(id(true)), - ?line ok = bool(id(false)), - - ?line error = bool(glurf), - ?line error = bool(id(glurf)), - - ?line error = bool([]), - ?line error = bool(id([])), - ?line error = bool(42), - ?line error = bool(id(-42)), - - ?line error = bool(math:pi()), - ?line error = bool(384793478934378924978439789873478934897), - - ?line error = bool(id(self())), - ?line error = bool(id({x,y,z})), - ?line error = bool(id([a,b,c])), - ?line error = bool(id(make_ref())), - ?line error = bool(id(<<1,2,3>>)), - - ?line true = my_is_bool(true), - ?line true = my_is_bool(false), - ?line false = my_is_bool([]), - ?line false = my_is_bool([1,2,3,4]), - ?line false = my_is_bool({a,b,c}), + true = is_boolean(true), + true = is_boolean(false), + true = is_boolean(id(true)), + true = is_boolean(id(false)), + + false = is_boolean(glurf), + false = is_boolean(id(glurf)), + + false = is_boolean([]), + false = is_boolean(id([])), + false = is_boolean(42), + false = is_boolean(id(-42)), + + false = is_boolean(math:pi()), + false = is_boolean(384793478934378924978439789873478934897), + + false = is_boolean(id(self())), + false = is_boolean(id({x,y,z})), + false = is_boolean(id([a,b,c])), + false = is_boolean(id(make_ref())), + false = is_boolean(id(<<1,2,3>>)), + false = is_boolean({id(x),y,z}), + false = is_boolean([id(a),b,c]), + + ok = bool(true), + ok = bool(false), + ok = bool(id(true)), + ok = bool(id(false)), + + error = bool(glurf), + error = bool(id(glurf)), + + error = bool([]), + error = bool(id([])), + error = bool(42), + error = bool(id(-42)), + + error = bool(math:pi()), + error = bool(384793478934378924978439789873478934897), + + error = bool(id(self())), + error = bool(id({x,y,z})), + error = bool(id([a,b,c])), + error = bool(id(make_ref())), + error = bool(id(<<1,2,3>>)), + + true = my_is_bool(true), + true = my_is_bool(false), + false = my_is_bool([]), + false = my_is_bool([1,2,3,4]), + false = my_is_bool({a,b,c}), ok. @@ -1048,18 +1048,18 @@ is_function_2(Config) when is_list(Config) -> end. tricky(Config) when is_list(Config) -> - ?line not_ok = tricky_1(1, 2), - ?line not_ok = tricky_1(1, blurf), - ?line not_ok = tricky_1(foo, 2), - ?line not_ok = tricky_1(a, b), - - ?line error = tricky_2(0.5), - ?line error = tricky_2(a), - ?line error = tricky_2({a,b,c}), - - ?line false = rb(100000, [1], 42), - ?line true = rb(100000, [], 42), - ?line true = rb(555, [a,b,c], 19), + not_ok = tricky_1(1, 2), + not_ok = tricky_1(1, blurf), + not_ok = tricky_1(foo, 2), + not_ok = tricky_1(a, b), + + error = tricky_2(0.5), + error = tricky_2(a), + error = tricky_2({a,b,c}), + + false = rb(100000, [1], 42), + true = rb(100000, [], 42), + true = rb(555, [a,b,c], 19), ok. tricky_1(X, Y) when abs((X == 1) or (Y == 2)) -> ok; @@ -1097,40 +1097,40 @@ rb(_, _, _) -> false. rel_ops(Config) when is_list(Config) -> - ?line ?T(=/=, 1, 1.0), - ?line ?F(=/=, 2, 2), - ?line ?F(=/=, {a}, {a}), + ?T(=/=, 1, 1.0), + ?F(=/=, 2, 2), + ?F(=/=, {a}, {a}), - ?line ?F(/=, a, a), - ?line ?F(/=, 0, 0.0), - ?line ?T(/=, 0, 1), - ?line ?F(/=, {a}, {a}), + ?F(/=, a, a), + ?F(/=, 0, 0.0), + ?T(/=, 0, 1), + ?F(/=, {a}, {a}), - ?line ?T(==, 1, 1.0), - ?line ?F(==, a, {}), + ?T(==, 1, 1.0), + ?F(==, a, {}), - ?line ?F(=:=, 1, 1.0), - ?line ?T(=:=, 42.0, 42.0), + ?F(=:=, 1, 1.0), + ?T(=:=, 42.0, 42.0), - ?line ?F(>, a, b), - ?line ?T(>, 42, 1.0), - ?line ?F(>, 42, 42.0), + ?F(>, a, b), + ?T(>, 42, 1.0), + ?F(>, 42, 42.0), - ?line ?T(<, a, b), - ?line ?F(<, 42, 1.0), - ?line ?F(<, 42, 42.0), + ?T(<, a, b), + ?F(<, 42, 1.0), + ?F(<, 42, 42.0), - ?line ?T(=<, 1.5, 5), - ?line ?F(=<, -9, -100.344), - ?line ?T(=<, 42, 42.0), + ?T(=<, 1.5, 5), + ?F(=<, -9, -100.344), + ?T(=<, 42, 42.0), - ?line ?T(>=, 42, 42.0), - ?line ?F(>=, a, b), - ?line ?T(>=, 1.0, 0), + ?T(>=, 42, 42.0), + ?F(>=, a, b), + ?T(>=, 1.0, 0), %% Coverage of beam_block:is_exact_eq_ok/1 and collect/1. - ?line true = any_atom /= id(42), - ?line true = [] /= id(42), + true = any_atom /= id(42), + true = [] /= id(42), ok. @@ -1371,10 +1371,10 @@ literal_type_tests(Config) when is_list(Config) -> literal_type_tests_1(Config) -> %% Generate an Erlang module with all different type of type tests. - ?line Tests = make_test([{T,L} || T <- type_tests(), L <- literals()] ++ + Tests = make_test([{T,L} || T <- type_tests(), L <- literals()] ++ [{is_function,L1,L2} || L1 <- literals(), L2 <- literals()]), - ?line Mod = literal_test, + Mod = literal_test, Anno = erl_anno:new(0), Func = {function, Anno, test, 0, [{clause,Anno,[],[],Tests}]}, Form = [{attribute,Anno,module,Mod}, @@ -1382,24 +1382,24 @@ literal_type_tests_1(Config) -> Func, {eof,Anno}], %% Print generated code for inspection. - ?line lists:foreach(fun (F) -> io:put_chars([erl_pp:form(F),"\n"]) end, Form), + lists:foreach(fun (F) -> io:put_chars([erl_pp:form(F),"\n"]) end, Form), %% Test compile:form/1. This implies full optimization (default). - ?line {ok,Mod,Code1} = compile:forms(Form), - ?line smoke_disasm(Config, Mod, Code1), - ?line {module,Mod} = code:load_binary(Mod, Mod, Code1), - ?line Mod:test(), - ?line true = code:delete(Mod), - ?line code:purge(Mod), + {ok,Mod,Code1} = compile:forms(Form), + smoke_disasm(Config, Mod, Code1), + {module,Mod} = code:load_binary(Mod, Mod, Code1), + Mod:test(), + true = code:delete(Mod), + code:purge(Mod), %% Test compile:form/2. Turn off all optimizations. - ?line {ok,Mod,Code2} = compile:forms(Form, [binary,report,time, + {ok,Mod,Code2} = compile:forms(Form, [binary,report,time, no_copt,no_postopt]), - ?line smoke_disasm(Config, Mod, Code2), - ?line {module,Mod} = code:load_binary(Mod, Mod, Code2), - ?line Mod:test(), - ?line true = code:delete(Mod), - ?line code:purge(Mod), + smoke_disasm(Config, Mod, Code2), + {module,Mod} = code:load_binary(Mod, Mod, Code2), + Mod:test(), + true = code:delete(Mod), + code:purge(Mod), ok. make_test([{T,L1,L2}|Ts]) -> @@ -1427,7 +1427,7 @@ test(T, L1, L2) -> {match,Anno,{atom,Anno,Val},hd(E)}. smoke_disasm(Config, Mod, Bin) -> - Priv = ?config(priv_dir, Config), + Priv = proplists:get_value(priv_dir, Config), File = filename:join(Priv, atom_to_list(Mod)++".beam"), ok = file:write_file(File, Bin), test_lib:smoke_disasm(File). @@ -1459,30 +1459,30 @@ type_tests() -> is_function]. basic_andalso_orelse(Config) when is_list(Config) -> - ?line T = id({type,integers,23,42}), - ?line 65 = if - ((element(1, T) =:= type) andalso (tuple_size(T) =:= 4) andalso - element(2, T)) == integers -> - element(3, T) + element(4, T); - true -> error - end, - ?line 65 = case [] of - [] when ((element(1, T) =:= type) andalso (tuple_size(T) =:= 4) andalso - element(2, T)) == integers -> - element(3, T) + element(4, T) - end, - - ?line 42 = basic_rt({type,integers,40,2}), - ?line 5.0 = basic_rt({vector,{3.0,4.0}}), - ?line 20 = basic_rt(['+',3,7]), - ?line {'Set',a,b} = basic_rt({{'Set',a,b},{'Set',a,b}}), - ?line 12 = basic_rt({klurf,4}), - - ?line error = basic_rt({type,integers,40,2,3}), - ?line error = basic_rt({kalle,integers,40,2}), - ?line error = basic_rt({kalle,integers,40,2}), - ?line error = basic_rt({1,2}), - ?line error = basic_rt([]), + T = id({type,integers,23,42}), + 65 = if + ((element(1, T) =:= type) andalso (tuple_size(T) =:= 4) andalso + element(2, T)) == integers -> + element(3, T) + element(4, T); + true -> error + end, + 65 = case [] of + [] when ((element(1, T) =:= type) andalso (tuple_size(T) =:= 4) andalso + element(2, T)) == integers -> + element(3, T) + element(4, T) + end, + + 42 = basic_rt({type,integers,40,2}), + 5.0 = basic_rt({vector,{3.0,4.0}}), + 20 = basic_rt(['+',3,7]), + {'Set',a,b} = basic_rt({{'Set',a,b},{'Set',a,b}}), + 12 = basic_rt({klurf,4}), + + error = basic_rt({type,integers,40,2,3}), + error = basic_rt({kalle,integers,40,2}), + error = basic_rt({kalle,integers,40,2}), + error = basic_rt({1,2}), + error = basic_rt([]), RelProdBody = fun(R1, R2) -> @@ -1493,7 +1493,7 @@ basic_andalso_orelse(Config) when is_list(Config) -> end end, - ?line ok = RelProdBody({'Set',a,b}, {'Set',a,b}), + ok = RelProdBody({'Set',a,b}, {'Set',a,b}), %% 'andalso'/'orelse' with calls known to fail already at compile time. %% Used to crash the code generator. @@ -1564,14 +1564,14 @@ traverse_dcd({Cont,Recs},Log,Fun) -> check_qlc_hrl(Config) when is_list(Config) -> St = {r1,false,dum}, - ?line foo = cqlc(qlc, q, [{lc,1,2,3}], St), - ?line foo = cqlc(qlc, q, [{lc,1,2,3},b], St), - ?line St = cqlc(qlc, q, [], St), - ?line St = cqlc(qlc, blurf, [{lc,1,2,3},b], St), - ?line St = cqlc(q, q, [{lc,1,2,3},b], St), - ?line St = cqlc(qlc, q, [{lc,1,2,3},b,c], St), - ?line St = cqlc(qlc, q, [a,b], St), - ?line {r1,true,kalle} = cqlc(qlc, q, [{lc,1,2,3},b], {r1,true,kalle}), + foo = cqlc(qlc, q, [{lc,1,2,3}], St), + foo = cqlc(qlc, q, [{lc,1,2,3},b], St), + St = cqlc(qlc, q, [], St), + St = cqlc(qlc, blurf, [{lc,1,2,3},b], St), + St = cqlc(q, q, [{lc,1,2,3},b], St), + St = cqlc(qlc, q, [{lc,1,2,3},b,c], St), + St = cqlc(qlc, q, [a,b], St), + {r1,true,kalle} = cqlc(qlc, q, [{lc,1,2,3},b], {r1,true,kalle}), ok. %% From erl_lint.erl; original name was check_qlc_hrl/4. @@ -1588,13 +1588,13 @@ cqlc(M, F, As, St) -> %% OTP-7679: Thanks to Hunter Morris. andalso_semi(Config) when is_list(Config) -> - ?line ok = andalso_semi_foo(0), - ?line ok = andalso_semi_foo(1), - ?line fc(catch andalso_semi_foo(2)), + ok = andalso_semi_foo(0), + ok = andalso_semi_foo(1), + fc(catch andalso_semi_foo(2)), - ?line ok = andalso_semi_bar([a,b,c]), - ?line ok = andalso_semi_bar(1), - ?line fc(catch andalso_semi_bar([a,b])), + ok = andalso_semi_bar([a,b,c]), + ok = andalso_semi_bar(1), + fc(catch andalso_semi_bar([a,b])), ok. andalso_semi_foo(Bar) when is_integer(Bar) andalso Bar =:= 0; Bar =:= 1 -> @@ -1605,20 +1605,20 @@ andalso_semi_bar(Bar) when is_list(Bar) andalso length(Bar) =:= 3; Bar =:= 1 -> t_tuple_size(Config) when is_list(Config) -> - ?line 10 = do_tuple_size({1,2,3,4}), - ?line fc(catch do_tuple_size({1,2,3})), - ?line fc(catch do_tuple_size(42)), + 10 = do_tuple_size({1,2,3,4}), + fc(catch do_tuple_size({1,2,3})), + fc(catch do_tuple_size(42)), - ?line error = ludicrous_tuple_size({a,b,c}), - ?line error = ludicrous_tuple_size([a,b,c]), + error = ludicrous_tuple_size({a,b,c}), + error = ludicrous_tuple_size([a,b,c]), %% Test the "unsafe case" - the register assigned the tuple size is %% not killed. - ?line DataDir = test_lib:get_data_dir(Config), - ?line File = filename:join(DataDir, "guard_SUITE_tuple_size"), - ?line {ok,Mod,Code} = compile:file(File, [from_asm,binary]), - ?line code:load_binary(Mod, File, Code), - ?line 14 = Mod:t({1,2,3,4}), + DataDir = test_lib:get_data_dir(Config), + File = filename:join(DataDir, "guard_SUITE_tuple_size"), + {ok,Mod,Code} = compile:file(File, [from_asm,binary]), + code:load_binary(Mod, File, Code), + 14 = Mod:t({1,2,3,4}), _ = code:delete(Mod), _ = code:purge(Mod), @@ -1647,71 +1647,70 @@ mask_error({'EXIT',{Err,_}}) -> mask_error(Else) -> Else. -binary_part(doc) -> - ["Tests the binary_part/2,3 guard (GC) bif's"]; +%% Test the binary_part/2,3 guard (GC) BIFs. binary_part(Config) when is_list(Config) -> %% This is more or less a copy of what the guard_SUITE in emulator %% does to cover the guard bif's - ?line 1 = bptest(<<1,2,3>>), - ?line 2 = bptest(<<2,1,3>>), - ?line error = bptest(<<1>>), - ?line error = bptest(<<>>), - ?line error = bptest(apa), - ?line 3 = bptest(<<2,3,3>>), + 1 = bptest(<<1,2,3>>), + 2 = bptest(<<2,1,3>>), + error = bptest(<<1>>), + error = bptest(<<>>), + error = bptest(apa), + 3 = bptest(<<2,3,3>>), % With one variable (pos) - ?line 1 = bptest(<<1,2,3>>,1), - ?line 2 = bptest(<<2,1,3>>,1), - ?line error = bptest(<<1>>,1), - ?line error = bptest(<<>>,1), - ?line error = bptest(apa,1), - ?line 3 = bptest(<<2,3,3>>,1), + 1 = bptest(<<1,2,3>>,1), + 2 = bptest(<<2,1,3>>,1), + error = bptest(<<1>>,1), + error = bptest(<<>>,1), + error = bptest(apa,1), + 3 = bptest(<<2,3,3>>,1), % With one variable (length) - ?line 1 = bptesty(<<1,2,3>>,1), - ?line 2 = bptesty(<<2,1,3>>,1), - ?line error = bptesty(<<1>>,1), - ?line error = bptesty(<<>>,1), - ?line error = bptesty(apa,1), - ?line 3 = bptesty(<<2,3,3>>,2), + 1 = bptesty(<<1,2,3>>,1), + 2 = bptesty(<<2,1,3>>,1), + error = bptesty(<<1>>,1), + error = bptesty(<<>>,1), + error = bptesty(apa,1), + 3 = bptesty(<<2,3,3>>,2), % With one variable (whole tuple) - ?line 1 = bptestx(<<1,2,3>>,{1,1}), - ?line 2 = bptestx(<<2,1,3>>,{1,1}), - ?line error = bptestx(<<1>>,{1,1}), - ?line error = bptestx(<<>>,{1,1}), - ?line error = bptestx(apa,{1,1}), - ?line 3 = bptestx(<<2,3,3>>,{1,2}), + 1 = bptestx(<<1,2,3>>,{1,1}), + 2 = bptestx(<<2,1,3>>,{1,1}), + error = bptestx(<<1>>,{1,1}), + error = bptestx(<<>>,{1,1}), + error = bptestx(apa,{1,1}), + 3 = bptestx(<<2,3,3>>,{1,2}), % With two variables - ?line 1 = bptest(<<1,2,3>>,1,1), - ?line 2 = bptest(<<2,1,3>>,1,1), - ?line error = bptest(<<1>>,1,1), - ?line error = bptest(<<>>,1,1), - ?line error = bptest(apa,1,1), - ?line 3 = bptest(<<2,3,3>>,1,2), + 1 = bptest(<<1,2,3>>,1,1), + 2 = bptest(<<2,1,3>>,1,1), + error = bptest(<<1>>,1,1), + error = bptest(<<>>,1,1), + error = bptest(apa,1,1), + 3 = bptest(<<2,3,3>>,1,2), % Direct (autoimported) call, these will be evaluated by the compiler... - ?line <<2>> = binary_part(<<1,2,3>>,1,1), - ?line <<1>> = binary_part(<<2,1,3>>,1,1), + <<2>> = binary_part(<<1,2,3>>,1,1), + <<1>> = binary_part(<<2,1,3>>,1,1), % Compiler warnings due to constant evaluation expected (3) - ?line badarg = ?MASK_ERROR(binary_part(<<1>>,1,1)), - ?line badarg = ?MASK_ERROR(binary_part(<<>>,1,1)), - ?line badarg = ?MASK_ERROR(binary_part(apa,1,1)), - ?line <<3,3>> = binary_part(<<2,3,3>>,1,2), + badarg = ?MASK_ERROR(binary_part(<<1>>,1,1)), + badarg = ?MASK_ERROR(binary_part(<<>>,1,1)), + badarg = ?MASK_ERROR(binary_part(apa,1,1)), + <<3,3>> = binary_part(<<2,3,3>>,1,2), % Direct call through apply - ?line <<2>> = apply(erlang,binary_part,[<<1,2,3>>,1,1]), - ?line <<1>> = apply(erlang,binary_part,[<<2,1,3>>,1,1]), + <<2>> = apply(erlang,binary_part,[<<1,2,3>>,1,1]), + <<1>> = apply(erlang,binary_part,[<<2,1,3>>,1,1]), % Compiler warnings due to constant evaluation expected (3) - ?line badarg = ?MASK_ERROR(apply(erlang,binary_part,[<<1>>,1,1])), - ?line badarg = ?MASK_ERROR(apply(erlang,binary_part,[<<>>,1,1])), - ?line badarg = ?MASK_ERROR(apply(erlang,binary_part,[apa,1,1])), - ?line <<3,3>> = apply(erlang,binary_part,[<<2,3,3>>,1,2]), + badarg = ?MASK_ERROR(apply(erlang,binary_part,[<<1>>,1,1])), + badarg = ?MASK_ERROR(apply(erlang,binary_part,[<<>>,1,1])), + badarg = ?MASK_ERROR(apply(erlang,binary_part,[apa,1,1])), + <<3,3>> = apply(erlang,binary_part,[<<2,3,3>>,1,2]), % Constant propagation - ?line Bin = <<1,2,3>>, - ?line ok = if + Bin = <<1,2,3>>, + ok = if binary_part(Bin,1,1) =:= <<2>> -> ok; %% Compiler warning, clause cannot match (expected) true -> error end, - ?line ok = if + ok = if binary_part(Bin,{1,1}) =:= <<2>> -> ok; %% Compiler warning, clause cannot match (expected) @@ -1778,24 +1777,24 @@ bptest(_,_,_) -> -define(FAILING(C), if - C -> ?t:fail(should_fail); + C -> ct:fail(should_fail); true -> ok end, if - true, C -> ?t:fail(should_fail); + true, C -> ct:fail(should_fail); true -> ok end). bad_constants(Config) when is_list(Config) -> - ?line ?FAILING(false), - ?line ?FAILING([]), - ?line ?FAILING([a]), - ?line ?FAILING([Config]), - ?line ?FAILING({a,b}), - ?line ?FAILING({a,Config}), - ?line ?FAILING(<<1>>), - ?line ?FAILING(42), - ?line ?FAILING(3.14), + ?FAILING(false), + ?FAILING([]), + ?FAILING([a]), + ?FAILING([Config]), + ?FAILING({a,b}), + ?FAILING({a,Config}), + ?FAILING(<<1>>), + ?FAILING(42), + ?FAILING(3.14), ok. bad_guards(Config) when is_list(Config) -> @@ -1915,7 +1914,7 @@ check(F, Result) -> Other -> io:format("Expected: ~p\n", [Result]), io:format(" Got: ~p\n", [Other]), - test_server:fail() + ct:fail(check_failed) end. fc({'EXIT',{function_clause,_}}) -> ok; diff --git a/lib/compiler/test/inline_SUITE.erl b/lib/compiler/test/inline_SUITE.erl index f28e1e5a25..4c53b96fe6 100644 --- a/lib/compiler/test/inline_SUITE.erl +++ b/lib/compiler/test/inline_SUITE.erl @@ -47,8 +47,8 @@ init_per_suite(Config) -> [{testing_node,Node}|Config]. end_per_suite(Config) -> - Node = ?config(testing_node, Config), - ?t:stop_node(Node), + Node = proplists:get_value(testing_node, Config), + test_server:stop_node(Node), ok. init_per_group(_GroupName, Config) -> @@ -60,16 +60,16 @@ end_per_group(_GroupName, Config) -> attribute(Config) when is_list(Config) -> Name = "attribute", - ?line Src = filename:join(?config(data_dir, Config), Name), - ?line Out = ?config(priv_dir,Config), + Src = filename:join(proplists:get_value(data_dir, Config), Name), + Out = proplists:get_value(priv_dir,Config), - ?line {ok,attribute=Mod} = compile:file(Src, [{outdir,Out},report,time]), - ?line Outfile = filename:join(Out, Name++".beam"), - ?line {ok,{Mod,[{locals,Locals}]}} = beam_lib:chunks(Outfile, [locals]), - ?line io:format("locals: ~p\n", [Locals]), + {ok,attribute=Mod} = compile:file(Src, [{outdir,Out},report,time]), + Outfile = filename:join(Out, Name++".beam"), + {ok,{Mod,[{locals,Locals}]}} = beam_lib:chunks(Outfile, [locals]), + io:format("locals: ~p\n", [Locals]), %% The inliner should have removed all local functions. - ?line [] = Locals, + [] = Locals, ok. @@ -89,48 +89,46 @@ attribute(Config) when is_list(Config) -> ?comp(maps_inline_test). try_inline(Mod, Config) -> - Node = ?config(testing_node, Config), - ?line Src = filename:join(?config(data_dir, Config), atom_to_list(Mod)), - ?line Out = ?config(priv_dir,Config), + Node = proplists:get_value(testing_node, Config), + Src = filename:join(proplists:get_value(data_dir, Config), + atom_to_list(Mod)), + Out = proplists:get_value(priv_dir,Config), %% Normal compilation. - ?line io:format("Compiling: ~s\n", [Src]), - ?line {ok,Mod} = compile:file(Src, [{outdir,Out},report,bin_opt_info,clint]), + io:format("Compiling: ~s\n", [Src]), + {ok,Mod} = compile:file(Src, [{outdir,Out},report,bin_opt_info,clint]), - ?line Dog = test_server:timetrap(test_server:minutes(10)), - ?line NormalResult = rpc:call(Node, ?MODULE, load_and_call, [Out,Mod]), - ?line test_server:timetrap_cancel(Dog), + ct:timetrap({minutes,10}), + NormalResult = rpc:call(Node, ?MODULE, load_and_call, [Out,Mod]), %% Inlining. - ?line io:format("Compiling with old inliner: ~s\n", [Src]), - ?line {ok,Mod} = compile:file(Src, [{outdir,Out},report,bin_opt_info, + io:format("Compiling with old inliner: ~s\n", [Src]), + {ok,Mod} = compile:file(Src, [{outdir,Out},report,bin_opt_info, {inline,1000},clint]), %% Run inlined code. - ?line Dog3 = test_server:timetrap(test_server:minutes(10)), - ?line OldInlinedResult = rpc:call(Node, ?MODULE, load_and_call, [Out,Mod]), - ?line test_server:timetrap_cancel(Dog3), + ct:timetrap({minutes,10}), + OldInlinedResult = rpc:call(Node, ?MODULE, load_and_call, [Out,Mod]), %% Compare results. - ?line compare(NormalResult, OldInlinedResult), - ?line NormalResult = OldInlinedResult, + compare(NormalResult, OldInlinedResult), + NormalResult = OldInlinedResult, %% Inlining. - ?line io:format("Compiling with new inliner: ~s\n", [Src]), - ?line {ok,Mod} = compile:file(Src, [{outdir,Out},report, + io:format("Compiling with new inliner: ~s\n", [Src]), + {ok,Mod} = compile:file(Src, [{outdir,Out},report, bin_opt_info,inline,clint]), %% Run inlined code. - ?line Dog4 = test_server:timetrap(test_server:minutes(10)), - ?line InlinedResult = rpc:call(Node, ?MODULE, load_and_call, [Out,Mod]), - ?line test_server:timetrap_cancel(Dog4), + ct:timetrap({minutes,10}), + InlinedResult = rpc:call(Node, ?MODULE, load_and_call, [Out,Mod]), %% Compare results. - ?line compare(NormalResult, InlinedResult), - ?line NormalResult = InlinedResult, + compare(NormalResult, InlinedResult), + NormalResult = InlinedResult, %% Delete Beam file. - ?line ok = file:delete(filename:join(Out, atom_to_list(Mod)++code:objfile_extension())), + ok = file:delete(filename:join(Out, atom_to_list(Mod)++code:objfile_extension())), ok. @@ -142,24 +140,24 @@ compare([{X,Y,RGB1}|T1], [{X,Y,RGB2}|T2]) -> compare(T1, T2); compare([H1|_], [H2|_]) -> io:format("Normal = ~p, Inlined = ~p\n", [H1,H2]), - ?t:fail(); + ct:fail(different); compare([], []) -> ok. start_node(Name, Args) -> case test_server:start_node(Name, slave, [{args,Args}]) of {ok,Node} -> {ok, Node}; - Error -> ?line test_server:fail(Error) + Error -> ct:fail(Error) end. load_and_call(Out, Module) -> - ?line io:format("Loading...\n",[]), - ?line code:purge(Module), - ?line LoadRc = code:load_abs(filename:join(Out, Module)), - ?line {module,Module} = LoadRc, - - ?line io:format("Calling...\n",[]), - ?line {Time,CallResult} = timer:tc(Module, Module, []), - ?line io:format("Time: ~p\n", [Time]), + io:format("Loading...\n",[]), + code:purge(Module), + LoadRc = code:load_abs(filename:join(Out, Module)), + {module,Module} = LoadRc, + + io:format("Calling...\n",[]), + {Time,CallResult} = timer:tc(Module, Module, []), + io:format("Time: ~p\n", [Time]), CallResult. %% Macros used by lists/1 below. @@ -195,69 +193,78 @@ load_and_call(Out, Module) -> %% Note: This module must be compiled with the inline_lists_funcs option. lists(Config) when is_list(Config) -> - ?line List = lists:seq(1, 20), + List = lists:seq(1, 20), %% lists:map/2 - ?line ?TestHighOrder_2(map, (fun(E) -> - R = E band 16#ff, - put(?MODULE, [E|get(?MODULE)]), - R - end), List), + ?TestHighOrder_2(map, + (fun(E) -> + R = E band 16#ff, + put(?MODULE, [E|get(?MODULE)]), + R + end), List), %% lists:flatmap/2 - ?line ?TestHighOrder_2(flatmap, (fun(E) -> - R = lists:duplicate(E, E), - put(?MODULE, [E|get(?MODULE)]), - R - end), List), + ?TestHighOrder_2(flatmap, + (fun(E) -> + R = lists:duplicate(E, E), + put(?MODULE, [E|get(?MODULE)]), + R + end), List), %% lists:foreach/2 - ?line ?TestHighOrder_2(foreach, - (fun(E) -> - put(?MODULE, [E bor 7|get(?MODULE)]) - end), List), + ?TestHighOrder_2(foreach, + (fun(E) -> + put(?MODULE, [E bor 7|get(?MODULE)]) + end), List), %% lists:filter/2 - ?line ?TestHighOrder_2(filter, (fun(E) -> - put(?MODULE, [E|get(?MODULE)]), - (E bsr 1) band 1 =/= 0 - end), List), + ?TestHighOrder_2(filter, + (fun(E) -> + put(?MODULE, [E|get(?MODULE)]), + (E bsr 1) band 1 =/= 0 + end), List), %% lists:any/2 - ?line ?TestHighOrder_2(any, (fun(E) -> - put(?MODULE, [E|get(?MODULE)]), - false %Force it to go through all. - end), List), + ?TestHighOrder_2(any, + (fun(E) -> + put(?MODULE, [E|get(?MODULE)]), + false %Force it to go through all. + end), List), %% lists:all/2 - ?line ?TestHighOrder_2(all, (fun(E) -> - put(?MODULE, [E|get(?MODULE)]), - true %Force it to go through all. - end), List), + ?TestHighOrder_2(all, + (fun(E) -> + put(?MODULE, [E|get(?MODULE)]), + true %Force it to go through all. + end), List), %% lists:foldl/3 - ?line ?TestHighOrder_3(foldl, (fun(E, A) -> - put(?MODULE, [E|get(?MODULE)]), - A bxor E - end), 0, List), + ?TestHighOrder_3(foldl, + (fun(E, A) -> + put(?MODULE, [E|get(?MODULE)]), + A bxor E + end), 0, List), %% lists:foldr/3 - ?line ?TestHighOrder_3(foldr, (fun(E, A) -> - put(?MODULE, [E|get(?MODULE)]), - A bxor (bnot E) - end), 0, List), + ?TestHighOrder_3(foldr, + (fun(E, A) -> + put(?MODULE, [E|get(?MODULE)]), + A bxor (bnot E) + end), 0, List), %% lists:mapfoldl/3 - ?line ?TestHighOrder_3(mapfoldl, (fun(E, A) -> - put(?MODULE, [E|get(?MODULE)]), - {bnot E,A bxor (bnot E)} - end), 0, List), + ?TestHighOrder_3(mapfoldl, + (fun(E, A) -> + put(?MODULE, [E|get(?MODULE)]), + {bnot E,A bxor (bnot E)} + end), 0, List), %% lists:mapfoldr/3 - ?line ?TestHighOrder_3(mapfoldr, (fun(E, A) -> - put(?MODULE, [E|get(?MODULE)]), - {bnot E,A bxor (bnot E)} - end), 0, List), + ?TestHighOrder_3(mapfoldr, + (fun(E, A) -> + put(?MODULE, [E|get(?MODULE)]), + {bnot E,A bxor (bnot E)} + end), 0, List), %% Cleanup. erase(?MODULE), @@ -330,7 +337,7 @@ badarg(Reply, _A) -> Reply. otp_7223(Config) when is_list(Config) -> - ?line {'EXIT', {{case_clause,{1}},_}} = (catch otp_7223_1(1)), + {'EXIT', {{case_clause,{1}},_}} = (catch otp_7223_1(1)), ok. -compile({inline,[{otp_7223_1,1}]}). @@ -343,7 +350,7 @@ otp_7223_2({a}) -> coverage(Config) when is_list(Config) -> Mod = bsdecode, - Src = filename:join(?config(data_dir, Config), Mod), + Src = filename:join(proplists:get_value(data_dir, Config), Mod), {ok,Mod,_} = compile:file(Src, [binary,report,{inline,0},clint]), {ok,Mod,_} = compile:file(Src, [binary,report,{inline,20}, verbose,clint]), diff --git a/lib/compiler/test/lc_SUITE.erl b/lib/compiler/test/lc_SUITE.erl index 43e23f3b46..70c80d3353 100644 --- a/lib/compiler/test/lc_SUITE.erl +++ b/lib/compiler/test/lc_SUITE.erl @@ -28,7 +28,9 @@ -include_lib("common_test/include/ct.hrl"). -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,1}}]. all() -> test_lib:recompile(?MODULE), @@ -59,12 +61,9 @@ end_per_group(_GroupName, Config) -> init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) -> - Dog = test_server:timetrap(?t:minutes(1)), - [{watchdog,Dog}|Config]. + Config. end_per_testcase(Case, Config) when is_atom(Case), is_list(Config) -> - Dog = ?config(watchdog, Config), - ?t:timetrap_cancel(Dog), ok. basic(Config) when is_list(Config) -> @@ -171,7 +170,7 @@ no_gen_verify(Res, A, B) -> ShouldBe -> ok; _ -> io:format("A = ~p; B = ~p; Expected = ~p, actual = ~p", [A,B,ShouldBe,Res]), - ?t:fail() + ct:fail(failed) end. no_gen_eval(Fun, Res) -> diff --git a/lib/compiler/test/map_SUITE.erl b/lib/compiler/test/map_SUITE.erl index af98584e00..14d175b92c 100644 --- a/lib/compiler/test/map_SUITE.erl +++ b/lib/compiler/test/map_SUITE.erl @@ -1479,7 +1479,7 @@ t_guard_fun(Config) when is_list(Config) -> {'EXIT', {function_clause,[{?MODULE,_,[#{s:=none,v:=none}],_}|_]}} -> ok; {'EXIT', {{case_clause,_},_}} -> {comment,inlined}; Other -> - test_server:fail({no_match, Other}) + ct:fail({no_match, Other}) end. @@ -1565,7 +1565,7 @@ t_build_and_match_empty_val(Config) when is_list(Config) -> {'EXIT',{function_clause,_}} -> ok; {'EXIT', {{case_clause,_},_}} -> {comment,inlined}; Other -> - test_server:fail({no_match, Other}) + ct:fail({no_match, Other}) end. t_build_and_match_val(Config) when is_list(Config) -> @@ -1583,7 +1583,7 @@ t_build_and_match_val(Config) when is_list(Config) -> {'EXIT',{function_clause,_}} -> ok; {'EXIT', {{case_clause,_},_}} -> {comment,inlined}; Other -> - test_server:fail({no_match, Other}) + ct:fail({no_match, Other}) end. t_build_and_match_nil(Config) when is_list(Config) -> diff --git a/lib/compiler/test/match_SUITE.erl b/lib/compiler/test/match_SUITE.erl index 8e88d26b62..41fa1603ef 100644 --- a/lib/compiler/test/match_SUITE.erl +++ b/lib/compiler/test/match_SUITE.erl @@ -55,10 +55,10 @@ end_per_group(_GroupName, Config) -> pmatch(Config) when is_list(Config) -> - ?line ok = doit(1), - ?line ok = doit(2), - ?line {error,baz} = doit(3), - ?line {error,foobar} = doit(4), + ok = doit(1), + ok = doit(2), + {error,baz} = doit(3), + {error,foobar} = doit(4), ok. %% Thanks to Tobias Lindahl (HiPE). @@ -78,13 +78,13 @@ doit(X) -> end. mixed(Config) when is_list(Config) -> - ?line glufs = mixit(1), - ?line klafs = mixit(2), - ?line fnurra = mixit(3), - ?line usch = mixit(4), - ?line {error,blurf} = mixit(5), - ?line {error,87987987} = mixit(6), - ?line {error,{a,b,c}} = mixit(7), + glufs = mixit(1), + klafs = mixit(2), + fnurra = mixit(3), + usch = mixit(4), + {error,blurf} = mixit(5), + {error,87987987} = mixit(6), + {error,{a,b,c}} = mixit(7), ok. mixit(X) -> @@ -106,41 +106,41 @@ mixit(X) -> aliases(Config) when is_list(Config) -> %% Lists/strings. - ?line ok = str_alias("abc"), - ?line ok = str_alias("def"), - ?line ok = str_alias("ghi"), - ?line ok = str_alias("klm"), - ?line ok = str_alias("qrs"), - ?line ok = str_alias("xy"), - ?line ok = str_alias(""), - ?line ok = str_alias([]), - ?line error = str_alias("blurf"), + ok = str_alias("abc"), + ok = str_alias("def"), + ok = str_alias("ghi"), + ok = str_alias("klm"), + ok = str_alias("qrs"), + ok = str_alias("xy"), + ok = str_alias(""), + ok = str_alias([]), + error = str_alias("blurf"), %% Characters/integers. - ?line ok = char_alias($v), - ?line ok = char_alias(118), - ?line ok = char_alias($w), - ?line ok = char_alias(119), - ?line ok = char_alias(42), - ?line ok = char_alias(3.0), - ?line error = char_alias($_), - ?line error = char_alias(0), - - ?line {42,42,42} = three(42), - - ?line {1,42,99,1,42,99} = tuple_alias({1,42,99}), - ?line {-10,20,-10,20,-10,20} = tuple_alias({-10,20}), - ?line 6 = tup_lit_alias({1,2,3}), - ?line 6 = tup_lit_alias_rev({1,2,3}), - - ?line {42,42,42,42} = multiple_aliases_1(42), - ?line {7,7,7} = multiple_aliases_2(7), - ?line {{a,b},{a,b},{a,b}} = multiple_aliases_3({a,b}), + ok = char_alias($v), + ok = char_alias(118), + ok = char_alias($w), + ok = char_alias(119), + ok = char_alias(42), + ok = char_alias(3.0), + error = char_alias($_), + error = char_alias(0), + + {42,42,42} = three(42), + + {1,42,99,1,42,99} = tuple_alias({1,42,99}), + {-10,20,-10,20,-10,20} = tuple_alias({-10,20}), + 6 = tup_lit_alias({1,2,3}), + 6 = tup_lit_alias_rev({1,2,3}), + + {42,42,42,42} = multiple_aliases_1(42), + {7,7,7} = multiple_aliases_2(7), + {{a,b},{a,b},{a,b}} = multiple_aliases_3({a,b}), %% Lists/literals. - ?line {a,b} = list_alias1([a,b]), - ?line {a,b} = list_alias2([a,b]), - ?line {a,b} = list_alias3([a,b]), + {a,b} = list_alias1([a,b]), + {a,b} = list_alias2([a,b]), + {a,b} = list_alias3([a,b]), %% Non-matching aliases. none = mixed_aliases(<<42>>), @@ -261,14 +261,14 @@ mixed_aliases(_) -> none. %% OTP-7018. match_in_call(Config) when is_list(Config) -> - ?line mac_a(0), - ?line mac_b(1), - ?line mac_c(42), - ?line mac_d(42), - ?line mac_e({gurka,42}), + mac_a(0), + mac_b(1), + mac_c(42), + mac_d(42), + mac_e({gurka,42}), - ?line [{2,2},{2,2}] = mac_lc([{2,any},{2,2}]), - ?line {'EXIT',_} = (catch mac_lc([{1,1}])), + [{2,2},{2,2}] = mac_lc([{2,any},{2,2}]), + {'EXIT',_} = (catch mac_lc([{1,1}])), ok. @@ -313,8 +313,8 @@ gurka({gurka,X}, X) -> ok. untuplify(Config) when is_list(Config) -> %% We do this to cover sys_core_fold:unalias_pat/1. - ?line {1,2,3,4,alias,{[1,2],{3,4},alias}} = untuplify_1([1,2], {3,4}, alias), - ?line error = untuplify_1([1,2], {3,4}, 42), + {1,2,3,4,alias,{[1,2],{3,4},alias}} = untuplify_1([1,2], {3,4}, alias), + error = untuplify_1([1,2], {3,4}, 42), ok. untuplify_1(A, B, C) -> @@ -329,11 +329,11 @@ untuplify_1(A, B, C) -> %% Coverage of beam_dead:shortcut_boolean_label/4. shortcut_boolean(Config) when is_list(Config) -> - ?line false = shortcut_boolean_1([0]), - ?line true = shortcut_boolean_1({42}), - ?line maybe = shortcut_boolean_1(self()), - ?line {'EXIT',_} = (catch shortcut_boolean_1([a,b])), - ?line {'EXIT',_} = (catch shortcut_boolean_1({a,b})), + false = shortcut_boolean_1([0]), + true = shortcut_boolean_1({42}), + maybe = shortcut_boolean_1(self()), + {'EXIT',_} = (catch shortcut_boolean_1([a,b])), + {'EXIT',_} = (catch shortcut_boolean_1({a,b})), ok. shortcut_boolean_1(X) -> @@ -352,8 +352,8 @@ shortcut_boolean_1(X) -> %% Test sys_core_fold:letify_guard/3. letify_guard(Config) when is_list(Config) -> - ?line {-15,a} = letify_guard(-15, a), - ?line 5 = letify_guard(2, 3), + {-15,a} = letify_guard(-15, a), + 5 = letify_guard(2, 3), ok. letify_guard(A, B) -> @@ -369,18 +369,18 @@ letify_guard(A, B) -> %% instructions in beam_dead and beam_peep. selectify(Config) when is_list(Config) -> - ?line integer = sel_different_types({r,42}), - ?line atom = sel_different_types({r,forty_two}), - ?line none = sel_different_types({r,18}), - ?line {'EXIT',_} = (catch sel_different_types([a,b,c])), - - ?line integer = sel_same_value({r,42}), - ?line error = sel_same_value({r,100}), - ?line error = sel_same_value(a), - - ?line integer42 = sel_same_value2(42), - ?line integer43 = sel_same_value2(43), - ?line error = sel_same_value2(44), + integer = sel_different_types({r,42}), + atom = sel_different_types({r,forty_two}), + none = sel_different_types({r,18}), + {'EXIT',_} = (catch sel_different_types([a,b,c])), + + integer = sel_same_value({r,42}), + error = sel_same_value({r,100}), + error = sel_same_value(a), + + integer42 = sel_same_value2(42), + integer43 = sel_same_value2(43), + error = sel_same_value2(44), ok. sel_different_types({r,_}=T) when element(2, T) =:= forty_two -> diff --git a/lib/compiler/test/misc_SUITE.erl b/lib/compiler/test/misc_SUITE.erl index 9c65151685..8a639f741f 100644 --- a/lib/compiler/test/misc_SUITE.erl +++ b/lib/compiler/test/misc_SUITE.erl @@ -49,15 +49,14 @@ -opaque misc_SUITE_test_cases() :: [atom()]. init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) -> - Dog = test_server:timetrap(?t:minutes(10)), - [{watchdog,Dog}|Config]. + Config. end_per_testcase(Case, Config) when is_atom(Case), is_list(Config) -> - Dog = ?config(watchdog, Config), - ?t:timetrap_cancel(Dog), ok. -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,10}}]. -spec all() -> misc_SUITE_test_cases(). all() -> @@ -92,32 +91,27 @@ abs(_N) -> binary_part(_,_,_) -> dummy_bp. -% Make sure that auto-imported BIF's are overridden correctly - -override_bif(suite) -> - []; -override_bif(doc) -> - ["Test dat local functions and imports override auto-imported BIFs."]; +%% Test that local functions and imports override auto-imported BIFs. override_bif(Config) when is_list(Config) -> - ?line dummy_abs = abs(1), - ?line dummy_bp = binary_part(<<"hello">>,1,1), - ?line dummy = binary_part(<<"hello">>,{1,1}), - ?line 1 = erlang:abs(1), - ?line <<"e">> = erlang:binary_part(<<"hello">>,1,1), - ?line <<"e">> = erlang:binary_part(<<"hello">>,{1,1}), + dummy_abs = abs(1), + dummy_bp = binary_part(<<"hello">>,1,1), + dummy = binary_part(<<"hello">>,{1,1}), + 1 = erlang:abs(1), + <<"e">> = erlang:binary_part(<<"hello">>,1,1), + <<"e">> = erlang:binary_part(<<"hello">>,{1,1}), F = fun(X) when byte_size(X) =:= 4 -> four; (X) -> byte_size(X) end, - ?line four = F(<<1,2,3,4>>), - ?line 5 = F(<<1,2,3,4,5>>), + four = F(<<1,2,3,4>>), + 5 = F(<<1,2,3,4,5>>), ok. %% A bug reported by Tobias Lindahl for a development version of R11B. tobias(Config) when is_list(Config) -> - ?line 1 = tobias_1([1,2,3]), + 1 = tobias_1([1,2,3]), ok. tobias_1([H|_T]) -> @@ -138,7 +132,7 @@ tobias_2(_, _) -> -record(r, {s = ""}). empty_string(Config) when is_list(Config) -> - ?line #r{s="x"} = empty_string_1(#r{}), + #r{s="x"} = empty_string_1(#r{}), ok. empty_string_1(T) -> @@ -153,15 +147,15 @@ md5(Config) when is_list(Config) -> end. md5() -> - ?line Dir = filename:dirname(code:which(?MODULE)), - ?line Beams = filelib:wildcard(filename:join(Dir, "*.beam")), - ?line io:format("Found ~w beam files", [length(Beams)]), - ?line lists:foreach(fun md5_1/1, Beams). + Dir = filename:dirname(code:which(?MODULE)), + Beams = filelib:wildcard(filename:join(Dir, "*.beam")), + io:format("Found ~w beam files", [length(Beams)]), + lists:foreach(fun md5_1/1, Beams). md5_1(Beam) -> - ?line {ok,{Mod,[Vsn]}} = beam_lib:version(Beam), - ?line {ok,Code} = file:read_file(Beam), - ?line {Mod,<<Vsn:128>>} = {Mod,code:module_md5(Code)}. + {ok,{Mod,[Vsn]}} = beam_lib:version(Beam), + {ok,Code} = file:read_file(Beam), + {Mod,<<Vsn:128>>} = {Mod,code:module_md5(Code)}. %% Cover some code that handles internal errors. @@ -170,9 +164,9 @@ silly_coverage(Config) when is_list(Config) -> BadCoreErlang = {c_module,[], name,[],[], [{{c_var,[],{foo,2}},seriously_bad_body}]}, - ?line expect_error(fun() -> sys_core_fold:module(BadCoreErlang, []) end), - ?line expect_error(fun() -> sys_core_dsetel:module(BadCoreErlang, []) end), - ?line expect_error(fun() -> v3_kernel:module(BadCoreErlang, []) end), + expect_error(fun() -> sys_core_fold:module(BadCoreErlang, []) end), + expect_error(fun() -> sys_core_dsetel:module(BadCoreErlang, []) end), + expect_error(fun() -> v3_kernel:module(BadCoreErlang, []) end), %% v3_life BadKernel = {k_mdef,[],?MODULE, @@ -182,11 +176,11 @@ silly_coverage(Config) when is_list(Config) -> {k,[],[],[]}, f,0,[], seriously_bad_body}]}, - ?line expect_error(fun() -> v3_life:module(BadKernel, []) end), + expect_error(fun() -> v3_life:module(BadKernel, []) end), %% v3_codegen CodegenInput = {?MODULE,[{foo,0}],[],[{function,foo,0,[a|b],a,b,[]}]}, - ?line expect_error(fun() -> v3_codegen:module(CodegenInput, []) end), + expect_error(fun() -> v3_codegen:module(CodegenInput, []) end), %% beam_a BeamAInput = {?MODULE,[{foo,0}],[], @@ -210,7 +204,7 @@ silly_coverage(Config) when is_list(Config) -> [{label,1}, {func_info,{atom,?MODULE},{atom,foo},0}, {label,2}|non_proper_list]}],99}, - ?line expect_error(fun() -> beam_block:module(BlockInput, []) end), + expect_error(fun() -> beam_block:module(BlockInput, []) end), %% beam_bs BsInput = BlockInput, @@ -240,7 +234,7 @@ silly_coverage(Config) when is_list(Config) -> [{label,1}, {func_info,{atom,?MODULE},{atom,foo},0}, {label,2}|non_proper_list]}],99}, - ?line expect_error(fun() -> beam_bool:module(BoolInput, []) end), + expect_error(fun() -> beam_bool:module(BoolInput, []) end), %% beam_dead. This is tricky. Our function must look OK to %% beam_utils:clean_labels/1, but must crash beam_dead. @@ -259,7 +253,7 @@ silly_coverage(Config) when is_list(Config) -> {func_info,{atom,?MODULE},{atom,foo},0}, {label,2}, {jump,{f,42}}]}],99}, - ?line expect_error(fun() -> beam_clean:module(CleanInput, []) end), + expect_error(fun() -> beam_clean:module(CleanInput, []) end), %% beam_peep PeepInput = {?MODULE,[{foo,0}],[], @@ -267,7 +261,7 @@ silly_coverage(Config) when is_list(Config) -> [{label,1}, {func_info,{atom,?MODULE},{atom,foo},0}, {label,2}|non_proper_list]}],99}, - ?line expect_error(fun() -> beam_peep:module(PeepInput, []) end), + expect_error(fun() -> beam_peep:module(PeepInput, []) end), %% beam_bsm. This is tricky. Our function must be sane enough to not crash %% btb_index/1, but must crash the main optimization pass. @@ -278,7 +272,7 @@ silly_coverage(Config) when is_list(Config) -> {label,2}, {test,bs_get_binary2,{f,99},0,[{x,0},{atom,all},1,[]],{x,0}}, {block,[a|b]}]}],0}, - ?line expect_error(fun() -> beam_bsm:module(BsmInput, []) end), + expect_error(fun() -> beam_bsm:module(BsmInput, []) end), %% beam_receive. ReceiveInput = {?MODULE,[{foo,0}],[], @@ -288,7 +282,7 @@ silly_coverage(Config) when is_list(Config) -> {label,2}, {call_ext,0,{extfunc,erlang,make_ref,0}}, {block,[a|b]}]}],0}, - ?line expect_error(fun() -> beam_receive:module(ReceiveInput, []) end), + expect_error(fun() -> beam_receive:module(ReceiveInput, []) end), BeamZInput = {?MODULE,[{foo,0}],[], [{function,foo,0,2, @@ -311,27 +305,30 @@ expect_error(Fun) -> try Fun() of Any -> io:format("~p", [Any]), - ?t:fail(call_was_supposed_to_fail) + ct:fail(call_was_supposed_to_fail) catch Class:Reason -> Stk = erlang:get_stacktrace(), io:format("~p:~p\n~p\n", [Class,Reason,Stk]), case {Class,Reason} of {error,undef} -> - ?t:fail(not_supposed_to_fail_with_undef); + ct:fail(not_supposed_to_fail_with_undef); {_,_} -> ok end end. confused_literals(Config) when is_list(Config) -> - ?line {0,infinity} = confused_literals_1(int), - ?line {0.0,infinity} = confused_literals_1(float), + {0,infinity} = confused_literals_1(int), + {0.0,infinity} = confused_literals_1(float), ok. confused_literals_1(int) -> {0,infinity}; confused_literals_1(float) -> {0.0,infinity}. +integer_encoding() -> + [{timetrap,{minutes,4}}]. + integer_encoding(Config) when is_list(Config) -> case ?MODULE of misc_SUITE -> integer_encoding_1(Config); @@ -339,22 +336,21 @@ integer_encoding(Config) when is_list(Config) -> end. integer_encoding_1(Config) -> - Dog = test_server:timetrap(?t:minutes(4)), - ?line PrivDir = ?config(priv_dir, Config), - ?line SrcFile = filename:join(PrivDir, "misc_SUITE_integer_encoding.erl"), - ?line DataFile = filename:join(PrivDir, "integer_encoding.data"), + PrivDir = proplists:get_value(priv_dir, Config), + SrcFile = filename:join(PrivDir, "misc_SUITE_integer_encoding.erl"), + DataFile = filename:join(PrivDir, "integer_encoding.data"), Mod = misc_SUITE_integer_encoding, %% Create files. - ?line {ok,Src} = file:open(SrcFile, [write]), - ?line {ok,Data} = file:open(DataFile, [write]), + {ok,Src} = file:open(SrcFile, [write]), + {ok,Data} = file:open(DataFile, [write]), io:format(Src, "-module(~s).\n", [Mod]), io:put_chars(Src, "-export([t/1]).\n"), io:put_chars(Src, "t(Last) ->[\n"), io:put_chars(Data, "[\n"), - ?line do_integer_encoding(-(id(1) bsl 10000), Src, Data), - ?line do_integer_encoding(id(1) bsl 10000, Src, Data), + do_integer_encoding(-(id(1) bsl 10000), Src, Data), + do_integer_encoding(id(1) bsl 10000, Src, Data), do_integer_encoding(1024, 0, Src, Data), _ = [begin B = 1 bsl I, @@ -366,25 +362,24 @@ integer_encoding_1(Config) -> do_integer_encoding(B+1, Src, Data) end || I <- lists:seq(1, 128)], io:put_chars(Src, "Last].\n\n"), - ?line ok = file:close(Src), + ok = file:close(Src), io:put_chars(Data, "0].\n\n"), - ?line ok = file:close(Data), + ok = file:close(Data), %% Compile and load Erlang module. - ?line SrcRoot = filename:rootname(SrcFile), - ?line {ok,Mod,Binary} = compile:file(SrcRoot, [binary,report]), - ?line {module,Mod} = code:load_binary(Mod, SrcRoot, Binary), + SrcRoot = filename:rootname(SrcFile), + {ok,Mod,Binary} = compile:file(SrcRoot, [binary,report]), + {module,Mod} = code:load_binary(Mod, SrcRoot, Binary), %% Compare lists. - ?line List = Mod:t(0), - ?line {ok,[List]} = file:consult(DataFile), + List = Mod:t(0), + {ok,[List]} = file:consult(DataFile), OneBsl10000 = id(1) bsl 10000, - ?line [-(1 bsl 10000),OneBsl10000|_] = List, + [-(1 bsl 10000),OneBsl10000|_] = List, %% Cleanup. - ?line file:delete(SrcFile), - ?line file:delete(DataFile), - ?t:timetrap_cancel(Dog), + file:delete(SrcFile), + file:delete(DataFile), ok. do_integer_encoding(0, _, _, _) -> ok; diff --git a/lib/compiler/test/num_bif_SUITE.erl b/lib/compiler/test/num_bif_SUITE.erl index a94ca40b38..78f6fdc3c7 100644 --- a/lib/compiler/test/num_bif_SUITE.erl +++ b/lib/compiler/test/num_bif_SUITE.erl @@ -65,68 +65,68 @@ end_per_group(_GroupName, Config) -> t_abs(Config) when is_list(Config) -> %% Floats. - ?line 5.5 = abs(5.5), - ?line 0.0 = abs(0.0), - ?line 100.0 = abs(-100.0), + 5.5 = abs(5.5), + 0.0 = abs(0.0), + 100.0 = abs(-100.0), %% Integers. - ?line 5 = abs(5), - ?line 0 = abs(0), - ?line 100 = abs(-100), + 5 = abs(5), + 0 = abs(0), + 100 = abs(-100), %% The largest smallnum. OTP-3190. - ?line X = (1 bsl 27) - 1, - ?line X = abs(X), - ?line X = abs(X-1)+1, - ?line X = abs(X+1)-1, - ?line X = abs(-X), - ?line X = abs(-X-1)-1, - ?line X = abs(-X+1)+1, + X = (1 bsl 27) - 1, + X = abs(X), + X = abs(X-1)+1, + X = abs(X+1)-1, + X = abs(-X), + X = abs(-X-1)-1, + X = abs(-X+1)+1, %% Bignums. BigNum = 13984792374983749, - ?line BigNum = abs(BigNum), - ?line BigNum = abs(-BigNum), + BigNum = abs(BigNum), + BigNum = abs(-BigNum), ok. t_float(Config) when is_list(Config) -> - ?line 0.0 = float(0), - ?line 2.5 = float(2.5), - ?line 0.0 = float(0.0), - ?line -100.55 = float(-100.55), - ?line 42.0 = float(42), - ?line -100.0 = float(-100), + 0.0 = float(0), + 2.5 = float(2.5), + 0.0 = float(0.0), + -100.55 = float(-100.55), + 42.0 = float(42), + -100.0 = float(-100), %% Bignums. - ?line 4294967305.0 = float(4294967305), - ?line -4294967305.0 = float(-4294967305), + 4294967305.0 = float(4294967305), + -4294967305.0 = float(-4294967305), %% Extremly big bignums. - ?line Big = list_to_integer(lists:duplicate(2000, $1)), - ?line {'EXIT', {badarg, _}} = (catch float(Big)), + Big = list_to_integer(lists:duplicate(2000, $1)), + {'EXIT', {badarg, _}} = (catch float(Big)), %% Invalid types and lists. - ?line {'EXIT', {badarg, _}} = (catch list_to_integer(atom)), - ?line {'EXIT', {badarg, _}} = (catch list_to_integer(123)), - ?line {'EXIT', {badarg, _}} = (catch list_to_integer([$1, [$2]])), - ?line {'EXIT', {badarg, _}} = (catch list_to_integer("1.2")), - ?line {'EXIT', {badarg, _}} = (catch list_to_integer("a")), - ?line {'EXIT', {badarg, _}} = (catch list_to_integer("")), + {'EXIT', {badarg, _}} = (catch list_to_integer(atom)), + {'EXIT', {badarg, _}} = (catch list_to_integer(123)), + {'EXIT', {badarg, _}} = (catch list_to_integer([$1, [$2]])), + {'EXIT', {badarg, _}} = (catch list_to_integer("1.2")), + {'EXIT', {badarg, _}} = (catch list_to_integer("a")), + {'EXIT', {badarg, _}} = (catch list_to_integer("")), ok. %% Tests float_to_list/1. t_float_to_list(Config) when is_list(Config) -> - ?line test_ftl("0.0e+0", 0.0), - ?line test_ftl("2.5e+1", 25.0), - ?line test_ftl("2.5e+0", 2.5), - ?line test_ftl("2.5e-1", 0.25), - ?line test_ftl("-3.5e+17", -350.0e15), + test_ftl("0.0e+0", 0.0), + test_ftl("2.5e+1", 25.0), + test_ftl("2.5e+0", 2.5), + test_ftl("2.5e-1", 0.25), + test_ftl("-3.5e+17", -350.0e15), ok. test_ftl(Expect, Float) -> - %% No ?line on the next line -- we want the line number from t_float_to_list. + %% No on the next line -- we want the line number from t_float_to_list. Expect = remove_zeros(lists:reverse(float_to_list(Float)), []). %% Removes any non-significant zeros in a floating point number. @@ -148,36 +148,36 @@ remove_zeros([], Result) -> %% Tests integer_to_list/1. t_integer_to_list(Config) when is_list(Config) -> - ?line "0" = integer_to_list(0), - ?line "42" = integer_to_list(42), - ?line "-42" = integer_to_list(-42), - ?line "-42" = integer_to_list(-42), - ?line "32768" = integer_to_list(32768), - ?line "268435455" = integer_to_list(268435455), - ?line "-268435455" = integer_to_list(-268435455), - ?line "123456932798748738738" = integer_to_list(123456932798748738738), - ?line Big_List = lists:duplicate(2000, $1), - ?line Big = list_to_integer(Big_List), - ?line Big_List = integer_to_list(Big), + "0" = integer_to_list(0), + "42" = integer_to_list(42), + "-42" = integer_to_list(-42), + "-42" = integer_to_list(-42), + "32768" = integer_to_list(32768), + "268435455" = integer_to_list(268435455), + "-268435455" = integer_to_list(-268435455), + "123456932798748738738" = integer_to_list(123456932798748738738), + Big_List = lists:duplicate(2000, $1), + Big = list_to_integer(Big_List), + Big_List = integer_to_list(Big), ok. %% Tests list_to_float/1. t_list_to_float_safe(Config) when is_list(Config) -> - ?line 0.0 = list_to_float("0.0"), - ?line 0.0 = list_to_float("-0.0"), - ?line 0.5 = list_to_float("0.5"), - ?line -0.5 = list_to_float("-0.5"), - ?line 100.0 = list_to_float("1.0e2"), - ?line 127.5 = list_to_float("127.5"), - ?line -199.5 = list_to_float("-199.5"), - - ?line {'EXIT', {badarg, _}} = (catch list_to_float("0")), - ?line {'EXIT', {badarg, _}} = (catch list_to_float("0..0")), - ?line {'EXIT', {badarg, _}} = (catch list_to_float("0e12")), - ?line {'EXIT', {badarg, _}} = (catch list_to_float("--0.0")), -%% ?line {'EXIT', {badarg, _}} = (catch list_to_float("0.0e+99999999")), + 0.0 = list_to_float("0.0"), + 0.0 = list_to_float("-0.0"), + 0.5 = list_to_float("0.5"), + -0.5 = list_to_float("-0.5"), + 100.0 = list_to_float("1.0e2"), + 127.5 = list_to_float("127.5"), + -199.5 = list_to_float("-199.5"), + + {'EXIT', {badarg, _}} = (catch list_to_float("0")), + {'EXIT', {badarg, _}} = (catch list_to_float("0..0")), + {'EXIT', {badarg, _}} = (catch list_to_float("0e12")), + {'EXIT', {badarg, _}} = (catch list_to_float("--0.0")), +%% {'EXIT', {badarg, _}} = (catch list_to_float("0.0e+99999999")), ok. @@ -185,101 +185,101 @@ t_list_to_float_safe(Config) when is_list(Config) -> %% (Known to crash the Unix version of Erlang 4.4.1) t_list_to_float_risky(Config) when is_list(Config) -> - ?line Many_Ones = lists:duplicate(25000, $1), - ?line _ = list_to_float("2."++Many_Ones), - ?line {'EXIT', {badarg, _}} = (catch list_to_float("2"++Many_Ones)), + Many_Ones = lists:duplicate(25000, $1), + _ = list_to_float("2."++Many_Ones), + {'EXIT', {badarg, _}} = (catch list_to_float("2"++Many_Ones)), ok. %% Tests list_to_integer/1. t_list_to_integer(Config) when is_list(Config) -> - ?line 0 = list_to_integer("0"), - ?line 0 = list_to_integer("00"), - ?line 0 = list_to_integer("-0"), - ?line 1 = list_to_integer("1"), - ?line -1 = list_to_integer("-1"), - ?line 42 = list_to_integer("42"), - ?line -12 = list_to_integer("-12"), - ?line 32768 = list_to_integer("32768"), - ?line 268435455 = list_to_integer("268435455"), - ?line -268435455 = list_to_integer("-268435455"), + 0 = list_to_integer("0"), + 0 = list_to_integer("00"), + 0 = list_to_integer("-0"), + 1 = list_to_integer("1"), + -1 = list_to_integer("-1"), + 42 = list_to_integer("42"), + -12 = list_to_integer("-12"), + 32768 = list_to_integer("32768"), + 268435455 = list_to_integer("268435455"), + -268435455 = list_to_integer("-268435455"), %% Bignums. - ?line 123456932798748738738 = list_to_integer("123456932798748738738"), - ?line _ = list_to_integer(lists:duplicate(2000, $1)), + 123456932798748738738 = list_to_integer("123456932798748738738"), + _ = list_to_integer(lists:duplicate(2000, $1)), ok. %% Tests round/1. t_round(Config) when is_list(Config) -> - ?line 0 = round(0.0), - ?line 0 = round(0.4), - ?line 1 = round(0.5), - ?line 0 = round(-0.4), - ?line -1 = round(-0.5), - ?line 255 = round(255.3), - ?line 256 = round(255.6), - ?line -1033 = round(-1033.3), - ?line -1034 = round(-1033.6), + 0 = round(0.0), + 0 = round(0.4), + 1 = round(0.5), + 0 = round(-0.4), + -1 = round(-0.5), + 255 = round(255.3), + 256 = round(255.6), + -1033 = round(-1033.3), + -1034 = round(-1033.6), % OTP-3722: - ?line X = (1 bsl 27) - 1, - ?line MX = -X, - ?line MXm1 = -X-1, - ?line MXp1 = -X+1, - ?line F = X + 0.0, - ?line X = round(F), - ?line X = round(F+1)-1, - ?line X = round(F-1)+1, - ?line MX = round(-F), - ?line MXm1 = round(-F-1), - ?line MXp1 = round(-F+1), - - ?line X = round(F+0.1), - ?line X = round(F+1+0.1)-1, - ?line X = round(F-1+0.1)+1, - ?line MX = round(-F+0.1), - ?line MXm1 = round(-F-1+0.1), - ?line MXp1 = round(-F+1+0.1), - - ?line X = round(F-0.1), - ?line X = round(F+1-0.1)-1, - ?line X = round(F-1-0.1)+1, - ?line MX = round(-F-0.1), - ?line MXm1 = round(-F-1-0.1), - ?line MXp1 = round(-F+1-0.1), - - ?line 0.5 = abs(round(F+0.5)-(F+0.5)), - ?line 0.5 = abs(round(F-0.5)-(F-0.5)), - ?line 0.5 = abs(round(-F-0.5)-(-F-0.5)), - ?line 0.5 = abs(round(-F+0.5)-(-F+0.5)), + X = (1 bsl 27) - 1, + MX = -X, + MXm1 = -X-1, + MXp1 = -X+1, + F = X + 0.0, + X = round(F), + X = round(F+1)-1, + X = round(F-1)+1, + MX = round(-F), + MXm1 = round(-F-1), + MXp1 = round(-F+1), + + X = round(F+0.1), + X = round(F+1+0.1)-1, + X = round(F-1+0.1)+1, + MX = round(-F+0.1), + MXm1 = round(-F-1+0.1), + MXp1 = round(-F+1+0.1), + + X = round(F-0.1), + X = round(F+1-0.1)-1, + X = round(F-1-0.1)+1, + MX = round(-F-0.1), + MXm1 = round(-F-1-0.1), + MXp1 = round(-F+1-0.1), + + 0.5 = abs(round(F+0.5)-(F+0.5)), + 0.5 = abs(round(F-0.5)-(F-0.5)), + 0.5 = abs(round(-F-0.5)-(-F-0.5)), + 0.5 = abs(round(-F+0.5)-(-F+0.5)), %% Bignums. - ?line 4294967296 = round(4294967296.1), - ?line 4294967297 = round(4294967296.9), - ?line -4294967296 = -round(4294967296.1), - ?line -4294967297 = -round(4294967296.9), + 4294967296 = round(4294967296.1), + 4294967297 = round(4294967296.9), + -4294967296 = -round(4294967296.1), + -4294967297 = -round(4294967296.9), ok. t_trunc(Config) when is_list(Config) -> - ?line 0 = trunc(0.0), - ?line 5 = trunc(5.3333), - ?line -10 = trunc(-10.978987), + 0 = trunc(0.0), + 5 = trunc(5.3333), + -10 = trunc(-10.978987), % The largest smallnum, converted to float (OTP-3722): - ?line X = (1 bsl 27) - 1, - ?line F = X + 0.0, + X = (1 bsl 27) - 1, + F = X + 0.0, io:format("X = ~p/~w/~w, F = ~p/~w/~w, trunc(F) = ~p/~w/~w~n", [X, X, binary_to_list(term_to_binary(X)), F, F, binary_to_list(term_to_binary(F)), trunc(F), trunc(F), binary_to_list(term_to_binary(trunc(F)))]), - ?line X = trunc(F), - ?line X = trunc(F+1)-1, - ?line X = trunc(F-1)+1, - ?line X = -trunc(-F), - ?line X = -trunc(-F-1)-1, - ?line X = -trunc(-F+1)+1, + X = trunc(F), + X = trunc(F+1)-1, + X = trunc(F-1)+1, + X = -trunc(-F), + X = -trunc(-F-1)-1, + X = -trunc(-F+1)+1, %% Bignums. - ?line 4294967305 = trunc(4294967305.7), - ?line -4294967305 = trunc(-4294967305.7), + 4294967305 = trunc(4294967305.7), + -4294967305 = trunc(-4294967305.7), ok. diff --git a/lib/compiler/test/receive_SUITE.erl b/lib/compiler/test/receive_SUITE.erl index fef29ab06d..8d2c78aae2 100644 --- a/lib/compiler/test/receive_SUITE.erl +++ b/lib/compiler/test/receive_SUITE.erl @@ -30,15 +30,14 @@ -include_lib("common_test/include/ct.hrl"). init_per_testcase(_Case, Config) -> - ?line Dog = test_server:timetrap(test_server:minutes(2)), - [{watchdog, Dog}|Config]. + Config. -end_per_testcase(_Case, Config) -> - Dog=?config(watchdog, Config), - test_server:timetrap_cancel(Dog), +end_per_testcase(_Case, _Config) -> ok. -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,2}}]. all() -> test_lib:recompile(?MODULE), @@ -64,21 +63,21 @@ end_per_group(_GroupName, Config) -> -record(state, {ena = true}). recv(Config) when is_list(Config) -> - ?line Pid = spawn_link(fun() -> loop(#state{}) end), + Pid = spawn_link(fun() -> loop(#state{}) end), Self = self(), - ?line Pid ! {Self,test}, + Pid ! {Self,test}, receive {ok,test} -> ok; {error,Other} -> io:format("Got unpexected ~p", [Other]), - ?line ?t:fail() + ct:fail(unexpected) after 10000 -> - ?line ?t:fail(no_answer) + ct:fail(no_answer) end, receive X -> io:format("Unexpected extra message: ~p", [X]), - ?line ?t:fail() + ct:fail(unexpected) after 10 -> ok end, @@ -116,9 +115,9 @@ coverage(Config) when is_list(Config) -> self() ! 17, self() ! 19, - ?line 59 = tuple_to_values(infinity, x), - ?line 61 = tuple_to_values(999999, x), - ?line 0 = tuple_to_values(1, x), + 59 = tuple_to_values(infinity, x), + 61 = tuple_to_values(999999, x), + 0 = tuple_to_values(1, x), ok. receive_all() -> @@ -188,8 +187,8 @@ ref_opt(Config) when is_list(Config) -> end. ref_opt_1(Config) -> - DataDir = ?config(data_dir, Config), - PrivDir = ?config(priv_dir, Config), + DataDir = proplists:get_value(data_dir, Config), + PrivDir = proplists:get_value(priv_dir, Config), Sources = filelib:wildcard(filename:join([DataDir,"ref_opt","*.{erl,S}"])), test_lib:p_run(fun(Src) -> do_ref_opt(Src, PrivDir) @@ -257,9 +256,9 @@ cover_recv_instructions() -> export(Config) when is_list(Config) -> Ref = make_ref(), - ?line self() ! {result,Ref,42}, - ?line 42 = export_1(Ref), - ?line {error,timeout} = export_1(Ref), + self() ! {result,Ref,42}, + 42 = export_1(Ref), + {error,timeout} = export_1(Ref), ok. export_1(Reference) -> diff --git a/lib/compiler/test/record_SUITE.erl b/lib/compiler/test/record_SUITE.erl index 48a2a9f5df..680bd38317 100644 --- a/lib/compiler/test/record_SUITE.erl +++ b/lib/compiler/test/record_SUITE.erl @@ -31,15 +31,14 @@ nested_access/1,coverage/1]). init_per_testcase(_Case, Config) -> - ?line Dog = test_server:timetrap(test_server:minutes(2)), - [{watchdog,Dog}|Config]. + Config. -end_per_testcase(_Case, Config) -> - Dog = ?config(watchdog, Config), - test_server:timetrap_cancel(Dog), +end_per_testcase(_Case, _Config) -> ok. -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,2}}]. all() -> test_lib:recompile(?MODULE), @@ -71,18 +70,18 @@ end_per_group(_GroupName, Config) -> errors(Config) when is_list(Config) -> Foo = #foo{a=1,b=2,c=3,d=4}, - ?line #foo{a=19,b=42,c=3,d=4} = update_foo(Foo, 19, 42), - - ?line {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19)), - ?line {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19, 35)), - ?line {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19, 35, 17)), - ?line {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19, 35, 17, 42)), - - ?line {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19)), - ?line {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19, 35)), - ?line {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19, 35, 17)), - ?line {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19, 35, 17, 42)), - ?line {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19, + #foo{a=19,b=42,c=3,d=4} = update_foo(Foo, 19, 42), + + {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19)), + {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19, 35)), + {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19, 35, 17)), + {'EXIT',{{badrecord,bar},_}} = (catch update_foo_bar(Foo, 19, 35, 17, 42)), + + {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19)), + {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19, 35)), + {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19, 35, 17)), + {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19, 35, 17, 42)), + {'EXIT',{{badrecord,barf},_}} = (catch update_foo_barf(Foo, 19, 35, 17, 42, -2)), ok. @@ -118,72 +117,72 @@ update_foo_barf(#foo{}=R, A, _B, C, D, E) -> R#barf{a=A,b=A,c=C,d=D,e=E}. --define(TrueGuard(Expr), if Expr -> ok; true -> ?t:fail() end). --define(FalseGuard(Expr), if Expr -> ?t:fail(); true -> ok end). +-define(TrueGuard(Expr), if Expr -> ok; true -> ct:fail(failed) end). +-define(FalseGuard(Expr), if Expr -> ct:fail(failed); true -> ok end). record_test_2(Config) when is_list(Config) -> - ?line true = is_record(#foo{}, foo), - ?line false = is_record(#foo{}, barf), - ?line false = is_record({foo}, foo), + true = is_record(#foo{}, foo), + false = is_record(#foo{}, barf), + false = is_record({foo}, foo), - ?line true = erlang:is_record(#foo{}, foo), - ?line false = erlang:is_record(#foo{}, barf), - ?line false = erlang:is_record({foo}, foo), + true = erlang:is_record(#foo{}, foo), + false = erlang:is_record(#foo{}, barf), + false = erlang:is_record({foo}, foo), - ?line false = is_record([], foo), - ?line false = is_record(Config, foo), + false = is_record([], foo), + false = is_record(Config, foo), - ?line ?TrueGuard(is_record(#foo{}, foo)), - ?line ?FalseGuard(is_record(#foo{}, barf)), - ?line ?FalseGuard(is_record({foo}, foo)), + ?TrueGuard(is_record(#foo{}, foo)), + ?FalseGuard(is_record(#foo{}, barf)), + ?FalseGuard(is_record({foo}, foo)), - ?line ?TrueGuard(erlang:is_record(#foo{}, foo)), - ?line ?FalseGuard(erlang:is_record(#foo{}, barf)), - ?line ?FalseGuard(erlang:is_record({foo}, foo)), + ?TrueGuard(erlang:is_record(#foo{}, foo)), + ?FalseGuard(erlang:is_record(#foo{}, barf)), + ?FalseGuard(erlang:is_record({foo}, foo)), - ?line ?FalseGuard(is_record([], foo)), - ?line ?FalseGuard(is_record(Config, foo)), + ?FalseGuard(is_record([], foo)), + ?FalseGuard(is_record(Config, foo)), %% 'not is_record/2' to test guard optimization. - ?line ?FalseGuard(not is_record(#foo{}, foo)), - ?line ?TrueGuard(not is_record(#foo{}, barf)), - ?line ?TrueGuard(not is_record({foo}, foo)), + ?FalseGuard(not is_record(#foo{}, foo)), + ?TrueGuard(not is_record(#foo{}, barf)), + ?TrueGuard(not is_record({foo}, foo)), - ?line ?FalseGuard(not erlang:is_record(#foo{}, foo)), - ?line ?TrueGuard(not erlang:is_record(#foo{}, barf)), - ?line ?TrueGuard(not erlang:is_record({foo}, foo)), + ?FalseGuard(not erlang:is_record(#foo{}, foo)), + ?TrueGuard(not erlang:is_record(#foo{}, barf)), + ?TrueGuard(not erlang:is_record({foo}, foo)), Foo = id(#foo{}), - ?line ?FalseGuard(not erlang:is_record(Foo, foo)), - ?line ?TrueGuard(not erlang:is_record(Foo, barf)), + ?FalseGuard(not erlang:is_record(Foo, foo)), + ?TrueGuard(not erlang:is_record(Foo, barf)), - ?line ?TrueGuard(not is_record(Config, foo)), + ?TrueGuard(not is_record(Config, foo)), - ?line ?TrueGuard(not is_record(a, foo)), - ?line ?TrueGuard(not is_record([], foo)), + ?TrueGuard(not is_record(a, foo)), + ?TrueGuard(not is_record([], foo)), %% Pass non-literal first argument. - ?line true = is_record(id(#foo{}), foo), - ?line false = is_record(id(#foo{}), barf), - ?line false = is_record(id({foo}), foo), + true = is_record(id(#foo{}), foo), + false = is_record(id(#foo{}), barf), + false = is_record(id({foo}), foo), - ?line true = erlang:is_record(id(#foo{}), foo), - ?line false = erlang:is_record(id(#foo{}), barf), - ?line false = erlang:is_record(id({foo}), foo), + true = erlang:is_record(id(#foo{}), foo), + false = erlang:is_record(id(#foo{}), barf), + false = erlang:is_record(id({foo}), foo), NoRec1 = id(blurf), NoRec2 = id([]), - ?line ?TrueGuard(not is_record(NoRec1, foo)), - ?line ?TrueGuard(not is_record(NoRec2, foo)), + ?TrueGuard(not is_record(NoRec1, foo)), + ?TrueGuard(not is_record(NoRec2, foo)), %% The optimizer attempts to move expressions to guards, %% but it must not move an is_record/2 call that is not %% allowed in a guard in the first place. - ?line ok = case is_record(id({a}), id(a)) of + ok = case is_record(id({a}), id(a)) of true -> ok; false -> error end, @@ -191,61 +190,61 @@ record_test_2(Config) when is_list(Config) -> %% Force the use of guard bifs by using the 'xor' operation. False = id(false), - ?line ?TrueGuard(is_record(#foo{}, foo) xor False), - ?line ?FalseGuard(is_record(#foo{}, barf) xor False), - ?line ?FalseGuard(is_record({foo}, foo) xor False ), + ?TrueGuard(is_record(#foo{}, foo) xor False), + ?FalseGuard(is_record(#foo{}, barf) xor False), + ?FalseGuard(is_record({foo}, foo) xor False ), - ?line ?TrueGuard(is_record(Foo, foo) xor False), - ?line ?FalseGuard(is_record(Foo, barf) xor False), + ?TrueGuard(is_record(Foo, foo) xor False), + ?FalseGuard(is_record(Foo, barf) xor False), %% Implicit guards by using a list comprehension. List = id([1,#foo{a=2},3,#bar{d=4},5,#foo{a=6},7]), - ?line [#foo{a=2},#foo{a=6}] = [X || X <- List, is_record(X, foo)], - ?line [#bar{d=4}] = [X || X <- List, is_record(X, bar)], - ?line [1,#foo{a=2},3,5,#foo{a=6},7] = + [#foo{a=2},#foo{a=6}] = [X || X <- List, is_record(X, foo)], + [#bar{d=4}] = [X || X <- List, is_record(X, bar)], + [1,#foo{a=2},3,5,#foo{a=6},7] = [X || X <- List, not is_record(X, bar)], - ?line [1,3,5,7] = + [1,3,5,7] = [X || X <- List, ((not is_record(X, bar)) and (not is_record(X, foo)))], - ?line [#foo{a=2},#bar{d=4},#foo{a=6}] = + [#foo{a=2},#bar{d=4},#foo{a=6}] = [X || X <- List, ((is_record(X, bar)) or (is_record(X, foo)))], - ?line [1,3,#bar{d=4}] = + [1,3,#bar{d=4}] = [X || X <- List, ((is_record(X, bar)) or (X < 5))], - ?line MyList = [#foo{a=3},x,[],{a,b}], - ?line [#foo{a=3}] = [X || X <- MyList, is_record(X, foo)], - ?line [x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo)], - ?line [#foo{a=3}] = [X || X <- MyList, begin is_record(X, foo) end], - ?line [x,[],{a,b}] = [X || X <- MyList, begin not is_record(X, foo) end], - ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, is_record(X, foo) or - not is_binary(X)], - ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo) or - not is_binary(X)], - ?line [#foo{a=3}] = [X || X <- MyList, is_record(X, foo) or is_reference(X)], - ?line [x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo) or - is_reference(X)], - ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, - begin is_record(X, foo) or - not is_binary(X) end], - ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, - begin not is_record(X, foo) or - not is_binary(X) end], - ?line [#foo{a=3}] = [X || X <- MyList, - begin is_record(X, foo) or is_reference(X) end], - ?line [x,[],{a,b}] = [X || X <- MyList, - begin not is_record(X, foo) or - is_reference(X) end], + MyList = [#foo{a=3},x,[],{a,b}], + [#foo{a=3}] = [X || X <- MyList, is_record(X, foo)], + [x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo)], + [#foo{a=3}] = [X || X <- MyList, begin is_record(X, foo) end], + [x,[],{a,b}] = [X || X <- MyList, begin not is_record(X, foo) end], + [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, is_record(X, foo) or + not is_binary(X)], + [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo) or + not is_binary(X)], + [#foo{a=3}] = [X || X <- MyList, is_record(X, foo) or is_reference(X)], + [x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo) or + is_reference(X)], + [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, + begin is_record(X, foo) or + not is_binary(X) end], + [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, + begin not is_record(X, foo) or + not is_binary(X) end], + [#foo{a=3}] = [X || X <- MyList, + begin is_record(X, foo) or is_reference(X) end], + [x,[],{a,b}] = [X || X <- MyList, + begin not is_record(X, foo) or + is_reference(X) end], %% Call is_record/2 with illegal arguments. - ?line [] = [X || X <- [], is_record(t, id(X))], - ?line {'EXIT',{badarg,_}} = (catch [X || X <- [1], is_record(t, id(X))]), + [] = [X || X <- [], is_record(t, id(X))], + {'EXIT',{badarg,_}} = (catch [X || X <- [1], is_record(t, id(X))]), %% Update several fields with a string literal. - ?line #barf{} = Barf0 = id(#barf{}), - ?line Barf = update_barf(Barf0), - ?line #barf{a="abc",b=1} = id(Barf), + #barf{} = Barf0 = id(#barf{}), + Barf = update_barf(Barf0), + #barf{a="abc",b=1} = id(Barf), %% Test optimization of is_record/3. false = case id({a,b}) of @@ -258,125 +257,125 @@ record_test_2(Config) when is_list(Config) -> ok. record_test_3(Config) when is_list(Config) -> - ?line true = is_record(#foo{}, foo, 5), - ?line false = is_record(#foo{}, barf, 5), - ?line false = is_record(#foo{}, barf, 6), - ?line false = is_record({foo}, foo, 5), + true = is_record(#foo{}, foo, 5), + false = is_record(#foo{}, barf, 5), + false = is_record(#foo{}, barf, 6), + false = is_record({foo}, foo, 5), - ?line true = erlang:is_record(#foo{}, foo, 5), - ?line false = erlang:is_record(#foo{}, barf, 5), - ?line false = erlang:is_record({foo}, foo, 5), + true = erlang:is_record(#foo{}, foo, 5), + false = erlang:is_record(#foo{}, barf, 5), + false = erlang:is_record({foo}, foo, 5), - ?line false = is_record([], foo), - ?line false = is_record(Config, foo), + false = is_record([], foo), + false = is_record(Config, foo), - ?line ?TrueGuard(is_record(#foo{}, foo, 5)), - ?line ?FalseGuard(is_record(#foo{}, barf, 5)), - ?line ?FalseGuard(is_record(#foo{}, barf, 6)), - ?line ?FalseGuard(is_record({foo}, foo, 5)), + ?TrueGuard(is_record(#foo{}, foo, 5)), + ?FalseGuard(is_record(#foo{}, barf, 5)), + ?FalseGuard(is_record(#foo{}, barf, 6)), + ?FalseGuard(is_record({foo}, foo, 5)), - ?line ?TrueGuard(erlang:is_record(#foo{}, foo, 5)), - ?line ?FalseGuard(erlang:is_record(#foo{}, barf, 5)), - ?line ?FalseGuard(erlang:is_record(#foo{}, barf, 6)), - ?line ?FalseGuard(erlang:is_record({foo}, foo, 5)), + ?TrueGuard(erlang:is_record(#foo{}, foo, 5)), + ?FalseGuard(erlang:is_record(#foo{}, barf, 5)), + ?FalseGuard(erlang:is_record(#foo{}, barf, 6)), + ?FalseGuard(erlang:is_record({foo}, foo, 5)), - ?line ?FalseGuard(is_record([], foo, 5)), - ?line ?FalseGuard(is_record(Config, foo, 5)), + ?FalseGuard(is_record([], foo, 5)), + ?FalseGuard(is_record(Config, foo, 5)), %% 'not is_record/2' to test guard optimization. - ?line ?FalseGuard(not is_record(#foo{}, foo, 5)), - ?line ?TrueGuard(not is_record(#foo{}, barf, 6)), - ?line ?TrueGuard(not is_record({foo}, foo, 5)), + ?FalseGuard(not is_record(#foo{}, foo, 5)), + ?TrueGuard(not is_record(#foo{}, barf, 6)), + ?TrueGuard(not is_record({foo}, foo, 5)), - ?line ?FalseGuard(not erlang:is_record(#foo{}, foo, 5)), - ?line ?TrueGuard(not erlang:is_record(#foo{}, barf, 5)), - ?line ?TrueGuard(not erlang:is_record({foo}, foo, 5)), + ?FalseGuard(not erlang:is_record(#foo{}, foo, 5)), + ?TrueGuard(not erlang:is_record(#foo{}, barf, 5)), + ?TrueGuard(not erlang:is_record({foo}, foo, 5)), Foo = id(#foo{}), - ?line ?FalseGuard(not erlang:is_record(Foo, foo, 5)), - ?line ?TrueGuard(not erlang:is_record(Foo, barf, 6)), + ?FalseGuard(not erlang:is_record(Foo, foo, 5)), + ?TrueGuard(not erlang:is_record(Foo, barf, 6)), - ?line ?TrueGuard(not is_record(Config, foo, 5)), + ?TrueGuard(not is_record(Config, foo, 5)), - ?line ?TrueGuard(not is_record(a, foo, 5)), - ?line ?TrueGuard(not is_record([], foo, 5)), + ?TrueGuard(not is_record(a, foo, 5)), + ?TrueGuard(not is_record([], foo, 5)), %% Pass non-literal first argument. - ?line true = is_record(id(#foo{}), foo, 5), - ?line false = is_record(id(#foo{}), barf, 6), - ?line false = is_record(id({foo}), foo, 5), + true = is_record(id(#foo{}), foo, 5), + false = is_record(id(#foo{}), barf, 6), + false = is_record(id({foo}), foo, 5), - ?line true = erlang:is_record(id(#foo{}), foo, 5), - ?line false = erlang:is_record(id(#foo{}), barf, 6), - ?line false = erlang:is_record(id({foo}), foo, 5), + true = erlang:is_record(id(#foo{}), foo, 5), + false = erlang:is_record(id(#foo{}), barf, 6), + false = erlang:is_record(id({foo}), foo, 5), NoRec1 = id(blurf), NoRec2 = id([]), - ?line ?TrueGuard(not is_record(NoRec1, foo, 5)), - ?line ?TrueGuard(not is_record(NoRec2, foo, 5)), + ?TrueGuard(not is_record(NoRec1, foo, 5)), + ?TrueGuard(not is_record(NoRec2, foo, 5)), %% Force the use of guard bifs by using the 'xor' operation. False = id(false), - ?line ?TrueGuard(is_record(#foo{}, foo, 5) xor False), - ?line ?FalseGuard(is_record(#foo{}, barf, 6) xor False), - ?line ?FalseGuard(is_record({foo}, foo, 5) xor False ), + ?TrueGuard(is_record(#foo{}, foo, 5) xor False), + ?FalseGuard(is_record(#foo{}, barf, 6) xor False), + ?FalseGuard(is_record({foo}, foo, 5) xor False ), - ?line ?TrueGuard(is_record(Foo, foo, 5) xor False), - ?line ?FalseGuard(is_record(Foo, barf, 6) xor False), + ?TrueGuard(is_record(Foo, foo, 5) xor False), + ?FalseGuard(is_record(Foo, barf, 6) xor False), %% Implicit guards by using a list comprehension. List = id([1,#foo{a=2},3,#bar{d=4},5,#foo{a=6},7]), - ?line [#foo{a=2},#foo{a=6}] = [X || X <- List, is_record(X, foo, 5)], - ?line [#bar{d=4}] = [X || X <- List, is_record(X, bar, 5)], - ?line [1,#foo{a=2},3,5,#foo{a=6},7] = + [#foo{a=2},#foo{a=6}] = [X || X <- List, is_record(X, foo, 5)], + [#bar{d=4}] = [X || X <- List, is_record(X, bar, 5)], + [1,#foo{a=2},3,5,#foo{a=6},7] = [X || X <- List, not is_record(X, bar, 5)], - ?line [1,3,5,7] = + [1,3,5,7] = [X || X <- List, ((not is_record(X, bar, 5)) and (not is_record(X, foo, 5)))], - ?line [#foo{a=2},#bar{d=4},#foo{a=6}] = + [#foo{a=2},#bar{d=4},#foo{a=6}] = [X || X <- List, ((is_record(X, bar, 5)) or (is_record(X, foo, 5)))], - ?line [1,3,#bar{d=4}] = + [1,3,#bar{d=4}] = [X || X <- List, ((is_record(X, bar, 5)) or (X < 5))], - ?line MyList = [#foo{a=3},x,[],{a,b}], - ?line [#foo{a=3}] = [X || X <- MyList, is_record(X, foo, 5)], - ?line [x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo, 5)], - ?line [#foo{a=3}] = [X || X <- MyList, begin is_record(X, foo, 5) end], - ?line [x,[],{a,b}] = [X || X <- MyList, begin not is_record(X, foo, 5) end], - ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, is_record(X, foo, 5) or - not is_binary(X)], - ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo, 5) or - not is_binary(X)], - ?line [#foo{a=3}] = [X || X <- MyList, is_record(X, foo) or is_reference(X)], - ?line [x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo) or - is_reference(X)], - ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, - begin is_record(X, foo, 5) or - not is_binary(X) end], - ?line [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, - begin not is_record(X, foo, 5) or - not is_binary(X) end], - ?line [#foo{a=3}] = [X || X <- MyList, - begin is_record(X, foo, 5) or is_reference(X) end], - ?line [x,[],{a,b}] = [X || X <- MyList, - begin not is_record(X, foo, 5) or - is_reference(X) end], + MyList = [#foo{a=3},x,[],{a,b}], + [#foo{a=3}] = [X || X <- MyList, is_record(X, foo, 5)], + [x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo, 5)], + [#foo{a=3}] = [X || X <- MyList, begin is_record(X, foo, 5) end], + [x,[],{a,b}] = [X || X <- MyList, begin not is_record(X, foo, 5) end], + [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, is_record(X, foo, 5) or + not is_binary(X)], + [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo, 5) or + not is_binary(X)], + [#foo{a=3}] = [X || X <- MyList, is_record(X, foo) or is_reference(X)], + [x,[],{a,b}] = [X || X <- MyList, not is_record(X, foo) or + is_reference(X)], + [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, + begin is_record(X, foo, 5) or + not is_binary(X) end], + [#foo{a=3},x,[],{a,b}] = [X || X <- MyList, + begin not is_record(X, foo, 5) or + not is_binary(X) end], + [#foo{a=3}] = [X || X <- MyList, + begin is_record(X, foo, 5) or is_reference(X) end], + [x,[],{a,b}] = [X || X <- MyList, + begin not is_record(X, foo, 5) or + is_reference(X) end], %% Update several fields with a string literal. - ?line #barf{} = Barf0 = id(#barf{}), - ?line Barf = update_barf(Barf0), - ?line #barf{a="abc",b=1} = id(Barf), + #barf{} = Barf0 = id(#barf{}), + Barf = update_barf(Barf0), + #barf{a="abc",b=1} = id(Barf), %% Non-literal arguments. - ?line true = is_record(id(#barf{}), id(barf), id(6)), - ?line false = is_record(id(#barf{}), id(barf), id(42)), - ?line false = is_record(id(#barf{}), id(foo), id(6)), + true = is_record(id(#barf{}), id(barf), id(6)), + false = is_record(id(#barf{}), id(barf), id(42)), + false = is_record(id(#barf{}), id(foo), id(6)), Rec = id(#barf{}), Good = id(barf), @@ -389,15 +388,15 @@ record_test_3(Config) when is_list(Config) -> ok. record_access_in_guards(Config) when is_list(Config) -> - ?line Priv = ?config(priv_dir, Config), - ?line file:set_cwd(test_lib:get_data_dir(Config)), - ?line Opts0 = [{outdir,Priv},report_errors|test_lib:opt_opts(?MODULE)], + Priv = proplists:get_value(priv_dir, Config), + file:set_cwd(test_lib:get_data_dir(Config)), + Opts0 = [{outdir,Priv},report_errors|test_lib:opt_opts(?MODULE)], M = record_access_in_guards, Opts = [strict_record_tests|Opts0], - ?line io:format("Options: ~p\n", [Opts]), - ?line {ok,M} = c:c(M, Opts), - ?line ok = M:t(), + io:format("Options: ~p\n", [Opts]), + {ok,M} = c:c(M, Opts), + ok = M:t(), ok. @@ -487,19 +486,19 @@ update_barf(R) -> R#barf{a="abc",b=1}. eval_once(Config) when is_list(Config) -> - ?line once(fun(GetRec) -> + once(fun(GetRec) -> true = erlang:is_record(GetRec(), foo) end, #foo{}), - ?line once(fun(GetRec) -> + once(fun(GetRec) -> (GetRec())#foo{a=1} end, #foo{}), - ?line once(fun(GetRec) -> + once(fun(GetRec) -> (GetRec())#foo{a=1,b=2} end, #foo{}), - ?line once(fun(GetRec) -> + once(fun(GetRec) -> (GetRec())#foo{a=1,b=2,c=3} end, #foo{}), - ?line once(fun(GetRec) -> + once(fun(GetRec) -> (GetRec())#foo{a=1,b=2,c=3,d=4} end, #foo{}), ok. @@ -515,7 +514,7 @@ once(Test, Record) -> 1 -> ok; N -> io:format("Evaluated ~w times\n", [N]), - ?t:fail() + ct:fail(more_than_once) end, Result. @@ -571,21 +570,21 @@ nested_access(Config) when is_list(Config) -> N0 = #nrec0{}, N1 = #nrec1{}, N2 = #nrec2{}, - ?line <<"nested0">> = N0#nrec0.name, - ?line <<"nested1">> = N1#nrec1.name, - ?line <<"nested2">> = N2#nrec2.name, - ?line <<"nested0">> = N1#nrec1.nrec0#nrec0.name, - ?line <<"nested0">> = N2#nrec2.nrec1#nrec1.nrec0#nrec0.name, - ?line <<"nested1">> = N2#nrec2.nrec1#nrec1.name, - ?line <<"nested0">> = ((N2#nrec2.nrec1)#nrec1.nrec0)#nrec0.name, + <<"nested0">> = N0#nrec0.name, + <<"nested1">> = N1#nrec1.name, + <<"nested2">> = N2#nrec2.name, + <<"nested0">> = N1#nrec1.nrec0#nrec0.name, + <<"nested0">> = N2#nrec2.nrec1#nrec1.nrec0#nrec0.name, + <<"nested1">> = N2#nrec2.nrec1#nrec1.name, + <<"nested0">> = ((N2#nrec2.nrec1)#nrec1.nrec0)#nrec0.name, N1a = N2#nrec2.nrec1#nrec1{name = <<"nested1a">>}, - ?line <<"nested1a">> = N1a#nrec1.name, + <<"nested1a">> = N1a#nrec1.name, N2a = N2#nrec2.nrec1#nrec1.nrec0#nrec0{name = <<"nested0a">>}, N2b = ((N2#nrec2.nrec1)#nrec1.nrec0)#nrec0{name = <<"nested0a">>}, - ?line <<"nested0a">> = N2a#nrec0.name, - ?line N2a = N2b, + <<"nested0a">> = N2a#nrec0.name, + N2a = N2b, ok. -record(rr, {a,b,c}). diff --git a/lib/compiler/test/regressions_SUITE.erl b/lib/compiler/test/regressions_SUITE.erl index a8caa34c60..3fd4645529 100644 --- a/lib/compiler/test/regressions_SUITE.erl +++ b/lib/compiler/test/regressions_SUITE.erl @@ -21,26 +21,23 @@ -module(regressions_SUITE). -include_lib("common_test/include/ct.hrl"). --export([all/0, groups/0, init_per_testcase/2,end_per_testcase/2]). - +-export([all/0,groups/0,init_per_testcase/2,end_per_testcase/2,suite/0]). -export([maps/1]). groups() -> [{p,test_lib:parallel(), [maps]}]. -% Default timetrap timeout (set in init_per_testcase). --define(default_timeout, ?t:minutes(2)). - init_per_testcase(_Case, Config) -> - ?line Dog = ?t:timetrap(?default_timeout), - [{watchdog, Dog} | Config]. + Config. -end_per_testcase(_Case, Config) -> - Dog = ?config(watchdog, Config), - test_server:timetrap_cancel(Dog), +end_per_testcase(_Case, _Config) -> ok. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,2}}]. + all() -> test_lib:recompile(?MODULE), [{group,p}]. @@ -62,7 +59,8 @@ run(Config, Tests) -> io:format("Compiling test for: ~w~n", [N]), case catch run_test(Config, P) of {'EXIT', Reason} -> - ?t:format("~nTest ~p failed.~nReason: ~p~n", [N, Reason]), + io:format("~nTest ~p failed.~nReason: ~p~n", + [N, Reason]), fail(); _ -> ok end @@ -73,7 +71,7 @@ run(Config, Tests) -> run_test(Conf, Test0) -> Module = "regressions_"++test_lib:uniq(), Filename = Module ++ ".erl", - DataDir = ?config(priv_dir, Conf), + DataDir = proplists:get_value(priv_dir, Conf), Test = ["-module(", Module, "). ", Test0], File = filename:join(DataDir, Filename), Def = [binary,export_all,return], @@ -94,5 +92,4 @@ run_test(Conf, Test0) -> ok. fail() -> - io:format("failed~n"), - ?t:fail(). + ct:fail(failed). diff --git a/lib/compiler/test/test_lib.erl b/lib/compiler/test/test_lib.erl index e4b6a2fa9c..3ca93fb021 100644 --- a/lib/compiler/test/test_lib.erl +++ b/lib/compiler/test/test_lib.erl @@ -52,7 +52,7 @@ smoke_disasm(File) when is_list(File) -> %% be slower than running them sequentially. parallel() -> - case ?t:is_cover() orelse erlang:system_info(schedulers) =:= 1 of + case test_server:is_cover() orelse erlang:system_info(schedulers) =:= 1 of true -> []; false -> [parallel] end. @@ -66,7 +66,7 @@ uniq() -> opt_opts(Mod) -> Comp = Mod:module_info(compile), - {value,{options,Opts}} = lists:keysearch(options, 1, Comp), + {options,Opts} = lists:keyfind(options, 1, Comp), lists:filter(fun(no_copt) -> true; (no_postopt) -> true; (no_float_opt) -> true; @@ -85,7 +85,7 @@ opt_opts(Mod) -> %% This function retrieves the path to the original data directory. get_data_dir(Config) -> - Data0 = ?config(data_dir, Config), + Data0 = proplists:get_value(data_dir, Config), Opts = [{return,list}], Data1 = re:replace(Data0, "_no_opt_SUITE", "_SUITE", Opts), Data = re:replace(Data1, "_post_opt_SUITE", "_SUITE", Opts), @@ -96,7 +96,7 @@ get_data_dir(Config) -> p_run(Test, List) -> S = erlang:system_info(schedulers), - N = case ?t:is_cover() of + N = case test_server:is_cover() of false -> S + 1; true -> @@ -118,7 +118,8 @@ p_run_loop(_, [], _, [], Errors, Ws) -> 1 -> {comment,"1 warning"}; N -> {comment,integer_to_list(N)++" warnings"} end; - N -> ?t:fail({N,errors}) + N -> + ct:fail({N,errors}) end; p_run_loop(Test, [H|T], N, Refs, Errors, Ws) when length(Refs) < N -> {_,Ref} = erlang:spawn_monitor(fun() -> exit(Test(H)) end), diff --git a/lib/compiler/test/trycatch_SUITE.erl b/lib/compiler/test/trycatch_SUITE.erl index b316776f50..82e3c86649 100644 --- a/lib/compiler/test/trycatch_SUITE.erl +++ b/lib/compiler/test/trycatch_SUITE.erl @@ -60,32 +60,32 @@ end_per_group(_GroupName, Config) -> basic(Conf) when is_list(Conf) -> - ?line 2 = + 2 = try my_div(4, 2) catch Class:Reason -> {Class,Reason} end, - ?line error = + error = try my_div(1, 0) catch error:badarith -> error end, - ?line error = + error = try 1.0 / zero() catch error:badarith -> error end, - ?line ok = + ok = try my_add(53, atom) catch error:badarith -> ok end, - ?line exit_nisse = + exit_nisse = try exit(nisse) catch exit:nisse -> exit_nisse end, - ?line ok = + ok = try throw(kalle) catch kalle -> ok @@ -94,27 +94,27 @@ basic(Conf) when is_list(Conf) -> %% Try some stuff where the compiler will optimize away the try. V = id({a,variable}), - ?line V = try V catch nisse -> error end, - ?line 42 = try 42 catch nisse -> error end, - ?line [V] = try [V] catch nisse -> error end, - ?line {ok,V} = try {ok,V} catch nisse -> error end, + V = try V catch nisse -> error end, + 42 = try 42 catch nisse -> error end, + [V] = try [V] catch nisse -> error end, + {ok,V} = try {ok,V} catch nisse -> error end, %% Same idea, but use an after too. - ?line V = try V catch nisse -> error after after_call() end, - ?line after_clean(), - ?line 42 = try 42 after after_call() end, - ?line after_clean(), - ?line [V] = try [V] catch nisse -> error after after_call() end, - ?line after_clean(), - ?line {ok,V} = try {ok,V} after after_call() end, + V = try V catch nisse -> error after after_call() end, + after_clean(), + 42 = try 42 after after_call() end, + after_clean(), + [V] = try [V] catch nisse -> error after after_call() end, + after_clean(), + {ok,V} = try {ok,V} after after_call() end, %% Try/of - ?line ok = try V of - {a,variable} -> ok - catch nisse -> erro - end, - + ok = try V of + {a,variable} -> ok + catch nisse -> erro + end, + ok. after_call() -> @@ -125,24 +125,24 @@ after_clean() -> lean_throw(Conf) when is_list(Conf) -> - ?line {throw,kalle} = + {throw,kalle} = try throw(kalle) catch Kalle -> {throw,Kalle} end, - ?line {exit,kalle} = + {exit,kalle} = try exit(kalle) catch Throw1 -> {throw,Throw1}; exit:Reason1 -> {exit,Reason1} end, - ?line {exit,kalle} = + {exit,kalle} = try exit(kalle) catch exit:Reason2 -> {exit,Reason2}; Throw2 -> {throw,Throw2} end, - ?line {exit,kalle} = + {exit,kalle} = try try exit(kalle) catch Throw3 -> {throw,Throw3} @@ -155,25 +155,25 @@ lean_throw(Conf) when is_list(Conf) -> try_of(Conf) when is_list(Conf) -> - ?line {ok,{some,content}} = + {ok,{some,content}} = try_of_1({value,{good,{some,content}}}), - ?line {error,[other,content]} = + {error,[other,content]} = try_of_1({value,{bad,[other,content]}}), - ?line {caught,{exit,{ex,it,[reason]}}} = + {caught,{exit,{ex,it,[reason]}}} = try_of_1({exit,{ex,it,[reason]}}), - ?line {caught,{throw,[term,{in,a,{tuple}}]}} = + {caught,{throw,[term,{in,a,{tuple}}]}} = try_of_1({throw,[term,{in,a,{tuple}}]}), - ?line {caught,{error,[bad,arg]}} = + {caught,{error,[bad,arg]}} = try_of_1({error,[bad,arg]}), - ?line {caught,{error,badarith}} = + {caught,{error,badarith}} = try_of_1({'div',{1,0}}), - ?line {caught,{error,badarith}} = + {caught,{error,badarith}} = try_of_1({'add',{a,0}}), - ?line {caught,{error,badarg}} = + {caught,{error,badarg}} = try_of_1({'abs',x}), - ?line {caught,{error,function_clause}} = + {caught,{error,function_clause}} = try_of_1(illegal), - ?line {error,{try_clause,{some,other_garbage}}} = + {error,{try_clause,{some,other_garbage}}} = try try_of_1({value,{some,other_garbage}}) catch error:Reason -> {error,Reason} end, @@ -191,29 +191,29 @@ try_of_1(X) -> try_after(Conf) when is_list(Conf) -> - ?line {{ok,[some,value],undefined},finalized} = + {{ok,[some,value],undefined},finalized} = try_after_1({value,{ok,[some,value]}},finalized), - ?line {{error,badarith,undefined},finalized} = + {{error,badarith,undefined},finalized} = try_after_1({'div',{1,0}},finalized), - ?line {{error,badarith,undefined},finalized} = + {{error,badarith,undefined},finalized} = try_after_1({'add',{1,a}},finalized), - ?line {{error,badarg,undefined},finalized} = + {{error,badarg,undefined},finalized} = try_after_1({'abs',a},finalized), - ?line {{error,[the,{reason}],undefined},finalized} = + {{error,[the,{reason}],undefined},finalized} = try_after_1({error,[the,{reason}]},finalized), - ?line {{throw,{thrown,[reason]},undefined},finalized} = + {{throw,{thrown,[reason]},undefined},finalized} = try_after_1({throw,{thrown,[reason]}},finalized), - ?line {{exit,{exited,{reason}},undefined},finalized} = + {{exit,{exited,{reason}},undefined},finalized} = try_after_1({exit,{exited,{reason}}},finalized), - ?line {{error,function_clause,undefined},finalized} = + {{error,function_clause,undefined},finalized} = try_after_1(function_clause,finalized), - ?line ok = + ok = try try_after_1({'add',{1,1}}, finalized) catch error:{try_clause,2} -> ok end, - ?line finalized = erase(try_after), - ?line ok = + finalized = erase(try_after), + ok = try try foo({exit,[reaso,{n}]}) after put(try_after, finalized) end @@ -242,7 +242,7 @@ try_after_1(X, Y) -> after_bind(Conf) when is_list(Conf) -> V = [make_ref(),self()|value], - ?line {value,{value,V}} = + {value,{value,V}} = after_bind_1({value,V}, V, {value,V}), ok. @@ -269,12 +269,12 @@ after_bind_1(X, V, Y) -> catch_oops(Conf) when is_list(Conf) -> V = {v,[a,l|u],{e},self()}, - ?line {value,V} = catch_oops_1({value,V}), - ?line {value,1} = catch_oops_1({'div',{1,1}}), - ?line {error,badarith} = catch_oops_1({'div',{1,0}}), - ?line {error,function_clause} = catch_oops_1(function_clause), - ?line {throw,V} = catch_oops_1({throw,V}), - ?line {exit,V} = catch_oops_1({exit,V}), + {value,V} = catch_oops_1({value,V}), + {value,1} = catch_oops_1({'div',{1,1}}), + {error,badarith} = catch_oops_1({'div',{1,0}}), + {error,function_clause} = catch_oops_1(function_clause), + {throw,V} = catch_oops_1({throw,V}), + {exit,V} = catch_oops_1({exit,V}), ok. catch_oops_1(X) -> @@ -293,10 +293,10 @@ catch_oops_1(X) -> after_oops(Conf) when is_list(Conf) -> V = {self(),make_ref()}, - ?line {{value,V},V} = after_oops_1({value,V}, {value,V}), - ?line {{exit,V},V} = after_oops_1({exit,V}, {value,V}), - ?line {{error,V},undefined} = after_oops_1({value,V}, {error,V}), - ?line {{error,function_clause},undefined} = + {{value,V},V} = after_oops_1({value,V}, {value,V}), + {{exit,V},V} = after_oops_1({exit,V}, {value,V}), + {{error,V},undefined} = after_oops_1({value,V}, {error,V}), + {{error,function_clause},undefined} = after_oops_1({exit,V}, function_clause), ok. @@ -317,39 +317,39 @@ after_oops_1(X, Y) -> eclectic(Conf) when is_list(Conf) -> V = {make_ref(),3.1415926535,[[]|{}]}, - ?line {{value,{value,V},V},V} = + {{value,{value,V},V},V} = eclectic_1({foo,{value,{value,V}}}, undefined, {value,V}), - ?line {{'EXIT',{V,[{?MODULE,foo,1,_}|_]}},V} = + {{'EXIT',{V,[{?MODULE,foo,1,_}|_]}},V} = eclectic_1({catch_foo,{error,V}}, undefined, {value,V}), - ?line {{error,{exit,V},{'EXIT',V}},V} = + {{error,{exit,V},{'EXIT',V}},V} = eclectic_1({foo,{error,{exit,V}}}, error, {value,V}), - ?line {{value,{value,V},V}, + {{value,{value,V},V}, {'EXIT',{badarith,[{?MODULE,my_add,2,_}|_]}}} = eclectic_1({foo,{value,{value,V}}}, undefined, {'add',{0,a}}), - ?line {{'EXIT',V},V} = + {{'EXIT',V},V} = eclectic_1({catch_foo,{exit,V}}, undefined, {throw,V}), - ?line {{error,{'div',{1,0}},{'EXIT',{badarith,[{?MODULE,my_div,2,_}|_]}}}, + {{error,{'div',{1,0}},{'EXIT',{badarith,[{?MODULE,my_div,2,_}|_]}}}, {'EXIT',V}} = eclectic_1({foo,{error,{'div',{1,0}}}}, error, {exit,V}), - ?line {{{error,V},{'EXIT',{V,[{?MODULE,foo,1,_}|_]}}}, + {{{error,V},{'EXIT',{V,[{?MODULE,foo,1,_}|_]}}}, {'EXIT',V}} = eclectic_1({catch_foo,{throw,{error,V}}}, undefined, {exit,V}), %% - ?line {{value,{value,{value,V},V}},V} = + {{value,{value,{value,V},V}},V} = eclectic_2({value,{value,V}}, undefined, {value,V}), - ?line {{value,{throw,{value,V},V}},V} = + {{value,{throw,{value,V},V}},V} = eclectic_2({throw,{value,V}}, throw, {value,V}), - ?line {{caught,{'EXIT',V}},undefined} = + {{caught,{'EXIT',V}},undefined} = eclectic_2({value,{value,V}}, undefined, {exit,V}), - ?line {{caught,{'EXIT',{V,[{?MODULE,foo,1,_}|_]}}},undefined} = + {{caught,{'EXIT',{V,[{?MODULE,foo,1,_}|_]}}},undefined} = eclectic_2({error,{value,V}}, throw, {error,V}), - ?line {{caught,{'EXIT',{badarg,[{erlang,abs,[V],_}|_]}}},V} = + {{caught,{'EXIT',{badarg,[{erlang,abs,[V],_}|_]}}},V} = eclectic_2({value,{'abs',V}}, undefined, {value,V}), - ?line {{caught,{'EXIT',{badarith,[{?MODULE,my_add,2,_}|_]}}},V} = + {{caught,{'EXIT',{badarith,[{?MODULE,my_add,2,_}|_]}}},V} = eclectic_2({exit,{'add',{0,a}}}, exit, {value,V}), - ?line {{caught,{'EXIT',V}},undefined} = + {{caught,{'EXIT',V}},undefined} = eclectic_2({value,{error,V}}, undefined, {exit,V}), - ?line {{caught,{'EXIT',{V,[{?MODULE,foo,1,_}|_]}}},undefined} = + {{caught,{'EXIT',{V,[{?MODULE,foo,1,_}|_]}}},undefined} = eclectic_2({throw,{'div',{1,0}}}, throw, {error,V}), ok. @@ -377,44 +377,44 @@ eclectic_2(X, C, Y) -> Catch = case catch - {Done, - try foo(X) of - V -> {value,V,foo(V)} - catch - C:D -> {C,D,foo(D)} - after - put(eclectic, foo(Y)) - end} of - {Done,Z} -> {value,Z}; - Z -> {caught,Z} - end, + {Done, + try foo(X) of + V -> {value,V,foo(V)} + catch + C:D -> {C,D,foo(D)} + after + put(eclectic, foo(Y)) + end} of + {Done,Z} -> {value,Z}; + Z -> {caught,Z} + end, {Catch,erase(eclectic)}. rethrow(Conf) when is_list(Conf) -> V = {a,[b,{c,self()},make_ref]}, - ?line {value2,value1} = + {value2,value1} = rethrow_1({value,V}, V), - ?line {caught2,{error,V}} = + {caught2,{error,V}} = rethrow_2({error,V}, undefined), - ?line {caught2,{exit,V}} = + {caught2,{exit,V}} = rethrow_1({exit,V}, error), - ?line {caught2,{throw,V}} = + {caught2,{throw,V}} = rethrow_1({throw,V}, undefined), - ?line {caught2,{throw,V}} = + {caught2,{throw,V}} = rethrow_2({throw,V}, undefined), - ?line {caught2,{error,badarith}} = + {caught2,{error,badarith}} = rethrow_1({'add',{0,a}}, throw), - ?line {caught2,{error,function_clause}} = + {caught2,{error,function_clause}} = rethrow_2(function_clause, undefined), - ?line {caught2,{error,{try_clause,V}}} = + {caught2,{error,{try_clause,V}}} = rethrow_1({value,V}, exit), - ?line {value2,{caught1,V}} = + {value2,{caught1,V}} = rethrow_1({error,V}, error), - ?line {value2,{caught1,V}} = + {value2,{caught1,V}} = rethrow_1({exit,V}, exit), - ?line {value2,caught1} = + {value2,caught1} = rethrow_2({throw,V}, V), ok. @@ -444,91 +444,91 @@ rethrow_2(X, C1) -> nested_of(Conf) when is_list(Conf) -> V = {[self()|make_ref()],1.4142136}, - ?line {{value,{value1,{V,x2}}}, - {V,x3}, - {V,x4}, - finalized} = + {{value,{value1,{V,x2}}}, + {V,x3}, + {V,x4}, + finalized} = nested_of_1({{value,{V,x1}},void,{V,x1}}, {value,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}), - ?line {{caught,{throw,{V,x2}}}, - {V,x3}, - {V,x4}, - finalized} = + {{caught,{throw,{V,x2}}}, + {V,x3}, + {V,x4}, + finalized} = nested_of_1({{value,{V,x1}},void,{V,x1}}, {throw,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}), - ?line {{caught,{error,badarith}}, - undefined, - {V,x4}, - finalized} = + {{caught,{error,badarith}}, + undefined, + {V,x4}, + finalized} = nested_of_1({{value,{V,x1}},void,{V,x1}}, {throw,{V,x2}}, {'div',{1,0}}, {value,{V,x4}}), - ?line {{caught,{error,badarith}}, - undefined, - undefined, - finalized} = + {{caught,{error,badarith}}, + undefined, + undefined, + finalized} = nested_of_1({{value,{V,x1}},void,{V,x1}}, {throw,{V,x2}}, {'div',{1,0}}, {'add',{0,b}}), %% - ?line {{caught,{error,{try_clause,{V,x1}}}}, - {V,x3}, - {V,x4}, - finalized} = + {{caught,{error,{try_clause,{V,x1}}}}, + {V,x3}, + {V,x4}, + finalized} = nested_of_1({{value,{V,x1}},void,try_clause}, void, {value,{V,x3}}, {value,{V,x4}}), - ?line {{caught,{exit,{V,x3}}}, - undefined, - {V,x4}, - finalized} = + {{caught,{exit,{V,x3}}}, + undefined, + {V,x4}, + finalized} = nested_of_1({{value,{V,x1}},void,try_clause}, void, {exit,{V,x3}}, {value,{V,x4}}), - ?line {{caught,{throw,{V,x4}}}, - undefined, - undefined, - finalized} = + {{caught,{throw,{V,x4}}}, + undefined, + undefined, + finalized} = nested_of_1({{value,{V,x1}},void,try_clause}, void, {exit,{V,x3}}, {throw,{V,x4}}), %% - ?line {{value,{caught1,{V,x2}}}, - {V,x3}, - {V,x4}, - finalized} = + {{value,{caught1,{V,x2}}}, + {V,x3}, + {V,x4}, + finalized} = nested_of_1({{error,{V,x1}},error,{V,x1}}, {value,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}), - ?line {{caught,{error,badarith}}, - {V,x3}, - {V,x4}, - finalized} = + {{caught,{error,badarith}}, + {V,x3}, + {V,x4}, + finalized} = nested_of_1({{error,{V,x1}},error,{V,x1}}, {'add',{1,c}}, {value,{V,x3}}, {value,{V,x4}}), - ?line {{caught,{error,badarith}}, - undefined, - {V,x4}, - finalized} = + {{caught,{error,badarith}}, + undefined, + {V,x4}, + finalized} = nested_of_1({{error,{V,x1}},error,{V,x1}}, {'add',{1,c}}, {'div',{17,0}}, {value,{V,x4}}), - ?line {{caught,{error,badarg}}, - undefined, - undefined, - finalized} = + {{caught,{error,badarg}}, + undefined, + undefined, + finalized} = nested_of_1({{error,{V,x1}},error,{V,x1}}, {'add',{1,c}}, {'div',{17,0}}, {'abs',V}), %% - ?line {{caught,{error,badarith}}, - {V,x3}, - {V,x4}, - finalized} = + {{caught,{error,badarith}}, + {V,x3}, + {V,x4}, + finalized} = nested_of_1({{'add',{2,c}},rethrow,void}, void, {value,{V,x3}}, {value,{V,x4}}), - ?line {{caught,{error,badarg}}, - undefined, - {V,x4}, - finalized} = + {{caught,{error,badarg}}, + undefined, + {V,x4}, + finalized} = nested_of_1({{'add',{2,c}},rethrow,void}, void, {'abs',V}, {value,{V,x4}}), - ?line {{caught,{error,function_clause}}, - undefined, - undefined, - finalized} = + {{caught,{error,function_clause}}, + undefined, + undefined, + finalized} = nested_of_1({{'add',{2,c}},rethrow,void}, void, {'abs',V}, function_clause), ok. @@ -569,93 +569,93 @@ nested_of_1({X1,C1,V1}, nested_catch(Conf) when is_list(Conf) -> V = {[make_ref(),1.4142136,self()]}, - ?line {{value,{value1,{V,x2}}}, - {V,x3}, - {V,x4}, - finalized} = + {{value,{value1,{V,x2}}}, + {V,x3}, + {V,x4}, + finalized} = nested_catch_1({{value,{V,x1}},void,{V,x1}}, - {value,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}), - ?line {{caught,{throw,{V,x2}}}, - {V,x3}, - {V,x4}, - finalized} = + {value,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}), + {{caught,{throw,{V,x2}}}, + {V,x3}, + {V,x4}, + finalized} = nested_catch_1({{value,{V,x1}},void,{V,x1}}, - {throw,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}), - ?line {{caught,{error,badarith}}, - undefined, - {V,x4}, - finalized} = + {throw,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}), + {{caught,{error,badarith}}, + undefined, + {V,x4}, + finalized} = nested_catch_1({{value,{V,x1}},void,{V,x1}}, - {throw,{V,x2}}, {'div',{1,0}}, {value,{V,x4}}), - ?line {{caught,{error,badarith}}, - undefined, - undefined, - finalized} = + {throw,{V,x2}}, {'div',{1,0}}, {value,{V,x4}}), + {{caught,{error,badarith}}, + undefined, + undefined, + finalized} = nested_catch_1({{value,{V,x1}},void,{V,x1}}, - {throw,{V,x2}}, {'div',{1,0}}, {'add',{0,b}}), + {throw,{V,x2}}, {'div',{1,0}}, {'add',{0,b}}), %% - ?line {{caught,{error,{try_clause,{V,x1}}}}, - {V,x3}, - {V,x4}, - finalized} = + {{caught,{error,{try_clause,{V,x1}}}}, + {V,x3}, + {V,x4}, + finalized} = nested_catch_1({{value,{V,x1}},void,try_clause}, - void, {value,{V,x3}}, {value,{V,x4}}), - ?line {{caught,{exit,{V,x3}}}, - undefined, - {V,x4}, - finalized} = + void, {value,{V,x3}}, {value,{V,x4}}), + {{caught,{exit,{V,x3}}}, + undefined, + {V,x4}, + finalized} = nested_catch_1({{value,{V,x1}},void,try_clause}, - void, {exit,{V,x3}}, {value,{V,x4}}), - ?line {{caught,{throw,{V,x4}}}, - undefined, - undefined, - finalized} = + void, {exit,{V,x3}}, {value,{V,x4}}), + {{caught,{throw,{V,x4}}}, + undefined, + undefined, + finalized} = nested_catch_1({{value,{V,x1}},void,try_clause}, - void, {exit,{V,x3}}, {throw,{V,x4}}), + void, {exit,{V,x3}}, {throw,{V,x4}}), %% - ?line {{value,{caught1,{V,x2}}}, - {V,x3}, - {V,x4}, - finalized} = + {{value,{caught1,{V,x2}}}, + {V,x3}, + {V,x4}, + finalized} = nested_catch_1({{error,{V,x1}},error,{V,x1}}, - {value,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}), - ?line {{caught,{error,badarith}}, - {V,x3}, - {V,x4}, - finalized} = + {value,{V,x2}}, {value,{V,x3}}, {value,{V,x4}}), + {{caught,{error,badarith}}, + {V,x3}, + {V,x4}, + finalized} = nested_catch_1({{error,{V,x1}},error,{V,x1}}, - {'add',{1,c}}, {value,{V,x3}}, {value,{V,x4}}), - ?line {{caught,{error,badarith}}, - undefined, - {V,x4}, - finalized} = + {'add',{1,c}}, {value,{V,x3}}, {value,{V,x4}}), + {{caught,{error,badarith}}, + undefined, + {V,x4}, + finalized} = nested_catch_1({{error,{V,x1}},error,{V,x1}}, - {'add',{1,c}}, {'div',{17,0}}, {value,{V,x4}}), - ?line {{caught,{error,badarg}}, - undefined, - undefined, - finalized} = + {'add',{1,c}}, {'div',{17,0}}, {value,{V,x4}}), + {{caught,{error,badarg}}, + undefined, + undefined, + finalized} = nested_catch_1({{error,{V,x1}},error,{V,x1}}, - {'add',{1,c}}, {'div',{17,0}}, {'abs',V}), + {'add',{1,c}}, {'div',{17,0}}, {'abs',V}), %% - ?line {{caught,{error,badarith}}, - {V,x3}, - {V,x4}, - finalized} = + {{caught,{error,badarith}}, + {V,x3}, + {V,x4}, + finalized} = nested_catch_1({{'add',{2,c}},rethrow,void}, - void, {value,{V,x3}}, {value,{V,x4}}), - ?line {{caught,{error,badarg}}, - undefined, - {V,x4}, - finalized} = + void, {value,{V,x3}}, {value,{V,x4}}), + {{caught,{error,badarg}}, + undefined, + {V,x4}, + finalized} = nested_catch_1({{'add',{2,c}},rethrow,void}, - void, {'abs',V}, {value,{V,x4}}), - ?line {{caught,{error,function_clause}}, - undefined, - undefined, - finalized} = + void, {'abs',V}, {value,{V,x4}}), + {{caught,{error,function_clause}}, + undefined, + undefined, + finalized} = nested_catch_1({{'add',{2,c}},rethrow,void}, - void, {'abs',V}, function_clause), + void, {'abs',V}, function_clause), ok. nested_catch_1({X1,C1,V1}, @@ -694,64 +694,64 @@ nested_catch_1({X1,C1,V1}, nested_after(Conf) when is_list(Conf) -> V = [{make_ref(),1.4142136,self()}], - ?line {value, + {value, {V,x3}, {value1,{V,x2}}, finalized} = nested_after_1({{value,{V,x1}},void,{V,x1}}, {value,{V,x2}}, {value,{V,x3}}), - ?line {{caught,{error,{V,x2}}}, + {{caught,{error,{V,x2}}}, {V,x3}, undefined, finalized} = nested_after_1({{value,{V,x1}},void,{V,x1}}, {error,{V,x2}}, {value,{V,x3}}), - ?line {{caught,{exit,{V,x3}}}, + {{caught,{exit,{V,x3}}}, undefined, undefined, finalized} = nested_after_1({{value,{V,x1}},void,{V,x1}}, {error,{V,x2}}, {exit,{V,x3}}), %% - ?line {{caught,{error,{try_clause,{V,x1}}}}, + {{caught,{error,{try_clause,{V,x1}}}}, {V,x3}, undefined, finalized} = nested_after_1({{value,{V,x1}},void,try_clause}, void, {value,{V,x3}}), - ?line {{caught,{error,badarith}}, + {{caught,{error,badarith}}, undefined, undefined, finalized} = nested_after_1({{value,{V,x1}},void,try_clause}, void, {'div',{17,0}}), %% - ?line {value, + {value, {V,x3}, {caught1,{V,x2}}, finalized} = nested_after_1({{throw,{V,x1}},throw,{V,x1}}, {value,{V,x2}}, {value,{V,x3}}), - ?line {{caught,{error,badarith}}, + {{caught,{error,badarith}}, {V,x3}, undefined, finalized} = nested_after_1({{throw,{V,x1}},throw,{V,x1}}, {'add',{a,b}}, {value,{V,x3}}), - ?line {{caught,{error,badarg}}, + {{caught,{error,badarg}}, undefined, undefined, finalized} = nested_after_1({{throw,{V,x1}},throw,{V,x1}}, {'add',{a,b}}, {'abs',V}), %% - ?line {{caught,{throw,{V,x1}}}, + {{caught,{throw,{V,x1}}}, {V,x3}, undefined, finalized} = nested_after_1({{throw,{V,x1}},rethrow,void}, void, {value,{V,x3}}), - ?line {{caught,{error,badarith}}, + {{caught,{error,badarith}}, undefined, undefined, finalized} = @@ -843,12 +843,12 @@ my_abs(X) -> abs(X). last_call_optimization(Config) when is_list(Config) -> - ?line error = in_tail(dum), - ?line StkSize0 = in_tail(0), - ?line StkSize = in_tail(50000), + error = in_tail(dum), + StkSize0 = in_tail(0), + StkSize = in_tail(50000), io:format("StkSize0 = ~p", [StkSize0]), io:format("StkSize = ~p", [StkSize]), - ?line StkSize = StkSize0, + StkSize = StkSize0, ok. in_tail(E) -> @@ -891,20 +891,20 @@ do_bool(A0, B) -> plain_catch_coverage(Config) when is_list(Config) -> %% Cover some code in beam_block:alloc_may_pass/1. - ?line {a,[42]} = do_plain_catch_list(42). + {a,[42]} = do_plain_catch_list(42). do_plain_catch_list(X) -> B = [X], catch id({a,B}). andalso_orelse(Config) when is_list(Config) -> - ?line {2,{a,42}} = andalso_orelse_1(true, {a,42}), - ?line {b,{b}} = andalso_orelse_1(false, {b}), - ?line {catched,no_tuple} = andalso_orelse_1(false, no_tuple), + {2,{a,42}} = andalso_orelse_1(true, {a,42}), + {b,{b}} = andalso_orelse_1(false, {b}), + {catched,no_tuple} = andalso_orelse_1(false, no_tuple), - ?line ok = andalso_orelse_2({type,[a]}), - ?line also_ok = andalso_orelse_2({type,[]}), - ?line also_ok = andalso_orelse_2({type,{a}}), + ok = andalso_orelse_2({type,[a]}), + also_ok = andalso_orelse_2({type,[]}), + also_ok = andalso_orelse_2({type,{a}}), ok. andalso_orelse_1(A, B) -> diff --git a/lib/compiler/test/warnings_SUITE.erl b/lib/compiler/test/warnings_SUITE.erl index 2a425c2ae5..d66f2d5053 100644 --- a/lib/compiler/test/warnings_SUITE.erl +++ b/lib/compiler/test/warnings_SUITE.erl @@ -28,8 +28,8 @@ -define(t, test_server). -else. -include_lib("common_test/include/ct.hrl"). --define(datadir, ?config(data_dir, Conf)). --define(privdir, ?config(priv_dir, Conf)). +-define(datadir, proplists:get_value(data_dir, Conf)). +-define(privdir, proplists:get_value(priv_dir, Conf)). -endif. -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, @@ -41,21 +41,18 @@ files/1,effect/1,bin_opt_info/1,bin_construction/1, comprehensions/1,maps/1,maps_bin_opt_info/1, redundant_boolean_clauses/1, - latin1_fallback/1,underscore/1,no_warnings/1]). - -% Default timetrap timeout (set in init_per_testcase). --define(default_timeout, ?t:minutes(2)). + latin1_fallback/1,underscore/1,no_warnings/1, + bit_syntax/1]). init_per_testcase(_Case, Config) -> - ?line Dog = ?t:timetrap(?default_timeout), - [{watchdog, Dog} | Config]. + Config. -end_per_testcase(_Case, Config) -> - Dog = ?config(watchdog, Config), - test_server:timetrap_cancel(Dog), +end_per_testcase(_Case, _Config) -> ok. -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,2}}]. all() -> test_lib:recompile(?MODULE), @@ -68,7 +65,7 @@ groups() -> bin_opt_info,bin_construction,comprehensions,maps, maps_bin_opt_info, redundant_boolean_clauses,latin1_fallback, - underscore,no_warnings]}]. + underscore,no_warnings,bit_syntax]}]. init_per_suite(Config) -> Config. @@ -103,7 +100,7 @@ pattern(Config) when is_list(Config) -> [{2,v3_core,nomatch}, {6,v3_core,nomatch}, {11,v3_core,nomatch} ] }}], - ?line [] = run(Config, Ts), + [] = run(Config, Ts), ok. pattern2(Config) when is_list(Config) -> @@ -127,7 +124,7 @@ pattern2(Config) when is_list(Config) -> {4,sys_core_fold,no_clause_match}, {5,sys_core_fold,nomatch_clause_type}, {6,sys_core_fold,nomatch_clause_type}]}}], - ?line [] = run(Config, Ts), + [] = run(Config, Ts), %% Disable Core Erlang optimizations. v3_kernel should produce %% a warning for the clause that didn't match. @@ -136,7 +133,7 @@ pattern2(Config) when is_list(Config) -> [nowarn_unused_vars,no_copt], {warnings, [{2,v3_kernel,{nomatch_shadow,1}}]}}], - ?line [] = run(Config, Ts2), + [] = run(Config, Ts2), ok. pattern3(Config) when is_list(Config) -> @@ -152,7 +149,7 @@ pattern3(Config) when is_list(Config) -> [nowarn_unused_vars], {warnings, [{4,v3_kernel,{nomatch_shadow,2}}]}}], - ?line [] = run(Config, Ts), + [] = run(Config, Ts), ok. @@ -213,7 +210,7 @@ pattern4(Config) when is_list(Config) -> {23,sys_core_fold,no_clause_match}, {33,sys_core_fold,no_clause_match} ]}}], - ?line [] = run(Config, Ts), + [] = run(Config, Ts), ok. @@ -256,7 +253,7 @@ guard(Config) when is_list(Config) -> {11,sys_core_fold,nomatch_guard}, {11,sys_core_fold,{eval_failure,badarg}} ]}}], - ?line [] = run(Config, Ts), + [] = run(Config, Ts), ok. @@ -321,7 +318,7 @@ bool_cases(Config) when is_list(Config) -> [{6,sys_core_fold,nomatch_shadow}, {13,sys_core_fold,nomatch_shadow}, {18,sys_core_fold,nomatch_clause_type} ]} }], - ?line [] = run(Config, Ts), + [] = run(Config, Ts), ok. bad_apply(Config) when is_list(Config) -> @@ -340,11 +337,11 @@ bad_apply(Config) when is_list(Config) -> {4,v3_kernel,bad_call}, {5,v3_kernel,bad_call}, {6,v3_kernel,bad_call}]}}], - ?line [] = run(Config, Ts), + [] = run(Config, Ts), %% Also verify that the generated code generates the correct error. - ?line try erlang:42() of - _ -> ?line ?t:fail() + try erlang:42() of + _ -> ct:fail(should_fail) catch error:badarg -> ok end, @@ -368,7 +365,7 @@ files(Config) when is_list(Config) -> [{"file1",[{17,sys_core_fold,{eval_failure,badarith}}]}, {"file2",[{10,sys_core_fold,{eval_failure,badarith}}]}]}}], - ?line [] = run(Config, Ts), + [] = run(Config, Ts), ok. %% Test warnings for term construction and BIF calls in effect context. @@ -514,7 +511,7 @@ effect(Config) when is_list(Config) -> {28,sys_core_fold,useless_building}, {36,sys_core_fold,{no_effect,{erlang,'=:=',2}}}, {38,sys_core_fold,{no_effect,{erlang,get_cookie,0}}}]}}], - ?line [] = run(Config, Ts), + [] = run(Config, Ts), ok. bin_opt_info(Config) when is_list(Config) -> @@ -537,14 +534,14 @@ bin_opt_info(Config) when is_list(Config) -> {5,beam_bsm,{no_bin_opt,{{t1,1},no_suitable_bs_start_match}}}, {9,beam_bsm,{no_bin_opt, {binary_used_in,{extfunc,erlang,split_binary,2}}}} ]}}], - ?line [] = run(Config, Ts1), + [] = run(Config, Ts1), %% For coverage: don't give the bin_opt_info option. Ts2 = [{bsm2, Code, [], []}], - ?line [] = run(Config, Ts2), + [] = run(Config, Ts2), ok. bin_construction(Config) when is_list(Config) -> @@ -561,7 +558,7 @@ bin_construction(Config) when is_list(Config) -> [], {warnings,[{4,sys_core_fold,embedded_binary_size}, {8,sys_core_fold,{embedded_unit,8,28}}]}}], - ?line [] = run(Config, Ts), + [] = run(Config, Ts), ok. @@ -783,6 +780,50 @@ no_warnings(Config) when is_list(Config) -> run(Config, Ts), ok. +bit_syntax(Config) -> + Ts = [{?FUNCTION_NAME, + <<"a(<<-1>>) -> ok; + a(<<1023>>) -> ok; + a(<<777/signed>>) -> ok; + a(<<a/binary>>) -> ok; + a(<<a/integer>>) -> ok; + a(<<a/float>>) -> ok; + a(<<a/utf8>>) -> ok; + a(<<a/utf16>>) -> ok; + a(<<a/utf32>>) -> ok; + a(<<a/utf32>>) -> ok. + b(Bin) -> Sz = bad, <<42:Sz>> = Bin. + c(Sz, Bin) -> + case Bin of + <<-42:Sz/unsigned>> -> ok; + <<42:Sz/float>> -> ok; + <<42:Sz/binary>> -> ok + end. + ">>, + [], + {warnings,[{1,sys_core_fold,no_clause_match}, + {1,sys_core_fold,{nomatch_bit_syntax_unsigned,-1}}, + {2,sys_core_fold,{nomatch_bit_syntax_truncated, + unsigned,1023,8}}, + {3,sys_core_fold,{nomatch_bit_syntax_truncated, + signed,777,8}}, + {4,sys_core_fold,{nomatch_bit_syntax_type,a,binary}}, + {5,sys_core_fold,{nomatch_bit_syntax_type,a,integer}}, + {6,sys_core_fold,{nomatch_bit_syntax_type,a,float}}, + {7,sys_core_fold,{nomatch_bit_syntax_type,a,utf8}}, + {8,sys_core_fold,{nomatch_bit_syntax_type,a,utf16}}, + {9,sys_core_fold,{nomatch_bit_syntax_type,a,utf32}}, + {10,sys_core_fold,{nomatch_bit_syntax_type,a,utf32}}, + {11,sys_core_fold,no_clause_match}, + {11,sys_core_fold,{nomatch_bit_syntax_size,bad}}, + {14,sys_core_fold,{nomatch_bit_syntax_unsigned,-42}}, + {16,sys_core_fold,{nomatch_bit_syntax_type,42,binary}} + ]} + }], + run(Config, Ts), + ok. + + %%% %%% End of test cases. %%% @@ -793,7 +834,7 @@ run(Config, Tests) -> E -> BadL; Bad -> - ?t:format("~nTest ~p failed. Expected~n ~p~n" + io:format("~nTest ~p failed. Expected~n ~p~n" "but got~n ~p~n", [N, E, Bad]), fail() end @@ -806,33 +847,32 @@ run(Config, Tests) -> run_test(Conf, Test0, Warnings) -> Module = "warnings_"++test_lib:uniq(), Filename = Module ++ ".erl", - ?line DataDir = ?privdir, + DataDir = ?privdir, Test = ["-module(", Module, "). ", Test0], - ?line File = filename:join(DataDir, Filename), - ?line Opts = [binary,export_all,return|Warnings], - ?line ok = file:write_file(File, Test), + File = filename:join(DataDir, Filename), + Opts = [binary,export_all,return|Warnings], + ok = file:write_file(File, Test), %% Compile once just to print all warnings. - ?line compile:file(File, [binary,export_all,report|Warnings]), + compile:file(File, [binary,export_all,report|Warnings]), %% Test result of compilation. - ?line Res = case compile:file(File, Opts) of - {ok, _M, Bin, []} when is_binary(Bin) -> - []; - {ok, _M, Bin, Ws0} when is_binary(Bin) -> - %% We are not interested in warnings from - %% erl_lint here. - WsL = [{F,[W || {_,Mod,_}=W <- Ws, - Mod =/= erl_lint]} || - {F,Ws} <- Ws0], - case WsL of - [{_File,Ws}] -> {warnings, Ws}; - _ -> list_to_tuple([warnings, WsL]) - end - end, + Res = case compile:file(File, Opts) of + {ok, _M, Bin, []} when is_binary(Bin) -> + []; + {ok, _M, Bin, Ws0} when is_binary(Bin) -> + %% We are not interested in warnings from + %% erl_lint here. + WsL = [{F,[W || {_,Mod,_}=W <- Ws, + Mod =/= erl_lint]} || + {F,Ws} <- Ws0], + case WsL of + [{_File,Ws}] -> {warnings, Ws}; + _ -> list_to_tuple([warnings, WsL]) + end + end, file:delete(File), Res. fail() -> - io:format("failed~n"), - ?t:fail(). + ct:fail(failed). diff --git a/lib/debugger/src/int.erl b/lib/debugger/src/int.erl index 4f54beb45b..1e43d1858a 100644 --- a/lib/debugger/src/int.erl +++ b/lib/debugger/src/int.erl @@ -547,7 +547,7 @@ load({Mod, Src, Beam, BeamBin, Exp, Abst}, Dist) -> check_module(Mod) -> case code:which(Mod) of Beam when is_list(Beam) -> - case find_src(Beam) of + case find_src(Mod, Beam) of Src when is_list(Src) -> check_application(Src), case check_beam(Beam) of @@ -608,7 +608,7 @@ check_application2("gs-"++_) -> throw({error,{app,gs}}); check_application2("debugger-"++_) -> throw({error,{app,debugger}}); check_application2(_) -> ok. -find_src(Beam) -> +find_src(Mod, Beam) -> Src0 = filename:rootname(Beam) ++ ".erl", case is_file(Src0) of true -> Src0; @@ -618,10 +618,22 @@ find_src(Beam) -> filename:basename(Src0)]), case is_file(Src) of true -> Src; - false -> error + false -> find_src_from_module(Mod) end end. +find_src_from_module(Mod) -> + Compile = Mod:module_info(compile), + case lists:keyfind(source, 1, Compile) of + {source, Src} -> + case is_file(Src) of + true -> Src; + false -> error + end; + false -> + error + end. + find_beam(Mod, Src) -> SrcDir = filename:dirname(Src), BeamFile = atom_to_list(Mod) ++ code:objfile_extension(), diff --git a/lib/debugger/test/int_SUITE.erl b/lib/debugger/test/int_SUITE.erl index 8b16b7631b..ec4de88331 100644 --- a/lib/debugger/test/int_SUITE.erl +++ b/lib/debugger/test/int_SUITE.erl @@ -245,14 +245,13 @@ interpretable(Config) when is_list(Config) -> ?line true = int:interpretable(filename:join([DataDir,lists1])), ?line true = code:del_path(DataDir), - %% {error, no_src} - ?line PrivDir = filename:join(?config(priv_dir, Config), ""), - ?line {ok, _} = file:copy(filename:join([DataDir,"lists1.beam"]), + %% true (from source) + PrivDir = filename:join(?config(priv_dir, Config), ""), + {ok, _} = file:copy(filename:join([DataDir,"lists1.beam"]), filename:join([PrivDir,"lists1.beam"])), - ?line true = code:add_patha(PrivDir), - - ?line {error, no_src} = int:interpretable(lists1), - ?line ok = file:delete(filename:join([PrivDir,"lists1.beam"])), + true = code:add_patha(PrivDir), + true = int:interpretable(lists1), + ok = file:delete(filename:join([PrivDir,"lists1.beam"])), %% {error, no_beam} Src = filename:join([PrivDir,"lists1.erl"]), @@ -267,6 +266,11 @@ interpretable(Config) when is_list(Config) -> ?line ok = file:delete(Src), ?line true = code:del_path(PrivDir), + %% {error, no_src} + {ok, lists2, Binary} = compile:forms([{attribute,1,module,lists2}], []), + code:load_binary(lists2, "unknown", Binary), + {error, no_src} = int:interpretable(lists2), + %% {error, badarg} ?line {error, badarg} = int:interpretable(pride), ?line {error, badarg} = int:interpretable("prejudice.erl"), diff --git a/lib/eldap/src/eldap.erl b/lib/eldap/src/eldap.erl index 5d9718f00c..dc236f8a44 100644 --- a/lib/eldap/src/eldap.erl +++ b/lib/eldap/src/eldap.erl @@ -697,7 +697,7 @@ exec_simple_bind_reply(Data, {ok,Msg}) when {bindResponse, Result} -> case Result#'BindResponse'.resultCode of success -> {ok,Data}; - referral -> {{ok, {referral,Msg#'BindResponse'.referral}}, Data}; + referral -> {{ok, {referral,Result#'BindResponse'.referral}}, Data}; Error -> {error, Error} end; Other -> {error, Other} diff --git a/lib/eldap/vsn.mk b/lib/eldap/vsn.mk index 105a2bcdbb..99c474d588 100644 --- a/lib/eldap/vsn.mk +++ b/lib/eldap/vsn.mk @@ -1 +1 @@ -ELDAP_VSN = 1.2 +ELDAP_VSN = 1.2.1 diff --git a/lib/erl_interface/configure.in b/lib/erl_interface/configure.in index 3ac9212085..7a3b5ce378 100644 --- a/lib/erl_interface/configure.in +++ b/lib/erl_interface/configure.in @@ -251,7 +251,7 @@ case "$threads_disabled" in ;; win32_threads) EI_THREADS="true" - THR_DEFS="$THR_DEFS -D_WIN32_WINNT=0x0500 -DWINVER=0x0500" + THR_DEFS="$THR_DEFS -D_WIN32_WINNT=0x0600 -DWINVER=0x0600" ;; pthread) EI_THREADS="true" diff --git a/lib/inets/src/http_server/httpd_request_handler.erl b/lib/inets/src/http_server/httpd_request_handler.erl index 134576059d..8fae9ac46e 100644 --- a/lib/inets/src/http_server/httpd_request_handler.erl +++ b/lib/inets/src/http_server/httpd_request_handler.erl @@ -102,8 +102,8 @@ init([Manager, ConfigDB, AcceptTimeout]) -> KeepAliveTimeOut = 1000 * httpd_util:lookup(ConfigDB, keep_alive_timeout, 150), case http_transport:negotiate(SocketType, Socket, ?HANDSHAKE_TIMEOUT) of - {error, _Error} -> - exit(shutdown); %% Can be 'normal'. + {error, Error} -> + exit({shutdown, Error}); %% Can be 'normal'. ok -> continue_init(Manager, ConfigDB, SocketType, Socket, KeepAliveTimeOut) end. @@ -294,7 +294,10 @@ handle_info(Info, #state{mod = ModData} = State) -> %% cleaning up. When it returns, the gen_server terminates with Reason. %% The return value is ignored. %%-------------------------------------------------------------------- -terminate(normal, State) -> +terminate(Reason, State) when Reason == normal; + Reason == shutdown -> + do_terminate(State); +terminate({shutdown,_}, State) -> do_terminate(State); terminate(Reason, #state{response_sent = false, mod = ModData} = State) -> httpd_response:send_status(ModData, 500, none), diff --git a/lib/kernel/doc/src/code.xml b/lib/kernel/doc/src/code.xml index d4c9a48901..819da544c3 100644 --- a/lib/kernel/doc/src/code.xml +++ b/lib/kernel/doc/src/code.xml @@ -310,6 +310,10 @@ <datatype> <name name="load_error_rsn"/> </datatype> + <datatype> + <name name="prepared_code"/> + <desc>An opaque term holding prepared code.</desc> + </datatype> </datatypes> <funcs> @@ -479,6 +483,138 @@ </desc> </func> <func> + <name name="atomic_load" arity="1"/> + <fsummary>Load a list of modules atomically</fsummary> + <desc> + <p>Tries to load all of the modules in the list + <c><anno>Modules</anno></c> atomically. That means that + either all modules are loaded at the same time, or + none of the modules are loaded if there is a problem with any + of the modules.</p> + <p>Loading can fail for one the following reasons:</p> + <taglist> + <tag><c>badfile</c></tag> + <item> + <p>The object code has an incorrect format or the module + name in the object code is not the expected module name.</p> + </item> + <tag><c>nofile</c></tag> + <item> + <p>No file with object code exists.</p> + </item> + <tag><c>on_load_not_allowed</c></tag> + <item> + <p>A module contains an + <seealso marker="doc/reference_manual:code_loading#on_load">-on_load function</seealso>.</p> + </item> + <tag><c>duplicated</c></tag> + <item> + <p>A module is included more than once in + <c><anno>Modules</anno></c>.</p> + </item> + <tag><c>not_purged</c></tag> + <item> + <p>The object code can not be loaded because an old version + of the code already exists.</p> + </item> + <tag><c>sticky_directory</c></tag> + <item> + <p>The object code resides in a sticky directory.</p> + </item> + <tag><c>pending_on_load</c></tag> + <item> + <p>A previously loaded module contains an + <c>-on_load</c> function that never finished.</p> + </item> + </taglist> + <p>If it is important to minimize the time that an application + is inactive while changing code, use + <seealso marker="#prepare_loading/1">prepare_loading/1</seealso> + and + <seealso marker="#finish_loading/1">finish_loading/1</seealso> + instead of <c>atomic_load/1</c>. Here is an example:</p> +<pre> +{ok,Prepared} = code:prepare_loading(Modules), +%% Put the application into an inactive state or do any +%% other preparation needed before changing the code. +ok = code:finish_loading(Prepared), +%% Resume the application.</pre> + </desc> + </func> + <func> + <name name="prepare_loading" arity="1"/> + <fsummary>Prepare a list of modules atomically</fsummary> + <desc> + <p>Prepares to load the modules in the list + <c><anno>Modules</anno></c>. + Finish the loading by calling + <seealso marker="#finish_loading/1">finish_loading(Prepared)</seealso>.</p> + <p>This function can fail with one of the following error reasons:</p> + <taglist> + <tag><c>badfile</c></tag> + <item> + <p>The object code has an incorrect format or the module + name in the object code is not the expected module name.</p> + </item> + <tag><c>nofile</c></tag> + <item> + <p>No file with object code exists.</p> + </item> + <tag><c>on_load_not_allowed</c></tag> + <item> + <p>A module contains an + <seealso marker="doc/reference_manual:code_loading#on_load">-on_load function</seealso>.</p> + </item> + <tag><c>duplicated</c></tag> + <item> + <p>A module is included more than once in + <c><anno>Modules</anno></c>.</p> + </item> + </taglist> + </desc> + </func> + <func> + <name name="finish_loading" arity="1"/> + <fsummary>Finish loading a list of prepared modules atomically</fsummary> + <desc> + <p>Tries to load code for all modules that have been previously + prepared by + <seealso marker="#prepare_loading/1">prepare_loading/1</seealso>. + The loading occurs atomically, meaning that + either all modules are loaded at the same time, or + none of the modules are loaded.</p> + <p>This function can fail with one of the following error reasons:</p> + <taglist> + <tag><c>not_purged</c></tag> + <item> + <p>The object code can not be loaded because an old version + of the code already exists.</p> + </item> + <tag><c>sticky_directory</c></tag> + <item> + <p>The object code resides in a sticky directory.</p> + </item> + <tag><c>pending_on_load</c></tag> + <item> + <p>A previously loaded module contains an + <c>-on_load</c> function that never finished.</p> + </item> + </taglist> + </desc> + </func> + <func> + <name name="ensure_modules_loaded" arity="1"/> + <fsummary>Ensure that a list of modules is loaded</fsummary> + <desc> + <p>Tries to load any modules not already loaded in the list + <c><anno>Modules</anno></c> in the same way as + <seealso marker="#load_file/1">load_file/1</seealso>.</p> + <p>Returns <c>ok</c> if successful, or + <c>{error,[{Module,Reason}]}</c> if loading of some modules fails. + See <seealso marker="#error_reasons">Error Reasons for Code-Loading Functions</seealso> for a description of other possible error reasons.</p> + </desc> + </func> + <func> <name name="delete" arity="1"/> <fsummary>Removes current code for a module</fsummary> <desc> diff --git a/lib/kernel/doc/src/heart.xml b/lib/kernel/doc/src/heart.xml index b9fad17ce1..9da4773f2d 100644 --- a/lib/kernel/doc/src/heart.xml +++ b/lib/kernel/doc/src/heart.xml @@ -118,6 +118,13 @@ <p>In the following descriptions, all function fails with reason <c>badarg</c> if <c>heart</c> is not started.</p> </description> + + <datatypes> + <datatype> + <name name="heart_option"/> + </datatype> + </datatypes> + <funcs> <func> <name name="set_cmd" arity="1"/> @@ -154,6 +161,62 @@ the empty string will be returned.</p> </desc> </func> + + <func> + <name name="set_callback" arity="2"/> + <fsummary>Set a validation callback</fsummary> + <desc> + <p> This validation callback will be executed before any heartbeat sent + to the port program. For the validation to succeed it needs to return + with the value <c>ok</c>. + </p> + <p> An exception within the callback will be treated as a validation failure. </p> + <p> The callback will be removed if the system reboots. </p> + </desc> + </func> + <func> + <name name="clear_callback" arity="0"/> + <fsummary>Clear the validation callback</fsummary> + <desc> + <p>Removes the validation callback call before heartbeats.</p> + </desc> + </func> + <func> + <name name="get_callback" arity="0"/> + <fsummary>Get the validation callback</fsummary> + <desc> + <p>Get the validation callback. If the callback is cleared, <c>none</c> will be returned.</p> + </desc> + </func> + + <func> + <name name="set_options" arity="1"/> + <fsummary>Set a list of options</fsummary> + <desc> + <p> Valid options <c>set_options</c> are: </p> + <taglist> + <tag><c>check_schedulers</c></tag> + <item> + <p>If enabled, a signal will be sent to each scheduler to check its + responsiveness. The system check occurs before any heartbeat sent + to the port program. If any scheduler is not responsive enough the + heart program will not receive its heartbeat and thus eventually terminate the node. + </p> + </item> + </taglist> + <p> Returns with the value <c>ok</c> if the options are valid.</p> + </desc> + </func> + <func> + <name name="get_options" arity="0"/> + <fsummary>Get the temporary reboot command</fsummary> + <desc> + <p>Returns <c>{ok, Options}</c> where <c>Options</c> is a list of current options enabled for heart. + If the callback is cleared, <c>none</c> will be returned.</p> + </desc> + </func> + + </funcs> </erlref> diff --git a/lib/kernel/examples/uds_dist/c_src/uds_drv.c b/lib/kernel/examples/uds_dist/c_src/uds_drv.c index e32ad69adf..8c028ba910 100644 --- a/lib/kernel/examples/uds_dist/c_src/uds_drv.c +++ b/lib/kernel/examples/uds_dist/c_src/uds_drv.c @@ -957,28 +957,24 @@ static void put_packet_length(char *b, int len) /* ** Malloc wrappers -** Note! -** The function erl_exit is actually not a pert of the -** driver interface, but it is very nice to use if one wants to halt -** with a core and an erlang crash dump. */ static void *my_malloc(size_t size) { - void erl_exit(int, char *, ...); void *ptr; if ((ptr = driver_alloc(size)) == NULL) { - erl_exit(1,"Could not allocate %lu bytes of memory",(unsigned long) size); + fprintf(stderr, "Could not allocate %lu bytes of memory",(unsigned long) size); + abort(); } return ptr; } static void *my_realloc(void *ptr, size_t size) { - void erl_exit(int, char *, ...); void *nptr; if ((nptr = driver_realloc(ptr, size)) == NULL) { - erl_exit(1,"Could not reallocate %lu bytes of memory",(unsigned long) size); + fprintf(stderr, "Could not reallocate %lu bytes of memory",(unsigned long) size); + abort(); } return nptr; } diff --git a/lib/kernel/src/code.erl b/lib/kernel/src/code.erl index 59e226df43..0882cb170c 100644 --- a/lib/kernel/src/code.erl +++ b/lib/kernel/src/code.erl @@ -28,11 +28,15 @@ get_path/0, load_file/1, ensure_loaded/1, + ensure_modules_loaded/1, load_abs/1, load_abs/2, load_binary/3, load_native_partial/2, load_native_sticky/3, + atomic_load/1, + prepare_loading/1, + finish_loading/1, delete/1, purge/1, soft_purge/1, @@ -71,6 +75,7 @@ -deprecated({rehash,0,next_major_release}). -export_type([load_error_rsn/0, load_ret/0]). +-export_type([prepared_code/0]). -include_lib("kernel/include/file.hrl"). @@ -88,6 +93,11 @@ -type loaded_ret_atoms() :: 'cover_compiled' | 'preloaded'. -type loaded_filename() :: (Filename :: file:filename()) | loaded_ret_atoms(). +-define(PREPARED, '$prepared$'). +-opaque prepared_code() :: + {?PREPARED,[{module(),{binary(),string(),_}}]}. + + %%% BIFs -export([get_chunk/2, is_module_native/1, make_stub_module/3, module_md5/1]). @@ -303,6 +313,313 @@ rehash() -> -spec get_mode() -> 'embedded' | 'interactive'. get_mode() -> call(get_mode). +%%% +%%% Loading of several modules in parallel. +%%% + +-spec ensure_modules_loaded([Module]) -> + 'ok' | {'error',[{Module,What}]} when + Module :: module(), + What :: badfile | nofile | on_load_failure. + +ensure_modules_loaded(Modules) when is_list(Modules) -> + case prepare_ensure(Modules, []) of + Ms when is_list(Ms) -> + ensure_modules_loaded_1(Ms); + error -> + error(function_clause, [Modules]) + end. + +ensure_modules_loaded_1(Ms0) -> + Ms = lists:usort(Ms0), + {Prep,Error0} = load_mods(Ms), + {OnLoad,Normal} = partition_on_load(Prep), + Error1 = case finish_loading(Normal, true) of + ok -> Error0; + {error,Err} -> Err ++ Error0 + end, + ensure_modules_loaded_2(OnLoad, Error1). + +ensure_modules_loaded_2([{M,_}|Ms], Errors) -> + case ensure_loaded(M) of + {module,M} -> + ensure_modules_loaded_2(Ms, Errors); + {error,Err} -> + ensure_modules_loaded_2(Ms, [{M,Err}|Errors]) + end; +ensure_modules_loaded_2([], []) -> + ok; +ensure_modules_loaded_2([], [_|_]=Errors) -> + {error,Errors}. + +prepare_ensure([M|Ms], Acc) when is_atom(M) -> + case erlang:module_loaded(M) of + true -> + prepare_ensure(Ms, Acc); + false -> + prepare_ensure(Ms, [M|Acc]) + end; +prepare_ensure([], Acc) -> + Acc; +prepare_ensure(_, _) -> + error. + +-spec atomic_load(Modules) -> 'ok' | {'error',[{Module,What}]} when + Modules :: [Module | {Module, Filename, Binary}], + Module :: module(), + Filename :: file:filename(), + Binary :: binary(), + What :: 'badfile' | 'nofile' | 'on_load_not_allowed' | 'duplicated' | + 'not_purged' | 'sticky_directory' | 'pending_on_load'. + +atomic_load(Modules) -> + case do_prepare_loading(Modules) of + {ok,Prep} -> + finish_loading(Prep, false); + {error,_}=Error -> + Error; + badarg -> + error(function_clause, [Modules]) + end. + +-spec prepare_loading(Modules) -> + {'ok',Prepared} | {'error',[{Module,What}]} when + Modules :: [Module | {Module, Filename, Binary}], + Module :: module(), + Filename :: file:filename(), + Binary :: binary(), + Prepared :: prepared_code(), + What :: 'badfile' | 'nofile' | 'on_load_not_allowed' | 'duplicated'. + +prepare_loading(Modules) -> + case do_prepare_loading(Modules) of + {ok,Prep} -> + {ok,{?PREPARED,Prep}}; + {error,_}=Error -> + Error; + badarg -> + error(function_clause, [Modules]) + end. + +-spec finish_loading(Prepared) -> 'ok' | {'error',[{Module,What}]} when + Prepared :: prepared_code(), + Module :: module(), + What :: 'not_purged' | 'sticky_directory' | 'pending_on_load'. + +finish_loading({?PREPARED,Prepared}=Arg) when is_list(Prepared) -> + case verify_prepared(Prepared) of + ok -> + finish_loading(Prepared, false); + error -> + error(function_clause, [Arg]) + end. + +partition_load([Item|T], Bs, Ms) -> + case Item of + {M,File,Bin} when is_atom(M) andalso + is_list(File) andalso + is_binary(Bin) -> + partition_load(T, [Item|Bs], Ms); + M when is_atom(M) -> + partition_load(T, Bs, [Item|Ms]); + _ -> + error + end; +partition_load([], Bs, Ms) -> + {Bs,Ms}. + +do_prepare_loading(Modules) -> + case partition_load(Modules, [], []) of + {ModBins,Ms} -> + case prepare_loading_1(ModBins, Ms) of + {error,_}=Error -> + Error; + Prep when is_list(Prep) -> + {ok,Prep} + end; + error -> + badarg + end. + +prepare_loading_1(ModBins, Ms) -> + %% erlang:finish_loading/1 *will* detect duplicates. + %% However, we want to detect all errors that can be detected + %% by only examining the input data before call the LastAction + %% fun. + case prepare_check_uniq(ModBins, Ms) of + ok -> + prepare_loading_2(ModBins, Ms); + Error -> + Error + end. + +prepare_loading_2(ModBins, Ms) -> + {Prep0,Error0} = load_bins(ModBins), + {Prep1,Error1} = load_mods(Ms), + case Error0 ++ Error1 of + [] -> + prepare_loading_3(Prep0 ++ Prep1); + [_|_]=Error -> + {error,Error} + end. + +prepare_loading_3(Prep) -> + case partition_on_load(Prep) of + {[_|_]=OnLoad,_} -> + Error = [{M,on_load_not_allowed} || {M,_} <- OnLoad], + {error,Error}; + {[],_} -> + Prep + end. + +prepare_check_uniq([{M,_,_}|T], Ms) -> + prepare_check_uniq(T, [M|Ms]); +prepare_check_uniq([], Ms) -> + prepare_check_uniq_1(lists:sort(Ms), []). + +prepare_check_uniq_1([M|[M|_]=Ms], Acc) -> + prepare_check_uniq_1(Ms, [{M,duplicated}|Acc]); +prepare_check_uniq_1([_|Ms], Acc) -> + prepare_check_uniq_1(Ms, Acc); +prepare_check_uniq_1([], []) -> + ok; +prepare_check_uniq_1([], [_|_]=Errors) -> + {error,Errors}. + +partition_on_load(Prep) -> + P = fun({_,{Bin,_,_}}) -> + erlang:has_prepared_code_on_load(Bin) + end, + lists:partition(P, Prep). + +verify_prepared([{M,{Prep,Name,_Native}}|T]) + when is_atom(M), is_binary(Prep), is_list(Name) -> + try erlang:has_prepared_code_on_load(Prep) of + false -> + verify_prepared(T); + _ -> + error + catch + error:_ -> + error + end; +verify_prepared([]) -> + ok; +verify_prepared(_) -> + error. + +finish_loading(Prepared0, EnsureLoaded) -> + Prepared = [{M,{Bin,File}} || {M,{Bin,File,_}} <- Prepared0], + Native0 = [{M,Code} || {M,{_,_,Code}} <- Prepared0, + Code =/= undefined], + case call({finish_loading,Prepared,EnsureLoaded}) of + ok -> + finish_loading_native(Native0); + {error,Errors}=E when EnsureLoaded -> + S0 = sofs:relation(Errors), + S1 = sofs:domain(S0), + R0 = sofs:relation(Native0), + R1 = sofs:drestriction(R0, S1), + Native = sofs:to_external(R1), + finish_loading_native(Native), + E; + {error,_}=E -> + E + end. + +finish_loading_native([{Mod,Code}|Ms]) -> + _ = load_native_partial(Mod, Code), + finish_loading_native(Ms); +finish_loading_native([]) -> + ok. + +load_mods([]) -> + {[],[]}; +load_mods(Mods) -> + Path = get_path(), + F = prepare_loading_fun(), + {ok,{Succ,Error0}} = erl_prim_loader:get_modules(Mods, F, Path), + Error = [case E of + badfile -> {M,E}; + _ -> {M,nofile} + end || {M,E} <- Error0], + {Succ,Error}. + +load_bins([]) -> + {[],[]}; +load_bins(BinItems) -> + F = prepare_loading_fun(), + do_par(F, BinItems). + +-type prep_fun_type() :: fun((module(), file:filename(), binary()) -> + {ok,_} | {error,_}). + +-spec prepare_loading_fun() -> prep_fun_type(). + +prepare_loading_fun() -> + GetNative = get_native_fun(), + fun(Mod, FullName, Beam) -> + case erlang:prepare_loading(Mod, Beam) of + Prepared when is_binary(Prepared) -> + {ok,{Prepared,FullName,GetNative(Beam)}}; + {error,_}=Error -> + Error + end + end. + +get_native_fun() -> + Architecture = erlang:system_info(hipe_architecture), + try hipe_unified_loader:chunk_name(Architecture) of + ChunkTag -> + fun(Beam) -> code:get_chunk(Beam, ChunkTag) end + catch _:_ -> + fun(_) -> undefined end + end. + +do_par(Fun, L) -> + {_,Ref} = spawn_monitor(do_par_fun(Fun, L)), + receive + {'DOWN',Ref,process,_,Res} -> + Res + end. + +-spec do_par_fun(prep_fun_type(), list()) -> fun(() -> no_return()). + +do_par_fun(Fun, L) -> + fun() -> + _ = [spawn_monitor(do_par_fun_2(Fun, Item)) || + Item <- L], + exit(do_par_recv(length(L), [], [])) + end. + +-spec do_par_fun_2(prep_fun_type(), + {module(),file:filename(),binary()}) -> + fun(() -> no_return()). + +do_par_fun_2(Fun, Item) -> + fun() -> + {Mod,Filename,Bin} = Item, + try Fun(Mod, Filename, Bin) of + {ok,Res} -> + exit({good,{Mod,Res}}); + {error,Error} -> + exit({bad,{Mod,Error}}) + catch + _:Error -> + exit({bad,{Mod,Error}}) + end + end. + +do_par_recv(0, Good, Bad) -> + {Good,Bad}; +do_par_recv(N, Good, Bad) -> + receive + {'DOWN',_,process,_,{good,Res}} -> + do_par_recv(N-1, [Res|Good], Bad); + {'DOWN',_,process,_,{bad,Res}} -> + do_par_recv(N-1, Good, [Res|Bad]) + end. + %%----------------------------------------------------------------- call(Req) -> diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl index b52def8777..6262407354 100644 --- a/lib/kernel/src/code_server.erl +++ b/lib/kernel/src/code_server.erl @@ -28,11 +28,10 @@ ]). -include_lib("kernel/include/file.hrl"). +-include_lib("stdlib/include/ms_transform.hrl"). -import(lists, [foreach/2]). --define(ANY_NATIVE_CODE_LOADED, any_native_code_loaded). - -type on_load_item() :: {reference(),module(),file:name_all(),[pid()]}. -record(state, {supervisor :: pid(), @@ -90,8 +89,6 @@ init(Ref, Parent, [Root,Mode]) -> namedb = init_namedb(Path), mode = Mode}, - put(?ANY_NATIVE_CODE_LOADED, false), - Parent ! {Ref,{ok,self()}}, loop(State). @@ -289,14 +286,14 @@ handle_call({load_binary,Mod,File,Bin}, Caller, S) when is_atom(Mod) -> handle_call({load_native_partial,Mod,Bin}, {_From,_Tag}, S) -> Architecture = erlang:system_info(hipe_architecture), Result = (catch hipe_unified_loader:load(Mod, Bin, Architecture)), - Status = hipe_result_to_status(Result), + Status = hipe_result_to_status(Result, S), {reply,Status,S}; handle_call({load_native_sticky,Mod,Bin,WholeModule}, {_From,_Tag}, S) -> Architecture = erlang:system_info(hipe_architecture), Result = (catch hipe_unified_loader:load_module(Mod, Bin, WholeModule, Architecture)), - Status = hipe_result_to_status(Result), + Status = hipe_result_to_status(Result, S), {reply,Status,S}; handle_call({ensure_loaded,Mod}, Caller, St) when is_atom(Mod) -> @@ -356,6 +353,9 @@ handle_call({set_primary_archive, File, ArchiveBin, FileInfo, ParserFun}, {_From handle_call(get_mode, {_From,_Tag}, S=#state{mode=Mode}) -> {reply, Mode, S}; +handle_call({finish_loading,Prepared,EnsureLoaded}, {_,_}, S) -> + {reply,finish_loading(Prepared, EnsureLoaded, S),S}; + handle_call(Other,{_From,_Tag}, S) -> error_msg(" ** Codeserver*** ignoring ~w~n ",[Other]), {noreply,S}. @@ -1107,8 +1107,7 @@ try_load_module_2(File, Mod, Bin, Caller, Architecture, #state{moddb=Db}=St) -> case catch hipe_unified_loader:load_native_code(Mod, Bin, Architecture) of {module,Mod} = Module -> - put(?ANY_NATIVE_CODE_LOADED, true), - ets:insert(Db, {Mod,File}), + ets:insert(Db, [{{native,Mod},true},{Mod,File}]), {reply,Module,St}; no_native -> try_load_module_3(File, Mod, Bin, Caller, Architecture, St); @@ -1122,7 +1121,7 @@ try_load_module_3(File, Mod, Bin, Caller, Architecture, case erlang:load_module(Mod, Bin) of {module,Mod} = Module -> ets:insert(Db, {Mod,File}), - post_beam_load(Mod, Architecture), + post_beam_load([Mod], Architecture, St), {reply,Module,St}; {error,on_load} -> handle_on_load(Mod, File, Caller, St); @@ -1131,23 +1130,24 @@ try_load_module_3(File, Mod, Bin, Caller, Architecture, {reply,Error,St} end. -hipe_result_to_status(Result) -> +hipe_result_to_status(Result, #state{moddb=Db}) -> case Result of - {module,_} -> - put(?ANY_NATIVE_CODE_LOADED, true), + {module,Mod} -> + ets:insert(Db, [{{native,Mod},true}]), Result; _ -> {error,Result} end. -post_beam_load(Mod, Architecture) -> +post_beam_load(_, undefined, _) -> + %% HiPE is disabled. + ok; +post_beam_load(Mods0, _Architecture, #state{moddb=Db}) -> %% post_beam_load/2 can potentially be very expensive because it - %% blocks multi-scheduling; thus we want to avoid the call if we - %% know that it is not needed. - case get(?ANY_NATIVE_CODE_LOADED) of - true -> hipe_unified_loader:post_beam_load(Mod, Architecture); - false -> ok - end. + %% blocks multi-scheduling. Therefore, we only want to call + %% it with modules that are known to have native code loaded. + Mods = [M || M <- Mods0, ets:member(Db, {native,M})], + hipe_unified_loader:post_beam_load(Mods). int_list([H|T]) when is_integer(H) -> int_list(T); int_list([_|_]) -> false; @@ -1221,7 +1221,6 @@ absname_vr([[X, $:]|Name], _, _AbsBase) -> absname(filename:join(Name), Dcwd). - is_loaded(M, Db) -> case ets:lookup(Db, M) of [{M,File}] -> {file,File}; @@ -1236,6 +1235,64 @@ do_soft_purge(Mod) -> erts_code_purger:soft_purge(Mod). +%%% +%%% Loading of multiple modules in parallel. +%%% + +finish_loading(Prepared, EnsureLoaded, #state{moddb=Db}=St) -> + Ps = [fun(L) -> finish_loading_ensure(L, EnsureLoaded) end, + fun(L) -> abort_if_pending_on_load(L, St) end, + fun(L) -> abort_if_sticky(L, Db) end, + fun(L) -> do_finish_loading(L, St) end], + run(Ps, Prepared). + +finish_loading_ensure(Prepared, true) -> + {ok,[P || {M,_}=P <- Prepared, not erlang:module_loaded(M)]}; +finish_loading_ensure(Prepared, false) -> + {ok,Prepared}. + +abort_if_pending_on_load(L, #state{on_load=[]}) -> + {ok,L}; +abort_if_pending_on_load(L, #state{on_load=OnLoad}) -> + Pending = [{M,pending_on_load} || + {M,_} <- L, + lists:keymember(M, 2, OnLoad)], + case Pending of + [] -> {ok,L}; + [_|_] -> {error,Pending} + end. + +abort_if_sticky(L, Db) -> + Sticky = [{M,sticky_directory} || {M,_} <- L, is_sticky(M, Db)], + case Sticky of + [] -> {ok,L}; + [_|_] -> {error,Sticky} + end. + +do_finish_loading(Prepared, #state{moddb=Db}=St) -> + MagicBins = [B || {_,{B,_}} <- Prepared], + case erlang:finish_loading(MagicBins) of + ok -> + MFs = [{M,F} || {M,{_,F}} <- Prepared], + true = ets:insert(Db, MFs), + Ms = [M || {M,_} <- MFs], + Architecture = erlang:system_info(hipe_architecture), + post_beam_load(Ms, Architecture, St), + ok; + {Reason,Ms} -> + {error,[{M,Reason} || M <- Ms]} + end. + +run([F], Data) -> + F(Data); +run([F|Fs], Data0) -> + case F(Data0) of + {ok,Data} -> + run(Fs, Data); + {error,_}=Error -> + Error + end. + %% ------------------------------------------------------- %% The on_load functionality. %% ------------------------------------------------------- @@ -1317,18 +1374,8 @@ finish_on_load_report(Mod, Term) -> %% ------------------------------------------------------- all_loaded(Db) -> - all_l(Db, ets:slot(Db, 0), 1, []). - -all_l(_Db, '$end_of_table', _, Acc) -> - Acc; -all_l(Db, ModInfo, N, Acc) -> - NewAcc = strip_mod_info(ModInfo,Acc), - all_l(Db, ets:slot(Db, N), N + 1, NewAcc). - - -strip_mod_info([{{sticky,_},_}|T], Acc) -> strip_mod_info(T, Acc); -strip_mod_info([H|T], Acc) -> strip_mod_info(T, [H|Acc]); -strip_mod_info([], Acc) -> Acc. + Ms = ets:fun2ms(fun({M,_}=T) when is_atom(M) -> T end), + ets:select(Db, Ms). -spec error_msg(io:format(), [term()]) -> 'ok'. error_msg(Format, Args) -> diff --git a/lib/kernel/src/erl_epmd.erl b/lib/kernel/src/erl_epmd.erl index 55ce9a7e64..c6202dd796 100644 --- a/lib/kernel/src/erl_epmd.erl +++ b/lib/kernel/src/erl_epmd.erl @@ -32,7 +32,7 @@ %% External exports -export([start/0, start_link/0, stop/0, port_please/2, port_please/3, names/0, names/1, - register_node/2, open/0, open/1, open/2]). + register_node/2, register_node/3, open/0, open/1, open/2]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, @@ -102,7 +102,9 @@ names(EpmdAddr) -> register_node(Name, PortNo) -> - gen_server:call(erl_epmd, {register, Name, PortNo}, infinity). + register_node(Name, PortNo, inet). +register_node(Name, PortNo, Family) -> + gen_server:call(erl_epmd, {register, Name, PortNo, Family}, infinity). %%%---------------------------------------------------------------------- %%% Callback functions from gen_server @@ -120,10 +122,10 @@ init(_) -> -spec handle_call(calls(), term(), state()) -> {'reply', term(), state()} | {'stop', 'shutdown', 'ok', state()}. -handle_call({register, Name, PortNo}, _From, State) -> +handle_call({register, Name, PortNo, Family}, _From, State) -> case State#state.socket of P when P < 0 -> - case do_register_node(Name, PortNo) of + case do_register_node(Name, PortNo, Family) of {alive, Socket, Creation} -> S = State#state{socket = Socket, port_no = PortNo, @@ -206,8 +208,12 @@ open({A,B,C,D,E,F,G,H}=EpmdAddr, Timeout) when ?ip6(A,B,C,D,E,F,G,H) -> close(Socket) -> gen_tcp:close(Socket). -do_register_node(NodeName, TcpPort) -> - case open() of +do_register_node(NodeName, TcpPort, Family) -> + Localhost = case Family of + inet -> open({127,0,0,1}); + inet6 -> open({0,0,0,0,0,0,0,1}) + end, + case Localhost of {ok, Socket} -> Name = to_string(NodeName), Extra = "", diff --git a/lib/kernel/src/heart.erl b/lib/kernel/src/heart.erl index 137fad706f..eea78aabdf 100644 --- a/lib/kernel/src/heart.erl +++ b/lib/kernel/src/heart.erl @@ -34,7 +34,11 @@ %%% %%% It recognizes the flag '-heart' %%%-------------------------------------------------------------------- --export([start/0, init/2, set_cmd/1, clear_cmd/0, get_cmd/0, cycle/0]). +-export([start/0, init/2, + set_cmd/1, clear_cmd/0, get_cmd/0, + set_callback/2, clear_callback/0, get_callback/0, + set_options/1, get_options/0, + cycle/0]). -define(START_ACK, 1). -define(HEART_BEAT, 2). @@ -49,6 +53,16 @@ -define(CYCLE_TIMEOUT, 10000). -define(HEART_PORT_NAME, heart_port). +%% valid heart options +-define(SCHEDULER_CHECK_OPT, check_schedulers). + +-type heart_option() :: ?SCHEDULER_CHECK_OPT. + +-record(state,{port :: port(), + cmd :: [] | binary(), + options :: [heart_option()], + callback :: 'undefined' | {atom(), atom()}}). + %%--------------------------------------------------------------------- -spec start() -> 'ignore' | {'error', term()} | {'ok', pid()}. @@ -81,11 +95,11 @@ wait_for_init_ack(From) -> init(Starter, Parent) -> process_flag(trap_exit, true), process_flag(priority, max), - register(heart, self()), + register(?MODULE, self()), case catch start_portprogram() of {ok, Port} -> Starter ! {ok, self()}, - loop(Parent, Port, ""); + loop(Parent, #state{port=Port, cmd=[], options=[]}); no_heart -> Starter ! {no_heart, self()}; error -> @@ -96,33 +110,68 @@ init(Starter, Parent) -> Cmd :: string(). set_cmd(Cmd) -> - heart ! {self(), set_cmd, Cmd}, + ?MODULE ! {self(), set_cmd, Cmd}, wait(). -spec get_cmd() -> {ok, Cmd} when Cmd :: string(). get_cmd() -> - heart ! {self(), get_cmd}, + ?MODULE ! {self(), get_cmd}, wait(). -spec clear_cmd() -> ok. clear_cmd() -> - heart ! {self(), clear_cmd}, + ?MODULE ! {self(), clear_cmd}, + wait(). + +-spec set_callback(Module,Function) -> 'ok' | {'error', {'bad_callback', {Module, Function}}} when + Module :: atom(), + Function :: atom(). + +set_callback(Module, Function) -> + ?MODULE ! {self(), set_callback, {Module,Function}}, + wait(). + +-spec get_callback() -> {'ok', {Module, Function}} | 'none' when + Module :: atom(), + Function :: atom(). + +get_callback() -> + ?MODULE ! {self(), get_callback}, + wait(). + +-spec clear_callback() -> ok. + +clear_callback() -> + ?MODULE ! {self(), clear_callback}, + wait(). + +-spec set_options(Options) -> 'ok' | {'error', {'bad_options', Options}} when + Options :: [heart_option()]. + +set_options(Options) -> + ?MODULE ! {self(), set_options, Options}, wait(). +-spec get_options() -> {'ok', Options} | 'none' when + Options :: [atom()]. + +get_options() -> + ?MODULE ! {self(), get_options}, + wait(). %%% Should be used solely by the release handler!!!!!!! -spec cycle() -> 'ok' | {'error', term()}. cycle() -> - heart ! {self(), cycle}, + ?MODULE ! {self(), cycle}, wait(). wait() -> receive - {heart, Res} -> + {?MODULE, Res} -> Res end. @@ -182,8 +231,8 @@ wait_ack(Port) -> {error, Reason} end. -loop(Parent, Port, Cmd) -> - _ = send_heart_beat(Port), +loop(Parent, #state{port=Port}=S) -> + _ = send_heart_beat(S), receive {From, set_cmd, NewCmd0} -> Enc = file:native_name_encoding(), @@ -191,37 +240,72 @@ loop(Parent, Port, Cmd) -> NewCmd when is_binary(NewCmd), byte_size(NewCmd) < 2047 -> _ = send_heart_cmd(Port, NewCmd), _ = wait_ack(Port), - From ! {heart, ok}, - loop(Parent, Port, NewCmd); + From ! {?MODULE, ok}, + loop(Parent, S#state{cmd=NewCmd}); _ -> - From ! {heart, {error, {bad_cmd, NewCmd0}}}, - loop(Parent, Port, Cmd) + From ! {?MODULE, {error, {bad_cmd, NewCmd0}}}, + loop(Parent, S) end; {From, clear_cmd} -> - From ! {heart, ok}, - _ = send_heart_cmd(Port, ""), + From ! {?MODULE, ok}, + _ = send_heart_cmd(Port, []), _ = wait_ack(Port), - loop(Parent, Port, ""); + loop(Parent, S#state{cmd = []}); {From, get_cmd} -> - From ! {heart, get_heart_cmd(Port)}, - loop(Parent, Port, Cmd); + From ! {?MODULE, get_heart_cmd(Port)}, + loop(Parent, S); + {From, set_callback, Callback} -> + case Callback of + {M,F} when is_atom(M), is_atom(F) -> + From ! {?MODULE, ok}, + loop(Parent, S#state{callback=Callback}); + _ -> + From ! {?MODULE, {error, {bad_callback, Callback}}}, + loop(Parent, S) + end; + {From, get_callback} -> + Res = case S#state.callback of + undefined -> none; + Cb -> {ok, Cb} + end, + From ! {?MODULE, Res}, + loop(Parent, S); + {From, clear_callback} -> + From ! {?MODULE, ok}, + loop(Parent, S#state{callback=undefined}); + {From, set_options, Options} -> + case validate_options(Options) of + Validated when is_list(Validated) -> + From ! {?MODULE, ok}, + loop(Parent, S#state{options=Validated}); + _ -> + From ! {?MODULE, {error, {bad_options, Options}}}, + loop(Parent, S) + end; + {From, get_options} -> + Res = case S#state.options of + [] -> none; + Cb -> {ok, Cb} + end, + From ! {?MODULE, Res}, + loop(Parent, S); {From, cycle} -> %% Calls back to loop - do_cycle_port_program(From, Parent, Port, Cmd); + do_cycle_port_program(From, Parent, S); {'EXIT', Parent, shutdown} -> no_reboot_shutdown(Port); {'EXIT', Parent, Reason} -> exit(Port, Reason), exit(Reason); {'EXIT', Port, badsig} -> % we can ignore badsig-messages! - loop(Parent, Port, Cmd); + loop(Parent, S); {'EXIT', Port, _Reason} -> - exit({port_terminated, {heart, loop, [Parent, Port, Cmd]}}); + exit({port_terminated, {?MODULE, loop, [Parent, S]}}); _ -> - loop(Parent, Port, Cmd) + loop(Parent, S) after ?TIMEOUT -> - loop(Parent, Port, Cmd) + loop(Parent, S) end. -spec no_reboot_shutdown(port()) -> no_return(). @@ -233,36 +317,44 @@ no_reboot_shutdown(Port) -> exit(normal) end. -do_cycle_port_program(Caller, Parent, Port, Cmd) -> +validate_options(Opts) -> validate_options(Opts,[]). +validate_options([],Res) -> Res; +validate_options([?SCHEDULER_CHECK_OPT=Opt|Opts],Res) -> validate_options(Opts,[Opt|Res]); +validate_options(_,_) -> error. + +do_cycle_port_program(Caller, Parent, #state{port=Port} = S) -> unregister(?HEART_PORT_NAME), case catch start_portprogram() of {ok, NewPort} -> _ = send_shutdown(Port), receive {'EXIT', Port, _Reason} -> - _ = send_heart_cmd(NewPort, Cmd), - Caller ! {heart, ok}, - loop(Parent, NewPort, Cmd) + _ = send_heart_cmd(NewPort, S#state.cmd), + Caller ! {?MODULE, ok}, + loop(Parent, S#state{port=NewPort}) after ?CYCLE_TIMEOUT -> %% Huh! Two heart port programs running... %% well, the old one has to be sick not to respond %% so we'll settle for the new one... - _ = send_heart_cmd(NewPort, Cmd), - Caller ! {heart, {error, stop_error}}, - loop(Parent, NewPort, Cmd) + _ = send_heart_cmd(NewPort, S#state.cmd), + Caller ! {?MODULE, {error, stop_error}}, + loop(Parent, S#state{port=NewPort}) end; no_heart -> - Caller ! {heart, {error, no_heart}}, - loop(Parent, Port, Cmd); + Caller ! {?MODULE, {error, no_heart}}, + loop(Parent, S); error -> - Caller ! {heart, {error, start_error}}, - loop(Parent, Port, Cmd) + Caller ! {?MODULE, {error, start_error}}, + loop(Parent, S) end. %% "Beates" the heart once. -send_heart_beat(Port) -> Port ! {self(), {command, [?HEART_BEAT]}}. +send_heart_beat(#state{port=Port, callback=Cb, options=Opts}) -> + ok = check_system(Opts), + ok = check_callback(Cb), + Port ! {self(), {command, [?HEART_BEAT]}}. %% Set a new HEART_COMMAND. -dialyzer({no_improper_lists, send_heart_cmd/2}). @@ -278,6 +370,24 @@ get_heart_cmd(Port) -> {ok, Cmd} end. +check_system([]) -> ok; +check_system([?SCHEDULER_CHECK_OPT|Opts]) -> + ok = erts_internal:system_check(schedulers), + check_system(Opts). + +%% validate system by performing a check before the heartbeat +%% return 'ok' if everything is alright. +%% Terminate if with reason if something is a miss. +%% It is fine to timeout in the callback, in fact that is the intention +%% if something goes wront -> no heartbeat. + +check_callback(Callback) -> + case Callback of + undefined -> ok; + {M,F} -> + erlang:apply(M,F,[]) + end. + %% Sends shutdown command to the port. send_shutdown(Port) -> Port ! {self(), {command, [?SHUT_DOWN]}}. diff --git a/lib/kernel/src/hipe_unified_loader.erl b/lib/kernel/src/hipe_unified_loader.erl index ddbbc548dd..73fcb2469c 100644 --- a/lib/kernel/src/hipe_unified_loader.erl +++ b/lib/kernel/src/hipe_unified_loader.erl @@ -44,7 +44,7 @@ -export([chunk_name/1, %% Only the code and code_server modules may call the entries below! load_native_code/3, - post_beam_load/2, + post_beam_load/1, load_module/4, load/3]). @@ -120,15 +120,15 @@ load_native_code(Mod, Bin, Architecture) when is_atom(Mod), is_binary(Bin) -> %%======================================================================== --spec post_beam_load(atom(), hipe_architecture()) -> 'ok'. +-spec post_beam_load([module()]) -> 'ok'. -%% does nothing on a hipe-disabled system -post_beam_load(_Mod, undefined) -> +post_beam_load([])-> ok; -post_beam_load(Mod, _) when is_atom(Mod) -> +post_beam_load([_|_]=Mods) -> erlang:system_flag(multi_scheduling, block), try - patch_to_emu(Mod) + _ = [patch_to_emu(Mod) || Mod <- Mods], + ok after erlang:system_flag(multi_scheduling, unblock) end, diff --git a/lib/kernel/src/kernel.appup.src b/lib/kernel/src/kernel.appup.src index 860d3640d0..a13819a183 100644 --- a/lib/kernel/src/kernel.appup.src +++ b/lib/kernel/src/kernel.appup.src @@ -18,9 +18,9 @@ %% %CopyrightEnd% {"%VSN%", %% Up from - max one major revision back - [{<<"4\\.[0-1](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.* - {<<"3\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-17 + [{<<"5\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.* + {<<"4\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-18.* %% Down to - max one major revision back - [{<<"4\\.[0-1](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.* - {<<"3\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-17 + [{<<"5\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.* + {<<"4\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-18.* }. diff --git a/lib/kernel/test/Makefile b/lib/kernel/test/Makefile index ba40dd3168..7b233741e0 100644 --- a/lib/kernel/test/Makefile +++ b/lib/kernel/test/Makefile @@ -79,7 +79,8 @@ MODULES= \ zlib_SUITE \ loose_node \ sendfile_SUITE \ - standard_error_SUITE + standard_error_SUITE \ + multi_load_SUITE APP_FILES = \ appinc.app \ diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index cf8863fcd0..00f29aa8ed 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -798,7 +798,7 @@ analyse2(MFA={_,_,_}, Path, Visited0) -> analyse(FL, [MFA|Path], my_usort([MFA|Visited0]), 0). %%%% We need to check these manually... -% fun's are ok as long as they are defined locally. +%% fun's are ok as long as they are defined locally. check_funs({'$M_EXPR','$F_EXPR',_}, [{unicode,characters_to_binary_int,3}, {unicode,characters_to_binary,3}, @@ -870,6 +870,8 @@ check_funs({'$M_EXPR','$F_EXPR',1}, {hipe_unified_loader,get_refs_from,2}| _]) -> 0; check_funs({'$M_EXPR',warning_msg,2}, [{code_server,finish_on_load_report,2} | _]) -> 0; +check_funs({'$M_EXPR','$F_EXPR',1}, + [{code_server,run,2}|_]) -> 0; %% This is cheating! /raimo %% %% check_funs(This = {M,_,_}, Path) -> diff --git a/lib/kernel/test/erl_prim_loader_SUITE.erl b/lib/kernel/test/erl_prim_loader_SUITE.erl index bc14a2764d..bccca59b93 100644 --- a/lib/kernel/test/erl_prim_loader_SUITE.erl +++ b/lib/kernel/test/erl_prim_loader_SUITE.erl @@ -29,7 +29,8 @@ inet_existing/1, inet_coming_up/1, inet_disconnects/1, multiple_slaves/1, file_requests/1, local_archive/1, remote_archive/1, - primary_archive/1, virtual_dir_in_archive/1]). + primary_archive/1, virtual_dir_in_archive/1, + get_modules/1]). -export([init_per_testcase/2, end_per_testcase/2]). @@ -44,7 +45,8 @@ all() -> normalize_and_backslash, inet_existing, inet_coming_up, inet_disconnects, multiple_slaves, file_requests, local_archive, remote_archive, - primary_archive, virtual_dir_in_archive]. + primary_archive, virtual_dir_in_archive, + get_modules]. groups() -> []. @@ -109,6 +111,37 @@ get_file(Config) when is_list(Config) -> ?line error = erl_prim_loader:get_file({dummy}), ok. +get_modules(_Config) -> + MsGood = lists:sort([lists,gen_server,gb_trees,code_server]), + Ms = [certainly_not_existing|MsGood], + SuccExp = [begin + F = code:which(M), + {ok,Code} = file:read_file(F), + {M,{F,erlang:md5(Code)}} + end || M <- MsGood], + FailExp = [{certainly_not_existing,enoent}], + + Path = code:get_path(), + Process = fun(_, F, Code) -> {ok,{F,erlang:md5(Code)}} end, + {ok,{Succ,FailExp}} = erl_prim_loader:get_modules(Ms, Process, Path), + SuccExp = lists:sort(Succ), + + Name = inet_get_modules, + {ok, Node, BootPid} = complete_start_node(Name), + ThisDir = filename:dirname(code:which(?MODULE)), + true = rpc:call(Node, code, add_patha, [ThisDir]), + _ = rpc:call(Node, code, ensure_loaded, [?MODULE]), + {ok,{InetSucc,FailExp}} = rpc:call(Node, erl_prim_loader, + get_modules, [Ms,Process,Path]), + SuccExp = lists:sort(InetSucc), + + stop_node(Node), + unlink(BootPid), + exit(BootPid, kill), + + ok. + + normalize_and_backslash(Config) -> %% Test OTP-11170 case os:type() of diff --git a/lib/kernel/test/heart_SUITE.erl b/lib/kernel/test/heart_SUITE.erl index 4447475833..eb6cb06622 100644 --- a/lib/kernel/test/heart_SUITE.erl +++ b/lib/kernel/test/heart_SUITE.erl @@ -27,6 +27,8 @@ node_start_immediately_after_crash/1, node_start_soon_after_crash/1, set_cmd/1, clear_cmd/1, get_cmd/1, + callback_api/1, + options_api/1, dont_drop/1, kill_pid/1]). -export([init_per_testcase/2, end_per_testcase/2]). @@ -66,6 +68,8 @@ all() -> [ node_start_immediately_after_crash, node_start_soon_after_crash, set_cmd, clear_cmd, get_cmd, + callback_api, + options_api, kill_pid ]. @@ -358,6 +362,69 @@ get_cmd(Config) when is_list(Config) -> stop_node(Node), ok. +callback_api(Config) when is_list(Config) -> + {ok, Node} = start_check(slave, heart_test), + none = rpc:call(Node, heart, get_callback, []), + M0 = self(), + F0 = ok, + {error, {bad_callback, {M0,F0}}} = rpc:call(Node, heart, set_callback, [M0,F0]), + none = rpc:call(Node, heart, get_callback, []), + M1 = lists:duplicate(28, $a), + F1 = lists:duplicate(28, $b), + {error, {bad_callback, {M1,F1}}} = rpc:call(Node, heart, set_callback, [M1,F1]), + none = rpc:call(Node, heart, get_callback, []), + + M2 = heart_check_module, + F2 = cb_ok, + F3 = cb_error, + Code0 = generate(M2, [], [ + atom_to_list(F2) ++ "() -> ok.", + atom_to_list(F3) ++ "() -> exit(\"callback_error (as intended)\")." + ]), + {module, M2} = rpc:call(Node, erlang, load_module, [M2, Code0]), + ok = rpc:call(Node, M2, F2, []), + ok = rpc:call(Node, heart, set_callback, [M2,F2]), + {ok, {M2,F2}} = rpc:call(Node, heart, get_callback, []), + ok = rpc:call(Node, heart, clear_callback, []), + none = rpc:call(Node, heart, get_callback, []), + ok = rpc:call(Node, heart, set_callback, [M2,F2]), + {ok, {M2,F2}} = rpc:call(Node, heart, get_callback, []), + ok = rpc:call(Node, heart, set_callback, [M2,F3]), + receive {nodedown, Node} -> ok + after 5000 -> test_server:fail(node_not_killed) + end, + stop_node(Node), + ok. + +options_api(Config) when is_list(Config) -> + {ok, Node} = start_check(slave, heart_test), + none = rpc:call(Node, heart, get_options, []), + M0 = self(), + F0 = ok, + {error, {bad_options, {M0,F0}}} = rpc:call(Node, heart, set_options, [{M0,F0}]), + none = rpc:call(Node, heart, get_options, []), + Ls = lists:duplicate(28, $b), + {error, {bad_options, Ls}} = rpc:call(Node, heart, set_options, [Ls]), + none = rpc:call(Node, heart, get_options, []), + + ok = rpc:call(Node, heart, set_options, [[check_schedulers]]), + {ok, [check_schedulers]} = rpc:call(Node, heart, get_options, []), + ok = rpc:call(Node, heart, set_options, [[]]), + none = rpc:call(Node, heart, get_options, []), + + ok = rpc:call(Node, heart, set_options, [[check_schedulers]]), + {ok, [check_schedulers]} = rpc:call(Node, heart, get_options, []), + {error, {bad_options, Ls}} = rpc:call(Node, heart, set_options, [Ls]), + {ok, [check_schedulers]} = rpc:call(Node, heart, get_options, []), + + receive after 3000 -> ok end, %% wait 3 secs + + ok = rpc:call(Node, heart, set_options, [[]]), + none = rpc:call(Node, heart, get_options, []), + stop_node(Node), + ok. + + dont_drop(suite) -> %%% Removed as it may crash epmd/distribution in colourful %%% ways. While we ARE finding out WHY, it would diff --git a/lib/kernel/test/multi_load_SUITE.erl b/lib/kernel/test/multi_load_SUITE.erl new file mode 100644 index 0000000000..bb87443e36 --- /dev/null +++ b/lib/kernel/test/multi_load_SUITE.erl @@ -0,0 +1,412 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2012. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% + +-module(multi_load_SUITE). +-export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1, + init_per_group/2,end_per_group/2, + basic_atomic_load/1,basic_errors/1,sticky_dir/1, + on_load_failing/1,ensure_modules_loaded/1, + native_code/1]). + +-include_lib("common_test/include/ct.hrl"). +-include_lib("syntax_tools/include/merl.hrl"). + +suite() -> [{ct_hooks,[ts_install_cth]}]. + +all() -> + [basic_atomic_load,basic_errors,sticky_dir,on_load_failing, + ensure_modules_loaded,native_code]. + +groups() -> + []. + +init_per_suite(Config) -> + Config. + +end_per_suite(_Config) -> + ok. + +init_per_group(_GroupName, Config) -> + Config. + +end_per_group(_GroupName, Config) -> + Config. + +basic_atomic_load(Config) -> + PrivDir = proplists:get_value(priv_dir, Config), + Dir = filename:join(PrivDir, multi_load_sticky_dir), + _ = file:make_dir(Dir), + + OldPath = code:get_path(), + try + code:add_patha(Dir), + do_basic(Dir) + after + code:set_path(OldPath) + end, + + ok. + +do_basic(Dir) -> + MsVer1_0 = make_modules(5, versioned_module(1)), + MsVer1 = [{M,filename:absname(F, Dir),Bin} || {M,F,Bin} <- MsVer1_0], + _ = [ok = file:write_file(F, Bin) || {_,F,Bin} <- MsVer1], + + Ms = [M || {M,_,_} <- MsVer1], + [] = [loaded || M <- Ms, is_loaded(M)], + + ok = code:atomic_load(Ms), + _ = [1 = M:M() || M <- Ms], + _ = [F = code:which(M) || {M,F,_} <- MsVer1], + [] = [not_loaded || M <- Ms, not is_loaded(M)], + + MsVer2 = update_modules(Ms, versioned_module(2)), + {ok,Prepared} = code:prepare_loading(MsVer2), + ok = code:finish_loading(Prepared), + _ = [2 = M:M() || M <- Ms], + _ = [F = code:which(M) || {M,F,_} <- MsVer2], + [] = [not_loaded || M <- Ms, not is_loaded(M)], + + MsVer3 = update_modules(Ms, versioned_module(2)), + NotPurged = lists:sort([{M,not_purged} || M <- Ms]), + NotPurged = atomic_load_error(MsVer3, true), + + ok. + +versioned_module(Ver) -> + fun(Mod) -> + ?Q(["-module('@Mod@').\n", + "-export(['@Mod@'/0]).\n", + "'@Mod@'() -> _@Ver@.\n"]) + end. + +basic_errors(_Config) -> + atomic_load_fc([42]), + atomic_load_fc([{"mod","file","bin"}]), + + finish_loading_fc(atom), + {ok,{PrepTag,_}} = code:prepare_loading([code]), + finish_loading_fc({PrepTag,[x]}), + finish_loading_fc({PrepTag,[{m,{<<>>,"",<<>>}}]}), + Prep = prepared_with_wrong_magic_bin(), + finish_loading_fc(Prep), + + [{x,badfile}] = atomic_load_error([{x,"x",<<"bad">>}], false), + [{a,badfile},{some_nonexistent_file,nofile}] = + atomic_load_error([some_nonexistent_file,{a,"a",<<>>}], + false), + + %% Modules mentioned more than once. + Mods = make_modules(2, fun basic_module/1), + Ms = [M || {M,_,_} <- Mods], + DupMods = Mods ++ [mnesia] ++ Mods ++ [mnesia], + DupErrors0 = lists:sort([mnesia|Ms]), + DupErrors = [{M,duplicated} || M <- DupErrors0], + DupErrors = atomic_load_error(DupMods, false), + + ok. + +atomic_load_fc(L) -> + {'EXIT',{function_clause,[{code,atomic_load,[L],_}|_]}} = + (catch code:atomic_load(L)), + {'EXIT',{function_clause,[{code,prepare_loading,[L],_}|_]}} = + (catch code:prepare_loading(L)). + +finish_loading_fc(Term) -> + {'EXIT',{function_clause,[{code,finish_loading,[Term],_}|_]}} = + (catch code:finish_loading(Term)). + +prepared_with_wrong_magic_bin() -> + {ok,Prep} = code:prepare_loading([?MODULE]), + prep_magic(Prep). + +prep_magic([H|T]) -> + [prep_magic(H)|prep_magic(T)]; +prep_magic(Tuple) when is_tuple(Tuple) -> + L = prep_magic(tuple_to_list(Tuple)), + list_to_tuple(L); +prep_magic(Bin) when is_binary(Bin) -> + try erlang:has_prepared_code_on_load(Bin) of + false -> + %% Create a different kind of magic binary. + ets:match_spec_compile([{'_',[true],['$_']}]) + catch + _:_ -> + Bin + end; +prep_magic(Other) -> + Other. + +sticky_dir(_Config) -> + Mod0 = make_module(lists, fun basic_module/1), + Mod1 = make_module(gen_server, fun basic_module/1), + Ms = [Mod0,Mod1], + SD = sticky_directory, + StickyErrors = [{gen_server,SD},{lists,SD}], + StickyErrors = atomic_load_error(Ms, true), + + ok. + +on_load_failing(_Config) -> + OnLoad = make_modules(1, fun on_load_module/1), + [{OnLoadMod,_,_}] = OnLoad, + Ms = make_modules(10, fun basic_module/1) ++ OnLoad, + + %% Fail because there is a module with on_load in the list. + on_load_failure(OnLoadMod, Ms), + on_load_failure(OnLoadMod, [lists:last(Ms)]), + + %% Fail because there already is a pending on_load. + [{HangingOnLoad,_,_}|_] = Ms, + spawn_hanging_on_load(HangingOnLoad), + NoOnLoadMs = lists:droplast(Ms), + {error,[{HangingOnLoad,pending_on_load}]} = + code:atomic_load(NoOnLoadMs), + hanging_on_load ! stop_hanging_and_unload, + + ok. + +on_load_failure(OnLoadMod, Ms) -> + [{OnLoadMod,on_load_not_allowed}] = atomic_load_error(Ms, false). + +spawn_hanging_on_load(Mod) -> + {Mod,Name,Bin} = make_module(Mod, "unknown", + fun(_) -> + hanging_on_load_module(Mod) + end), + spawn_link(fun() -> + {error,on_load_failure} = + code:load_binary(Mod, Name, Bin) + end). + +hanging_on_load_module(Mod) -> + ?Q(["-module('@Mod@').\n", + "-on_load(hang/0).\n", + "hang() ->\n" + " register(hanging_on_load, self()),\n" + " receive _ -> unload end.\n"]). + +ensure_modules_loaded(Config) -> + PrivDir = proplists:get_value(priv_dir, Config), + Dir = filename:join(PrivDir, multi_load_ensure_modules_loaded), + _ = file:make_dir(Dir), + + OldPath = code:get_path(), + try + code:add_patha(Dir), + do_ensure_modules_loaded(Dir) + after + code:set_path(OldPath) + end, + + ok. + +do_ensure_modules_loaded(Dir) -> + %% Create a dummy "lists" module and place it in our code path. + {lists,ListsFile,ListsCode} = make_module(lists, fun basic_module/1), + ok = file:write_file(filename:absname(ListsFile, Dir), ListsCode), + {error,sticky_directory} = code:load_file(lists), + + %% Make a new module that we can load. + Mod = make_module_file(Dir, fun basic_module/1), + false = is_loaded(Mod), + + %% Make a new module with an on_load function. + OLMod = make_module_file(Dir, fun on_load_module/1), + false = is_loaded(OLMod), + + %% lists should not be loaded again; Mod and OLMod should be + %% loaded. ?MODULE should not be reloaded, but there is no easy + %% way to test that. Repeating modules is OK. + ok = code:ensure_modules_loaded([?MODULE,lists,Mod,OLMod, + Mod,OLMod,Mod,lists]), + last = lists:last([last]), + true = is_loaded(Mod), + ok = Mod:Mod(), + true = is_loaded(OLMod), + _ = OLMod:module_info(), + + %% Unload the modules that were loaded. + [begin + code:purge(M), + code:delete(M), + code:purge(M), + false = is_loaded(M) + end || M <- [Mod,OLMod]], + + %% If there are some errors, all other modules should be loaded + %% anyway. + [{BadMod,BadFile,_}] = make_modules(1, fun basic_module/1), + ok = file:write_file(filename:absname(BadFile, Dir), <<"bad_code">>), + BadOLMod = make_module_file(Dir, fun failing_on_load_module/1), + BadEgg = bad__egg, + NativeMod = a_native_module, + NativeModFile = atom_to_list(NativeMod) ++ ".beam", + {NativeMod,_,NativeCode} = make_module(NativeMod, NativeModFile, + fun basic_module/1, [native]), + ok = file:write_file(filename:absname(NativeModFile, Dir), NativeCode), + ModulesToLoad = [OLMod,?MODULE,Mod,BadOLMod,NativeMod, + BadEgg,BadMod,lists], + {error,Error0} = code:ensure_modules_loaded(ModulesToLoad), + Error = lists:sort([{BadEgg,nofile}, + {BadMod,badfile}, + {BadOLMod,on_load_failure}]), + Error = lists:sort(Error0), + true = is_loaded(Mod), + true = is_loaded(OLMod), + true = is_loaded(NativeMod), + true = NativeMod:module_info(native), + + ok. + +failing_on_load_module(Mod) -> + ?Q(["-module('@Mod@').\n", + "-on_load(f/0).\n", + "f() -> fail.\n"]). + +native_code(_Config) -> + case erlang:system_info(hipe_architecture) of + undefined -> + {skip,"No native support"}; + _ -> + do_native_code() + end. + +do_native_code() -> + CalledMod = native_called_module, + CallingMod = native_calling_module, + + %% Create a module in native code that calls another module. + CallingMod = make_and_load(CallingMod, + calling_module_fun(CalledMod), + [native]), + + %% Create a threaded-code module. + _ = make_and_load(CalledMod, called_module_fun(42), []), + 42 = CallingMod:call(), + + %% Now replace it with a changed module in native code. + code:purge(CalledMod), + make_and_load(CalledMod, called_module_fun(43), [native]), + true = test_server:is_native(CalledMod), + 43 = CallingMod:call(), + + %% Reload the called module and call it. + code:purge(CalledMod), + ModVer3 = make_module(CalledMod, "", called_module_fun(changed)), + ok = code:atomic_load([ModVer3]), + false = test_server:is_native(CalledMod), + changed = CallingMod:call(), + code:purge(CalledMod), + + ok. + +make_and_load(Mod, Fun, Opts) -> + {Mod,_,Code} = make_module(Mod, "", Fun, Opts), + {module,Mod} = code:load_binary(Mod, "", Code), + Mod. + +calling_module_fun(Called) -> + fun(Mod) -> + ?Q(["-module('@Mod@').\n", + "-export([call/0]).\n", + "call() -> _@Called@:f().\n"]) + end. + +called_module_fun(Ret) -> + fun(Mod) -> + ?Q(["-module('@Mod@').\n", + "-export([f/0]).\n", + "f() -> _@Ret@.\n"]) + end. + +%%% +%%% Common utilities +%%% + +atomic_load_error(Modules, ErrorInFinishLoading) -> + {error,Errors0} = code:atomic_load(Modules), + {Errors1,Bool} = + case code:prepare_loading(Modules) of + {ok,Prepared} -> + {error,Es0} = code:finish_loading(Prepared), + {Es0,true}; + {error,Es0} -> + {Es0,false} + end, + Errors = lists:sort(Errors0), + Errors = lists:sort(Errors1), + case {ErrorInFinishLoading,Bool} of + {B,B} -> + Errors; + {false,true} -> + ct:fail("LastAction fun must not be called"); + {true,false} -> + ct:fail("LastAction fun was not called") + end. + +is_loaded(Mod) -> + case erlang:module_loaded(Mod) of + false -> + false = code:is_loaded(Mod); + true -> + {file,_} = code:is_loaded(Mod), + true + end. + +basic_module(Mod) -> + ?Q(["-module('@Mod@').\n" + "-export(['@Mod@'/0]).\n", + "'@Mod@'() -> ok."]). + +on_load_module(Mod) -> + ?Q(["-module('@Mod@').\n", + "-on_load(f/0).\n", + "f() -> ok.\n"]). + +make_module_file(Dir, Fun) -> + [{Mod,File,Code}] = make_modules(1, Fun), + ok = file:write_file(filename:absname(File, Dir), Code), + Mod. + +make_modules(0, _) -> + []; +make_modules(N, Fun) -> + U = erlang:unique_integer([positive]), + ModName = "m__" ++ integer_to_list(N) ++ "_" ++ integer_to_list(U), + Mod = list_to_atom(ModName), + ModItem = make_module(Mod, Fun), + [ModItem|make_modules(N-1, Fun)]. + +update_modules(Ms, Fun) -> + [make_module(M, Fun) || M <- Ms]. + +make_module(Mod, Fun) -> + Filename = atom_to_list(Mod) ++ ".beam", + make_module(Mod, Filename, Fun). + +make_module(Mod, Filename, Fun) -> + make_module(Mod, Filename, Fun, []). + +make_module(Mod, Filename, Fun, Opts) -> + Tree = Fun(Mod), + merl:print(Tree), + {ok,Mod,Code} = merl:compile(Tree, Opts), + {Mod,Filename,Code}. diff --git a/lib/observer/test/crashdump_viewer_SUITE.erl b/lib/observer/test/crashdump_viewer_SUITE.erl index 2d47054600..a2b96ecb88 100644 --- a/lib/observer/test/crashdump_viewer_SUITE.erl +++ b/lib/observer/test/crashdump_viewer_SUITE.erl @@ -563,22 +563,11 @@ dump_with_strange_module_name(DataDir,Rel,DumpName) -> CD. dump(Node,DataDir,Rel,DumpName) -> + Crashdump = filename:join(DataDir, dump_prefix(Rel)++DumpName), + rpc:call(Node,os,putenv,["ERL_CRASH_DUMP",Crashdump]), rpc:call(Node,erlang,halt,[DumpName]), - Crashdump0 = filename:join(filename:dirname(code:which(?t)), - "erl_crash_dump.n1"), - Crashdump1 = filename:join(DataDir, dump_prefix(Rel)++DumpName), - ok = rename(Crashdump0,Crashdump1), - Crashdump1. - -rename(From,To) -> - ok = check_complete(From), - case file:rename(From,To) of - {error,exdev} -> - {ok,_} = file:copy(From,To), - ok = file:delete(From); - ok -> - ok - end. + ok = check_complete(Crashdump), + Crashdump. check_complete(File) -> check_complete1(File,10). diff --git a/lib/public_key/src/pubkey_pem.erl b/lib/public_key/src/pubkey_pem.erl index 6a722b0525..d163004c7c 100644 --- a/lib/public_key/src/pubkey_pem.erl +++ b/lib/public_key/src/pubkey_pem.erl @@ -103,7 +103,7 @@ encode_pem_entry({'PrivateKeyInfo', Der, EncParams}) -> [StartStr, "\n", b64encode_and_split(EncDer), "\n", pem_end(StartStr) ,"\n\n"]; encode_pem_entry({Type, Der, {Cipher, Salt}}) -> StartStr = pem_start(Type), - [StartStr,"\n", pem_decrypt(),"\n", pem_decrypt_info(Cipher, Salt),"\n", + [StartStr,"\n", pem_decrypt(),"\n", pem_decrypt_info(Cipher, Salt),"\n\n", b64encode_and_split(Der), "\n", pem_end(StartStr) ,"\n\n"]. decode_pem_entries([], Entries) -> diff --git a/lib/public_key/test/public_key_SUITE.erl b/lib/public_key/test/public_key_SUITE.erl index 5e677f31d6..ea5e036a7e 100644 --- a/lib/public_key/test/public_key_SUITE.erl +++ b/lib/public_key/test/public_key_SUITE.erl @@ -189,6 +189,8 @@ encrypted_pem(Config) when is_list(Config) -> erl_make_certs:der_to_pem(DesKeyFile, [Entry1]), [{'RSAPrivateKey', _, {"DES-CBC", Salt1}} =Entry2] = erl_make_certs:pem_to_der(DesKeyFile), + {ok, Pem} = file:read_file(DesKeyFile), + check_encapsulated_header(Pem), true = check_entry_type(public_key:pem_entry_decode(Entry2, "4567efgh"), 'RSAPrivateKey'). @@ -826,6 +828,15 @@ check_entry_type(#'Certificate'{}, 'Certificate') -> check_entry_type(_,_) -> false. +check_encapsulated_header(Pem) when is_binary(Pem)-> + check_encapsulated_header( binary:split(Pem, <<"\n">>, [global])); +check_encapsulated_header([<<"DEK-Info: DES-CBC,FB7577791A9056A1">>, <<>> | _]) -> + true; +check_encapsulated_header([ _ | Rest]) -> + check_encapsulated_header(Rest); +check_encapsulated_header([]) -> + false. + strip_ending_newlines(Bin) -> string:strip(binary_to_list(Bin), right, 10). diff --git a/lib/runtime_tools/c_src/trace_file_drv.c b/lib/runtime_tools/c_src/trace_file_drv.c index a63a7d3ad9..8863b0d6ac 100644 --- a/lib/runtime_tools/c_src/trace_file_drv.c +++ b/lib/runtime_tools/c_src/trace_file_drv.c @@ -75,12 +75,8 @@ #ifdef DEBUG -#ifndef __WIN32__ -#define ASSERT(X) do {if (!(X)) {erl_exit(1,"%s",#X);} } while(0) -#else #include <assert.h> #define ASSERT(X) assert(X) -#endif #else #define ASSERT(X) #endif diff --git a/lib/runtime_tools/c_src/trace_ip_drv.c b/lib/runtime_tools/c_src/trace_ip_drv.c index f7b5ea65cb..5b43f8179e 100644 --- a/lib/runtime_tools/c_src/trace_ip_drv.c +++ b/lib/runtime_tools/c_src/trace_ip_drv.c @@ -44,19 +44,8 @@ #endif #ifdef DEBUG -# ifndef __WIN32__ - /* erl_exit is not available to dll_drivers on windows. */ - void erl_exit(int, char *, ...); -# define ASSERT(X) \ - do { \ - if (!(X)) { \ - erl_exit(1,"%s",#X); \ - } \ - } while(0) -# else -# include <assert.h> -# define ASSERT(X) assert(X) -# endif +# include <assert.h> +# define ASSERT(X) assert(X) #else # define ASSERT(X) #endif diff --git a/lib/sasl/doc/src/Makefile b/lib/sasl/doc/src/Makefile index 1ee48af338..a66b1f8bcb 100644 --- a/lib/sasl/doc/src/Makefile +++ b/lib/sasl/doc/src/Makefile @@ -36,7 +36,6 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN) # ---------------------------------------------------- XML_APPLICATION_FILES = ref_man.xml XML_REF3_FILES = alarm_handler.xml \ - overload.xml \ rb.xml \ release_handler.xml \ systools.xml diff --git a/lib/sasl/doc/src/overload.xml b/lib/sasl/doc/src/overload.xml deleted file mode 100644 index 2f19cd9088..0000000000 --- a/lib/sasl/doc/src/overload.xml +++ /dev/null @@ -1,152 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE erlref SYSTEM "erlref.dtd"> - -<erlref> - <header> - <copyright> - <year>1996</year><year>2013</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - </legalnotice> - - <title>overload</title> - <prepared>Peter Högfeldt</prepared> - <responsible>Peter Högfeldt</responsible> - <docno></docno> - <approved>(Joe Armstrong)</approved> - <checked></checked> - <date>1996-10-29</date> - <rev>A</rev> - <file>overload.sgml</file> - </header> - <module>overload</module> - <modulesummary>An Overload Regulation Process</modulesummary> - <description> - <warning> - <p> - All functions in this module are deprecated and will be - removed in a future release. - </p> - </warning> - <p><c>overload</c> is a process that indirectly regulates the CPU - usage in the system. The idea is that a main application calls - function - <seealso marker="#request/0"><c>request/0</c></seealso> - before starting a major job and - proceeds with the job if the return value is positive; otherwise - the job must not be started.</p> - <p><c>overload</c> is part of the <c>SASL</c> application and all - configuration parameters are defined there.</p> - <p>A set of two intensities are maintained, the <c>total intensity</c> - and the <c>accept intensity</c>. For that purpose, - there are two configuration parameters, <c>MaxIntensity</c> - and <c>Weight</c>; both are measured in 1/second.</p> - <p>Then total and accept intensities are calculated as - follows. Assume that the time of the current call to - <c>request/0</c> is <c>T(n)</c> and that the time of the - previous call was <c>T(n-1)</c>.</p> - <list type="bulleted"> - <item> - <p>The current <c>total intensity</c>, denoted - <c>TI(n)</c>, is calculated according to the formula</p> - <p><c>TI(n) = exp(-Weight*(T(n) - T(n-1)) * TI(n-1) + Weight</c>,</p> - <p>where <c>TI(n-1)</c> is the previous <c>total intensity</c>.</p> - </item> - <item> - <p>The current <c>accept intensity</c>, denoted - <c>AI(n)</c>, is determined by the formula</p> - <p><c>AI(n) = exp(-Weight*(T(n) - T(n-1)) * AI(n-1) + Weight</c>,</p> - <p>where <c>AI(n-1)</c> is the previous <c>accept intensity</c>, - if the value of <c>exp(-Weight*(T(n) - T(n-1)) * AI(n-1)</c> - is less than <c>MaxIntensity</c>. Otherwise the value is</p> - <p><c>AI(n) = exp(-Weight*(T(n) - T(n-1)) * AI(n-1)</c></p> - </item> - </list> - <p>The value of configuration parameter <c>Weight</c> controls the - speed with which the calculations of intensities react to - changes in the underlying input intensity. The inverted value of - <c>Weight</c>, <c>T = 1/Weight</c>, can be thought of as the - "time constant" of the intensity calculation formulas. For example, - if <c>Weight = 0.1</c>, a change in the underlying input intensity is - reflected in <c>total intensity</c> and <c>accept intensity</c> within - about 10 seconds.</p> - <p>The overload process defines one alarm, which it sets using - <c>alarm_handler:set_alarm(Alarm)</c>. <c>Alarm</c> is defined - as follows:</p> - <taglist> - <tag><c>{overload, []}</c></tag> - <item> - <p>This alarm is set when the current <c>accept intensity</c> exceeds - <c>MaxIntensity</c>.</p> - </item> - </taglist> - <p>A new request is not accepted until the current <c>accept - intensity</c> has fallen below <c>MaxIntensity</c>. To prevent the - overload process from generating many set/reset alarms, the - alarm is not reset until the current <c>accept intensity</c> has fallen - below 75% of <c>MaxIntensity</c>; it is not until then that - the alarm can be set again.</p> - </description> - - <funcs> - <func> - <name>request() -> accept | reject</name> - <fsummary>Requests to proceed with current job.</fsummary> - <desc> - <p>Returns <c>accept</c> or <c>reject</c> depending on the - current value of the <c>accept intensity</c>.</p> - <p>The application - calling this function is to proceed with the job in - question if the return value is <c>accept</c>; otherwise it - is not to continue with that job.</p> - </desc> - </func> - - <func> - <name>get_overload_info() -> OverloadInfo</name> - <fsummary>Returns current overload information data.</fsummary> - <type> - <v>OverloadInfo = [{total_intensity, TotalIntensity}, - {accept_intensity, AcceptIntensity}, {max_intensity, - MaxIntensity}, {weight, Weight}, {total_requests, - TotalRequests}, {accepted_requests, AcceptedRequests}].</v> - <v>TotalIntensity = float() > 0</v> - <v>AcceptIntensity = float() > 0</v> - <v>MaxIntensity = float() > 0</v> - <v>Weight = float() > 0</v> - <v>TotalRequests = integer()</v> - <v>AcceptedRequests = integer()</v> - </type> - <desc> - <p>Returns:</p> - <list type="bulleted"> - <item>Current total and accept intensities</item> - <item>Configuration parameters</item> - <item>Absolute counts of the total number of requests</item> - <item>Accepted number of requests (since the overload - process was started)</item> - </list> - </desc> - </func> - </funcs> - - <section> - <title>See Also</title> - <p><seealso marker="alarm_handler"><c>alarm_handler(3)</c></seealso>, - <seealso marker="sasl_app"><c>sasl(6)</c></seealso></p> - </section> -</erlref> - diff --git a/lib/sasl/doc/src/ref_man.xml b/lib/sasl/doc/src/ref_man.xml index a80e5a2a00..74cd92a9b0 100644 --- a/lib/sasl/doc/src/ref_man.xml +++ b/lib/sasl/doc/src/ref_man.xml @@ -35,7 +35,6 @@ </description> <xi:include href="sasl_app.xml"/> <xi:include href="alarm_handler.xml"/> - <xi:include href="overload.xml"/> <xi:include href="rb.xml"/> <xi:include href="release_handler.xml"/> <xi:include href="systools.xml"/> diff --git a/lib/sasl/doc/src/sasl_app.xml b/lib/sasl/doc/src/sasl_app.xml index bcd446a868..044c016302 100644 --- a/lib/sasl/doc/src/sasl_app.xml +++ b/lib/sasl/doc/src/sasl_app.xml @@ -34,7 +34,6 @@ <p>The <c>SASL</c> application provides the following services:</p> <list type="bulleted"> <item><c>alarm_handler</c></item> - <item><c>overload</c> (deprecated)</item> <item><c>rb</c></item> <item><c>release_handler</c></item> <item><c>systools</c></item> @@ -140,21 +139,6 @@ this parameter is undefined, the <c>log_mf_h</c> handler is not installed.</p> </item> - <tag><c><![CDATA[overload_max_intensity = float() > 0 ]]></c></tag> - <item> - <p>Specifies the maximum intensity - for <seealso marker="overload"><c>overload</c></seealso>. Default - is <c>0.8</c>.</p> - <p>Note that the <c>overload</c> module is deprected and - will be removed in a future release.</p> - </item> - <tag><c><![CDATA[overload_weight = float() > 0 ]]></c></tag> - <item> - <p>Specifies the <seealso marker="overload"><c>overload</c></seealso> - weight. Default is <c>0.1</c>.</p> - <p>Note that the <c>overload</c> module is deprected and - will be removed in a future release.</p> - </item> <tag><c><![CDATA[start_prg = string() ]]></c></tag> <item> <p>Specifies the program to be used when restarting the system @@ -205,7 +189,6 @@ <p><seealso marker="alarm_handler"><c>alarm_handler(3)</c></seealso>, <seealso marker="kernel:error_logger"><c>error_logger(3)</c></seealso>, <seealso marker="stdlib:log_mf_h"><c>log_mf_h(3)</c></seealso>, - <seealso marker="overload"><c>overload(3)</c></seealso>, <seealso marker="rb"><c>rb(3)</c></seealso>, <seealso marker="release_handler"><c>release_handler(3)</c></seealso>, <seealso marker="systools"><c>systools(3)</c></seealso></p> diff --git a/lib/sasl/doc/src/sasl_intro.xml b/lib/sasl/doc/src/sasl_intro.xml index bbc9457103..237580977c 100644 --- a/lib/sasl/doc/src/sasl_intro.xml +++ b/lib/sasl/doc/src/sasl_intro.xml @@ -36,7 +36,6 @@ <list type="bulleted"> <item>Error logging</item> <item>Alarm handling</item> - <item>Overload regulation</item> <item>Release handling</item> <item>Report browsing</item> </list> diff --git a/lib/sasl/src/Makefile b/lib/sasl/src/Makefile index 7ff6a03a50..92d4818f2e 100644 --- a/lib/sasl/src/Makefile +++ b/lib/sasl/src/Makefile @@ -36,7 +36,7 @@ RELSYSDIR = $(RELEASE_PATH)/lib/sasl-$(VSN) # ---------------------------------------------------- MODULES= alarm_handler sasl sasl_report \ sasl_report_file_h sasl_report_tty_h format_lib_supp \ - misc_supp overload rb rb_format_supp release_handler \ + misc_supp rb rb_format_supp release_handler \ release_handler_1 si si_sasl_supp systools \ systools_make systools_rc systools_relup systools_lib \ erlsrv diff --git a/lib/sasl/src/misc_supp.erl b/lib/sasl/src/misc_supp.erl index 42de7eedec..39656f6e65 100644 --- a/lib/sasl/src/misc_supp.erl +++ b/lib/sasl/src/misc_supp.erl @@ -27,7 +27,7 @@ %%% 2) Very generic functions such as, multi_map, is_string... %%% %%% This module is a part of the BOS. (format_pdict is called from -%%% init, memsup, disksup, overload (but not the fileserver since it +%%% init, memsup, disksup (but not the fileserver since it %%% formats its pdict its own way).) %%%--------------------------------------------------------------------- diff --git a/lib/sasl/src/overload.erl b/lib/sasl/src/overload.erl deleted file mode 100644 index bc8ab7d5e4..0000000000 --- a/lib/sasl/src/overload.erl +++ /dev/null @@ -1,233 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% --module(overload). - --deprecated(module). - --export([start_link/0, request/0, set_config_data/2, - get_overload_info/0]). - --export([init/1, handle_call/3, handle_info/2, terminate/2, - format_status/2]). - -%%%----------------------------------------------------------------- -%%% This is a rewrite of overload from BS.3, by Peter Högfeldt. -%%% -%%% DESCRIPTION -%%% -%%% This module implements a server process that keeps record of the -%%% intensity of calls of the request/0 function, and answers accept or -%%% reject depending on if the current average intensity is not greater -%%% than a specified maximum intensity. -%%% -%%% The intensity i is calculated according to the formula: -%%% i(n) = exp(-K*(T(n) - T(n-1)))*i(n-1) + Kappa -%%% where i(n) is the intensity at event n, Kappa is a constant, and -%%% T(n) is the time at event n. -%%% -%%% The constant Kappa can be thought of as 1 / T, where T is the time -%%% constant. Kappa is externally referred to as Weight. -%%% -%%% We keep track of two intensities: the total call intensity and the -%%% intensity of accepted calls. -%%%----------------------------------------------------------------- -%%% TODO -%%% -%%% 3. Hysteresis. -%%% -%%%----------------------------------------------------------------- - --record(state, {total = 0, accept = 0, max, prev_t = get_now(), - kappa, call_counts = {0, 0}, alarm = clear}). - --define(clear_timeout, 30000). - -start_link() -> - gen_server:start_link({local, overload}, overload, [], []). - -init([]) -> - process_flag(priority, high), - MaxIntensity = fetch_config_data(overload_max_intensity), - Kappa = fetch_config_data(overload_weight), - {ok, #state{max = MaxIntensity, kappa = Kappa}}. - -%%----------------------------------------------------------------- -%% Func: request/0 -%% Purpose: This is a request to proceed, e.g. a request to -%% establish a call. -%% Returns: accept | reject -%%----------------------------------------------------------------- -request() -> call(request). - -%%----------------------------------------------------------------- -%% Func: set_config_data/2 -%% Purpose: Set configuration data, and reset intensities. -%% Arguments: MaxIntensity (real > 0), Weight (real > 0). -%% Returns: ok | {error, What} -%% This function is for debugging purposes and is therefore not -%% documented at all. -%%----------------------------------------------------------------- -set_config_data(MaxIntensity, Weight) -> - call({set_config_data, MaxIntensity, Weight}). -%%----------------------------------------------------------------- -%% Func: get_overload_info/0 -%% Returns: A list of tagged items: TotalIntensity, AcceptIntensity, -%% MaxIntensity, Weight, TotalRequests, AcceptedRequests. -%%----------------------------------------------------------------- -get_overload_info() -> call(get_overload_info). - -%%----------------------------------------------------------------- -%% call(Request) -> Term -%%----------------------------------------------------------------- -call(Req) -> - gen_server:call(overload, Req, infinity). - -%%%----------------------------------------------------------------- -%%% Callback functions from gen_server -%%%----------------------------------------------------------------- -handle_call(request, _From, State) -> - #state{total = TI, accept = AI, kappa = Kappa, prev_t = PrevT, - alarm = Alarm} = State, - {TR, AR} = State#state.call_counts, - T = get_now(), - CurI = new_intensity(AI, T, PrevT, Kappa), - NewTI = new_intensity(TI, T, PrevT, Kappa) + Kappa, - if - CurI =< State#state.max -> - %% Hysteresis: If alarm is set, and current intensity has - %% fallen below 75% of max intensity, clear alarm. - NewAlarm = if - CurI =< 0.75*State#state.max -> - clear_alarm(Alarm); - true -> - Alarm - end, - {reply, accept, State#state{call_counts = {TR+1, AR+1}, - prev_t = T, total = NewTI, - accept = CurI + Kappa, - alarm = NewAlarm}, - ?clear_timeout}; - true -> - %% Set alarm if not already set. - NewAlarm = set_alarm(Alarm), - {reply, reject, - State#state{call_counts = {TR+1, AR}, prev_t = T, - total = NewTI, accept = CurI, - alarm = NewAlarm}, - ?clear_timeout} - end; -handle_call({set_config_data, MaxIntensity, Weight}, _From, _State) -> - {reply, ok, #state{max = MaxIntensity, kappa = Weight}, - ?clear_timeout}; -handle_call(get_overload_info, _From, State) -> - #state{max = MI, total = TI, accept = AI, kappa = Kappa, - prev_t = PrevT, call_counts = {TR, AR}} = State, - T = get_now(), - CurI = new_intensity(AI, T, PrevT, Kappa), - NewTI = new_intensity(TI, T, PrevT, Kappa), - Reply = [{total_intensity, NewTI}, {accept_intensity, CurI}, - {max_intensity, MI}, {weight, Kappa}, - {total_requests, TR}, {accepted_requests, AR}], - {reply, Reply, State#state{total = NewTI, accept = CurI}, - ?clear_timeout}. - -handle_info(timeout, State) -> - #state{total = TI, accept = AI, kappa = Kappa, prev_t = PrevT, - alarm = Alarm} = State, - T = get_now(), - CurI = new_intensity(AI, T, PrevT, Kappa), - NewTI = new_intensity(TI, T, PrevT, Kappa), - if - CurI < 0.75* State#state.max -> - NewAlarm = clear_alarm(Alarm), - {noreply, State#state{total = NewTI, accept = CurI, - alarm = NewAlarm}}; - - true -> - {noreply, State#state{total = NewTI, accept = CurI}, - ?clear_timeout} - end; - -handle_info(_, State) -> - {noreply, State, ?clear_timeout}. - -terminate(_Reason, _State) -> - ok. - -%%----------------------------------------------------------------- -%% Internal functions -%%----------------------------------------------------------------- -fetch_config_data(Tag) -> - case application:get_env(sasl, Tag) of - {ok, Value} -> Value; - _ -> fetch_default_data(Tag) - end. - -fetch_default_data(overload_max_intensity) -> 0.8; -fetch_default_data(overload_weight) -> 0.1. - -set_alarm(clear) -> - alarm_handler:set_alarm({overload, []}), - set; -set_alarm(Alarm) -> - Alarm. - -clear_alarm(set) -> - alarm_handler:clear_alarm(overload), - clear; -clear_alarm(Alarm) -> - Alarm. - -%%----------------------------------------------------------------- -%% The catch protects against floating-point exception. -%% -new_intensity(I, T, PrevT, K) -> - Diff = sub(T, PrevT)/1000, - case catch (I*math:exp(-K*Diff)) of - {'EXIT', _} -> % Assume zero. - 0.0; - Res -> - Res - end. - -%% Mask equal to 2^27 - 1, used below. --define(mask27, 16#7ffffff). - -%% Returns number of milliseconds in the range [0, 2^27 - 1]. Must have -%% this since statistics(wall_clock) wraps. Having 2^27 -1 as the max -%% assures that we always get non-negative integers. 2^27 milliseconds -%% are approx. 37.28 hours. -get_now() -> - element(1, statistics(wall_clock)) band ?mask27. - -%% Returns (X - Y) mod 2^27 (which is in the range [0, 2^27 - 1]). -sub(X, Y) -> - (X + (bnot Y) + 1) band ?mask27. - -format_status(Opt, [PDict, #state{max = MI, total = TI, accept = AI, - kappa = K, - call_counts = {TR, AR}}]) -> - [{data, [{"Total Intensity", TI}, - {"Accept Intensity", AI}, - {"Max Intensity", MI}, - {"Weight", K}, - {"Total requests", TR}, - {"Accepted requests", AR}]} | - misc_supp:format_pdict(Opt, PDict, [])]. diff --git a/lib/sasl/src/sasl.app.src b/lib/sasl/src/sasl.app.src index 507e2dc229..16e8e44ba2 100644 --- a/lib/sasl/src/sasl.app.src +++ b/lib/sasl/src/sasl.app.src @@ -24,7 +24,6 @@ alarm_handler, format_lib_supp, misc_supp, - overload, rb, rb_format_supp, release_handler, @@ -41,7 +40,7 @@ systools_relup, systools_lib ]}, - {registered, [sasl_sup, alarm_handler, overload, release_handler]}, + {registered, [sasl_sup, alarm_handler, release_handler]}, {applications, [kernel, stdlib]}, {env, [{sasl_error_logger, tty}, {errlog_type, all}]}, diff --git a/lib/sasl/src/sasl.appup.src b/lib/sasl/src/sasl.appup.src index 8faa0afbd4..ca5122dab4 100644 --- a/lib/sasl/src/sasl.appup.src +++ b/lib/sasl/src/sasl.appup.src @@ -18,9 +18,9 @@ %% %CopyrightEnd% {"%VSN%", %% Up from - max one major revision back - [{<<"2\\.[5-6](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.* - {<<"2\\.4(\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-17 + [{<<"3\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.* + {<<"2\\.[5-7](\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-18.* %% Down to - max one major revision back - [{<<"2\\.[5-6](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.* - {<<"2\\.4(\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-17 + [{<<"3\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.* + {<<"2\\.[5-7](\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-18.* }. diff --git a/lib/sasl/src/sasl.erl b/lib/sasl/src/sasl.erl index fc49fc2465..0fb85682c6 100644 --- a/lib/sasl/src/sasl.erl +++ b/lib/sasl/src/sasl.erl @@ -170,7 +170,4 @@ init(safe) -> AlarmH = {alarm_handler, {alarm_handler, start_link, []}, permanent, 2000, worker, dynamic}, - Overload = {overload, - {overload, start_link, []}, - permanent, 2000, worker, [overload]}, - {ok, {SupFlags, [AlarmH, Overload]}}. + {ok, {SupFlags, [AlarmH]}}. diff --git a/lib/sasl/test/Makefile b/lib/sasl/test/Makefile index 6f67498714..2e9e107efd 100644 --- a/lib/sasl/test/Makefile +++ b/lib/sasl/test/Makefile @@ -33,7 +33,6 @@ MODULES= \ sasl_report_suite_supervisor \ systools_SUITE \ systools_rc_SUITE \ - overload_SUITE \ rb_SUITE \ rh_test_lib \ diff --git a/lib/sasl/test/overload_SUITE.erl b/lib/sasl/test/overload_SUITE.erl deleted file mode 100644 index 02d1056698..0000000000 --- a/lib/sasl/test/overload_SUITE.erl +++ /dev/null @@ -1,168 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2011. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% - --module(overload_SUITE). --include_lib("common_test/include/ct.hrl"). - --compile(export_all). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -all() -> [info, set_config_data, set_env_vars, request, timeout]. - -init_per_testcase(_Case,Config) -> - restart_sasl(), - Config. - -end_per_testcase(Case,Config) -> - try apply(?MODULE,Case,[cleanup,Config]) - catch error:undef -> ok - end, - ok. - -%%%----------------------------------------------------------------- -info(_Config) -> - Info = overload:get_overload_info(), - [{total_intensity,0.0}, - {accept_intensity,0.0}, - {max_intensity,0.8}, - {weight,0.1}, - {total_requests,0}, - {accepted_requests,0}] = Info. - -%%%----------------------------------------------------------------- -set_config_data(_Config) -> - InfoDefault = overload:get_overload_info(), - ok = check_info(0.8,0.1,InfoDefault), - ok = overload:set_config_data(0.5,0.4), - Info1 = overload:get_overload_info(), - ok = check_info(0.5,0.4,Info1), - ok. - -%%%----------------------------------------------------------------- -set_env_vars(_Config) -> - InfoDefault = overload:get_overload_info(), - ok = check_info(0.8,0.1,InfoDefault), - ok = application:set_env(sasl,overload_max_intensity,0.5), - ok = application:set_env(sasl,overload_weight,0.4), - ok = application:stop(sasl), - ok = application:start(sasl), - Info1 = overload:get_overload_info(), - ok = check_info(0.5,0.4,Info1), - ok. -set_env_vars(cleanup,_Config) -> - application:unset_env(sasl,overload_max_intensity), - application:unset_env(sasl,overload_weight), - ok. - -%%%----------------------------------------------------------------- -request(_Config) -> - %% Find number of request that can be done with default settings - %% and no delay - overload:set_config_data(0.8, 0.1), - NDefault = do_many_requests(0), - restart_sasl(), - ?t:format("NDefault: ~p",[NDefault]), - - %% Check that the number of requests increases when max_intensity - %% increases - overload:set_config_data(2, 0.1), - NLargeMI = do_many_requests(0), - restart_sasl(), - ?t:format("NLargeMI: ~p",[NLargeMI]), - true = NLargeMI > NDefault, - - %% Check that the number of requests decreases when weight - %% increases - overload:set_config_data(0.8, 1), - NLargeWeight = do_many_requests(0), - restart_sasl(), - ?t:format("NLargeWeight: ~p",[NLargeWeight]), - true = NLargeWeight < NDefault, - - %% Check that number of requests increases when delay between - %% requests increases. - %% (Keeping same config and comparing to large weight in order to - %% minimize the time needed for this case.) - overload:set_config_data(0.8, 1), - NLargeTime = do_many_requests(500), - restart_sasl(), - ?t:format("NLargeTime: ~p",[NLargeTime]), - true = NLargeTime > NLargeWeight, - ok. - -%%%----------------------------------------------------------------- -timeout(_Config) -> - overload:set_config_data(0.8, 1), - _N = do_many_requests(0), - - %% Check that the overload alarm is raised - [{overload,_}] = alarm_handler:get_alarms(), - - %% Fake a clear timeout in overload.erl and check that, since it - %% came very soon after the overload situation, the alarm is not - %% cleared - overload ! timeout, - timer:sleep(1000), - [{overload,_}] = alarm_handler:get_alarms(), - - %% A bit later, try again and check that this time the alarm is - %% cleared - overload ! timeout, - timer:sleep(1000), - [] = alarm_handler:get_alarms(), - - ok. - - -%%%----------------------------------------------------------------- -%%% INTERNAL FUNCTIONS - -%%%----------------------------------------------------------------- -%%% Call overload:request/0 up to 30 times with the given time delay -%%% between. Stop when 'reject' is returned. -do_many_requests(T) -> - 30 - do_requests(30,T). - -do_requests(0,_) -> - ?t:fail(never_rejected); -do_requests(N,T) -> - case overload:request() of - accept -> - timer:sleep(T), - do_requests(N-1,T); - reject -> - N - end. - -%%%----------------------------------------------------------------- -%%% Restart the sasl application -restart_sasl() -> - application:stop(sasl), - application:start(sasl), - ok. - -%%%----------------------------------------------------------------- -%%% Check that max_intensity and weight is set as expected -check_info(MI,W,Info) -> - case {lists:keyfind(max_intensity,1,Info), lists:keyfind(weight,1,Info)} of - {{_,MI},{_,W}} -> ok; - _ -> ?t:fail({unexpected_info,MI,W,Info}) - end. diff --git a/lib/ssh/doc/src/ssh_sftp.xml b/lib/ssh/doc/src/ssh_sftp.xml index c6ca0f161a..f4b41b74f3 100644 --- a/lib/ssh/doc/src/ssh_sftp.xml +++ b/lib/ssh/doc/src/ssh_sftp.xml @@ -333,7 +333,7 @@ <func> <name>position(ChannelPid, Handle, Location) -></name> - <name>position(ChannelPid, Handle, Location, Timeout) -> {ok, NewPosition | {error, Error}</name> + <name>position(ChannelPid, Handle, Location, Timeout) -> {ok, NewPosition} | {error, Reason}</name> <fsummary>Sets the file position of a file.</fsummary> <type> <v>ChannelPid = pid()</v> @@ -399,7 +399,7 @@ <func> <name>pwrite(ChannelPid, Handle, Position, Data) -> ok</name> - <name>pwrite(ChannelPid, Handle, Position, Data, Timeout) -> ok | {error, Error}</name> + <name>pwrite(ChannelPid, Handle, Position, Data, Timeout) -> ok | {error, Reason}</name> <fsummary>Writes to an open file.</fsummary> <type> <v>ChannelPid = pid()</v> @@ -592,7 +592,7 @@ <func> <name>write(ChannelPid, Handle, Data) -></name> - <name>write(ChannelPid, Handle, Data, Timeout) -> ok | {error, Error}</name> + <name>write(ChannelPid, Handle, Data, Timeout) -> ok | {error, Reason}</name> <fsummary>Writes to an open file.</fsummary> <type> <v>ChannelPid = pid()</v> diff --git a/lib/ssh/test/ssh_algorithms_SUITE.erl b/lib/ssh/test/ssh_algorithms_SUITE.erl index a03a9ee0f2..49ed15698c 100644 --- a/lib/ssh/test/ssh_algorithms_SUITE.erl +++ b/lib/ssh/test/ssh_algorithms_SUITE.erl @@ -36,7 +36,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}, - {timetrap,{minutes,5}}]. + {timetrap,{minutes,10}}]. all() -> %% [{group,kex},{group,cipher}... etc diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl index 564fb66586..094d28e879 100644 --- a/lib/ssh/test/ssh_basic_SUITE.erl +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -79,7 +79,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}, - {timetrap,{minutes,5}}]. + {timetrap,{minutes,10}}]. all() -> [app_test, diff --git a/lib/ssh/test/ssh_connection_SUITE.erl b/lib/ssh/test/ssh_connection_SUITE.erl index 67d870bea4..6e90faf0e8 100644 --- a/lib/ssh/test/ssh_connection_SUITE.erl +++ b/lib/ssh/test/ssh_connection_SUITE.erl @@ -37,7 +37,7 @@ %% [{ct_hooks,[ts_install_cth]}]. suite() -> - [{timetrap,{minutes,5}}]. + [{timetrap,{minutes,2}}]. all() -> [ diff --git a/lib/ssh/test/ssh_options_SUITE.erl b/lib/ssh/test/ssh_options_SUITE.erl index e0ef3a4b05..ba0107efd6 100644 --- a/lib/ssh/test/ssh_options_SUITE.erl +++ b/lib/ssh/test/ssh_options_SUITE.erl @@ -80,7 +80,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}, - {timetrap,{minutes,5}}]. + {timetrap,{minutes,6}}]. all() -> [connectfun_disconnectfun_server, diff --git a/lib/ssh/test/ssh_protocol_SUITE.erl b/lib/ssh/test/ssh_protocol_SUITE.erl index cabdd35615..dbba48c726 100644 --- a/lib/ssh/test/ssh_protocol_SUITE.erl +++ b/lib/ssh/test/ssh_protocol_SUITE.erl @@ -43,7 +43,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}, - {timetrap,{minutes,5}}]. + {timetrap,{minutes,2}}]. all() -> [{group,tool_tests}, diff --git a/lib/ssh/test/ssh_renegotiate_SUITE.erl b/lib/ssh/test/ssh_renegotiate_SUITE.erl index fabe9a5829..6d2c97aa68 100644 --- a/lib/ssh/test/ssh_renegotiate_SUITE.erl +++ b/lib/ssh/test/ssh_renegotiate_SUITE.erl @@ -31,7 +31,7 @@ %%-------------------------------------------------------------------- suite() -> [{ct_hooks,[ts_install_cth]}, - {timetrap,{minutes,15}}]. + {timetrap,{minutes,12}}]. all() -> [{group,default_algs}, diff --git a/lib/ssh/test/ssh_sftp_SUITE.erl b/lib/ssh/test/ssh_sftp_SUITE.erl index 6066221fc7..c2b04d7a05 100644 --- a/lib/ssh/test/ssh_sftp_SUITE.erl +++ b/lib/ssh/test/ssh_sftp_SUITE.erl @@ -36,7 +36,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}, - {timetrap,{minutes,5}}]. + {timetrap,{minutes,2}}]. all() -> diff --git a/lib/ssh/test/ssh_sftpd_SUITE.erl b/lib/ssh/test/ssh_sftpd_SUITE.erl index 687f327206..45439ce0fa 100644 --- a/lib/ssh/test/ssh_sftpd_SUITE.erl +++ b/lib/ssh/test/ssh_sftpd_SUITE.erl @@ -45,7 +45,7 @@ %%-------------------------------------------------------------------- suite() -> - [{timetrap,{minutes,5}}]. + [{timetrap,{minutes,3}}]. all() -> [open_close_file, diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl index 84410f60e6..02a2ac4cf9 100644 --- a/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl +++ b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl @@ -37,7 +37,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}, - {timetrap,{minutes,5}}]. + {timetrap,{minutes,2}}]. all() -> diff --git a/lib/ssh/test/ssh_sup_SUITE.erl b/lib/ssh/test/ssh_sup_SUITE.erl index 5c77fcf1ef..18e91a9af3 100644 --- a/lib/ssh/test/ssh_sup_SUITE.erl +++ b/lib/ssh/test/ssh_sup_SUITE.erl @@ -34,6 +34,10 @@ %% Common Test interface functions ----------------------------------- %%-------------------------------------------------------------------- +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,1}}]. + all() -> [default_tree, sshc_subtree, sshd_subtree, sshd_subtree_profile]. diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl index 37885dfdef..2788bc6b58 100644 --- a/lib/ssh/test/ssh_to_openssh_SUITE.erl +++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl @@ -34,7 +34,7 @@ %%-------------------------------------------------------------------- suite() -> - [{timetrap,{minutes,5}}]. + [{timetrap,{minutes,1}}]. all() -> case os:find_executable("ssh") of diff --git a/lib/ssh/test/ssh_upgrade_SUITE.erl b/lib/ssh/test/ssh_upgrade_SUITE.erl index 006483d3ee..bf8874b118 100644 --- a/lib/ssh/test/ssh_upgrade_SUITE.erl +++ b/lib/ssh/test/ssh_upgrade_SUITE.erl @@ -39,7 +39,7 @@ %%% CommonTest callbacks %%% suite() -> - [{timetrap,{minutes,5}}]. + [{timetrap,{minutes,2}}]. all() -> [ diff --git a/lib/ssh/vsn.mk b/lib/ssh/vsn.mk index 55d12abffe..41b42d454b 100644 --- a/lib/ssh/vsn.mk +++ b/lib/ssh/vsn.mk @@ -1,5 +1,5 @@ #-*-makefile-*- ; force emacs to enter makefile-mode -SSH_VSN = 4.2.1 +SSH_VSN = 4.2.2 APP_VSN = "ssh-$(SSH_VSN)" diff --git a/lib/ssl/doc/src/ssl_distribution.xml b/lib/ssl/doc/src/ssl_distribution.xml index a347ce5ae6..dc04d446b0 100644 --- a/lib/ssl/doc/src/ssl_distribution.xml +++ b/lib/ssl/doc/src/ssl_distribution.xml @@ -271,4 +271,27 @@ Eshell V5.0 (abort with ^G) <p>The <c>init:get_arguments()</c> call verifies that the correct arguments are supplied to the emulator.</p> </section> + + <section> + <title>Using SSL distribution over IPv6</title> + <p>It is possible to use SSL distribution over IPv6 instead of + IPv4. To do this, pass the option <c>-proto_dist inet6_tls</c> + instead of <c>-proto_dist inet_tls</c> when starting Erlang, + either on the command line or in the <c>ERL_FLAGS</c> environment + variable.</p> + + <p>An example command line with this option would look like this:</p> + <code type="none"> +$ erl -boot /home/me/ssl/start_ssl -proto_dist inet6_tls + -ssl_dist_opt server_certfile "/home/me/ssl/erlserver.pem" + -ssl_dist_opt server_secure_renegotiate true client_secure_renegotiate true + -sname ssl_test +Erlang (BEAM) emulator version 5.0 [source] + +Eshell V5.0 (abort with ^G) +(ssl_test@myhost)1> </code> + + <p>A node started in this way will only be able to communicate with + other nodes using SSL distribution over IPv6.</p> + </section> </chapter> diff --git a/lib/ssl/src/Makefile b/lib/ssl/src/Makefile index 790328dc45..7a7a373487 100644 --- a/lib/ssl/src/Makefile +++ b/lib/ssl/src/Makefile @@ -51,6 +51,7 @@ MODULES= \ ssl_dist_sup\ ssl_sup \ inet_tls_dist \ + inet6_tls_dist \ ssl_certificate\ ssl_pkix_db\ ssl_cipher \ diff --git a/lib/ssl/src/inet6_tls_dist.erl b/lib/ssl/src/inet6_tls_dist.erl new file mode 100644 index 0000000000..ffd7296f93 --- /dev/null +++ b/lib/ssl/src/inet6_tls_dist.erl @@ -0,0 +1,46 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2015. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% + +%% +-module(inet6_tls_dist). + +-export([childspecs/0, listen/1, accept/1, accept_connection/5, + setup/5, close/1, select/1]). + +childspecs() -> + inet_tls_dist:childspecs(). + +select(Node) -> + inet_tls_dist:gen_select(inet6_tcp, Node). + +listen(Name) -> + inet_tls_dist:gen_listen(inet6_tcp, Name). + +accept(Listen) -> + inet_tls_dist:gen_accept(inet6_tcp, Listen). + +accept_connection(AcceptPid, Socket, MyNode, Allowed, SetupTime) -> + inet_tls_dist:gen_accept_connection(inet6_tcp, AcceptPid, Socket, MyNode, Allowed, SetupTime). + +setup(Node, Type, MyNode, LongOrShortNames,SetupTime) -> + inet_tls_dist:gen_setup(inet6_tcp, Node, Type, MyNode, LongOrShortNames,SetupTime). + +close(Socket) -> + inet_tls_dist:close(Socket). diff --git a/lib/ssl/src/inet_tls_dist.erl b/lib/ssl/src/inet_tls_dist.erl index 6fe99a81c5..ec26142a75 100644 --- a/lib/ssl/src/inet_tls_dist.erl +++ b/lib/ssl/src/inet_tls_dist.erl @@ -24,6 +24,10 @@ -export([childspecs/0, listen/1, accept/1, accept_connection/5, setup/5, close/1, select/1, is_node_name/1]). +%% Generalized dist API +-export([gen_listen/2, gen_accept/2, gen_accept_connection/6, + gen_setup/6, gen_select/2]). + -include_lib("kernel/include/net_address.hrl"). -include_lib("kernel/include/dist.hrl"). -include_lib("kernel/include/dist_util.hrl"). @@ -33,9 +37,15 @@ childspecs() -> permanent, infinity, supervisor, [ssl_dist_sup]}]}. select(Node) -> + gen_select(inet_tcp, Node). + +gen_select(Driver, Node) -> case split_node(atom_to_list(Node), $@, []) of - [_,_Host] -> - true; + [_, Host] -> + case inet:getaddr(Host, Driver:family()) of + {ok, _} -> true; + _ -> false + end; _ -> false end. @@ -46,23 +56,35 @@ is_node_name(_) -> false. listen(Name) -> - ssl_tls_dist_proxy:listen(Name). + gen_listen(inet_tcp, Name). + +gen_listen(Driver, Name) -> + ssl_tls_dist_proxy:listen(Driver, Name). accept(Listen) -> - ssl_tls_dist_proxy:accept(Listen). + gen_accept(inet_tcp, Listen). + +gen_accept(Driver, Listen) -> + ssl_tls_dist_proxy:accept(Driver, Listen). accept_connection(AcceptPid, Socket, MyNode, Allowed, SetupTime) -> + gen_accept_connection(inet_tcp, AcceptPid, Socket, MyNode, Allowed, SetupTime). + +gen_accept_connection(Driver, AcceptPid, Socket, MyNode, Allowed, SetupTime) -> Kernel = self(), - spawn_link(fun() -> do_accept(Kernel, AcceptPid, Socket, + spawn_link(fun() -> do_accept(Driver, Kernel, AcceptPid, Socket, MyNode, Allowed, SetupTime) end). setup(Node, Type, MyNode, LongOrShortNames,SetupTime) -> + gen_setup(inet_tcp, Node, Type, MyNode, LongOrShortNames,SetupTime). + +gen_setup(Driver, Node, Type, MyNode, LongOrShortNames,SetupTime) -> Kernel = self(), - spawn_opt(fun() -> do_setup(Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) end, [link, {priority, max}]). + spawn_opt(fun() -> do_setup(Driver, Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) end, [link, {priority, max}]). -do_setup(Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) -> - [Name, Address] = splitnode(Node, LongOrShortNames), - case inet:getaddr(Address, inet) of +do_setup(Driver, Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) -> + [Name, Address] = splitnode(Driver, Node, LongOrShortNames), + case inet:getaddr(Address, Driver:family()) of {ok, Ip} -> Timer = dist_util:start_timer(SetupTime), case erl_epmd:port_please(Name, Ip) of @@ -70,7 +92,7 @@ do_setup(Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) -> ?trace("port_please(~p) -> version ~p~n", [Node,Version]), dist_util:reset_timer(Timer), - case ssl_tls_dist_proxy:connect(Ip, TcpPort) of + case ssl_tls_dist_proxy:connect(Driver, Ip, TcpPort) of {ok, Socket} -> HSData = connect_hs_data(Kernel, Node, MyNode, Socket, Timer, Version, Ip, TcpPort, Address, @@ -99,12 +121,12 @@ close(Socket) -> gen_tcp:close(Socket), ok. -do_accept(Kernel, AcceptPid, Socket, MyNode, Allowed, SetupTime) -> +do_accept(Driver, Kernel, AcceptPid, Socket, MyNode, Allowed, SetupTime) -> process_flag(priority, max), receive {AcceptPid, controller} -> Timer = dist_util:start_timer(SetupTime), - case check_ip(Socket) of + case check_ip(Driver, Socket) of true -> HSData = accept_hs_data(Kernel, MyNode, Socket, Timer, Allowed), dist_util:handshake_other_started(HSData); @@ -118,12 +140,12 @@ do_accept(Kernel, AcceptPid, Socket, MyNode, Allowed, SetupTime) -> %% Do only accept new connection attempts from nodes at our %% own LAN, if the check_ip environment parameter is true. %% ------------------------------------------------------------ -check_ip(Socket) -> +check_ip(Driver, Socket) -> case application:get_env(check_ip) of {ok, true} -> case get_ifs(Socket) of {ok, IFs, IP} -> - check_ip(IFs, IP); + check_ip(Driver, IFs, IP); _ -> ?shutdown(no_node) end; @@ -142,37 +164,21 @@ get_ifs(Socket) -> Error end. -check_ip([{OwnIP, _, Netmask}|IFs], PeerIP) -> - case {mask(Netmask, PeerIP), mask(Netmask, OwnIP)} of +check_ip(Driver, [{OwnIP, _, Netmask}|IFs], PeerIP) -> + case {Driver:mask(Netmask, PeerIP), Driver:mask(Netmask, OwnIP)} of {M, M} -> true; _ -> check_ip(IFs, PeerIP) end; -check_ip([], PeerIP) -> +check_ip(_Driver, [], PeerIP) -> {false, PeerIP}. -mask({M1,M2,M3,M4}, {IP1,IP2,IP3,IP4}) -> - {M1 band IP1, - M2 band IP2, - M3 band IP3, - M4 band IP4}; - -mask({M1,M2,M3,M4, M5, M6, M7, M8}, {IP1,IP2,IP3,IP4, IP5, IP6, IP7, IP8}) -> - {M1 band IP1, - M2 band IP2, - M3 band IP3, - M4 band IP4, - M5 band IP5, - M6 band IP6, - M7 band IP7, - M8 band IP8}. - %% If Node is illegal terminate the connection setup!! -splitnode(Node, LongOrShortNames) -> +splitnode(Driver, Node, LongOrShortNames) -> case split_node(atom_to_list(Node), $@, []) of [Name|Tail] when Tail =/= [] -> Host = lists:append(Tail), - check_node(Name, Node, Host, LongOrShortNames); + check_node(Driver, Name, Node, Host, LongOrShortNames); [_] -> error_logger:error_msg("** Nodename ~p illegal, no '@' character **~n", [Node]), @@ -182,15 +188,20 @@ splitnode(Node, LongOrShortNames) -> ?shutdown(Node) end. -check_node(Name, Node, Host, LongOrShortNames) -> +check_node(Driver, Name, Node, Host, LongOrShortNames) -> case split_node(Host, $., []) of [_] when LongOrShortNames == longnames -> - error_logger:error_msg("** System running to use " - "fully qualified " - "hostnames **~n" - "** Hostname ~s is illegal **~n", - [Host]), - ?shutdown(Node); + case Driver:parse_address(Host) of + {ok, _} -> + [Name, Host]; + _ -> + error_logger:error_msg("** System running to use " + "fully qualified " + "hostnames **~n" + "** Hostname ~s is illegal **~n", + [Host]), + ?shutdown(Node) + end; [_, _ | _] when LongOrShortNames == shortnames -> error_logger:error_msg("** System NOT running to use fully qualified " "hostnames **~n" diff --git a/lib/ssl/src/ssl.app.src b/lib/ssl/src/ssl.app.src index 619ab7b610..1a2bf90ccf 100644 --- a/lib/ssl/src/ssl.app.src +++ b/lib/ssl/src/ssl.app.src @@ -31,6 +31,7 @@ ssl_listen_tracker_sup, %% Erlang Distribution over SSL/TLS inet_tls_dist, + inet6_tls_dist, ssl_tls_dist_proxy, ssl_dist_sup, %% SSL/TLS session handling diff --git a/lib/ssl/src/ssl_tls_dist_proxy.erl b/lib/ssl/src/ssl_tls_dist_proxy.erl index 211badef56..4c789793ec 100644 --- a/lib/ssl/src/ssl_tls_dist_proxy.erl +++ b/lib/ssl/src/ssl_tls_dist_proxy.erl @@ -20,7 +20,7 @@ -module(ssl_tls_dist_proxy). --export([listen/1, accept/1, connect/2, get_tcp_address/1]). +-export([listen/2, accept/2, connect/3, get_tcp_address/1]). -export([init/1, start_link/0, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3, ssl_options/2]). @@ -39,14 +39,14 @@ %% Internal application API %%==================================================================== -listen(Name) -> - gen_server:call(?MODULE, {listen, Name}, infinity). +listen(Driver, Name) -> + gen_server:call(?MODULE, {listen, Driver, Name}, infinity). -accept(Listen) -> - gen_server:call(?MODULE, {accept, Listen}, infinity). +accept(Driver, Listen) -> + gen_server:call(?MODULE, {accept, Driver, Listen}, infinity). -connect(Ip, Port) -> - gen_server:call(?MODULE, {connect, Ip, Port}, infinity). +connect(Driver, Ip, Port) -> + gen_server:call(?MODULE, {connect, Driver, Ip, Port}, infinity). do_listen(Options) -> @@ -108,10 +108,11 @@ init([]) -> process_flag(priority, max), {ok, #state{}}. -handle_call({listen, Name}, _From, State) -> +handle_call({listen, Driver, Name}, _From, State) -> case gen_tcp:listen(0, [{active, false}, {packet,?PPRE}, {ip, loopback}]) of {ok, Socket} -> - {ok, World} = do_listen([{active, false}, binary, {packet,?PPRE}, {reuseaddr, true}]), + {ok, World} = do_listen([{active, false}, binary, {packet,?PPRE}, {reuseaddr, true}, + Driver:family()]), {ok, TcpAddress} = get_tcp_address(Socket), {ok, WorldTcpAddress} = get_tcp_address(World), {_,Port} = WorldTcpAddress#net_address.address, @@ -126,15 +127,15 @@ handle_call({listen, Name}, _From, State) -> {reply, Error, State} end; -handle_call({accept, Listen}, {From, _}, State = #state{listen={_, World}}) -> +handle_call({accept, _Driver, Listen}, {From, _}, State = #state{listen={_, World}}) -> Self = self(), ErtsPid = spawn_link(fun() -> accept_loop(Self, erts, Listen, From) end), WorldPid = spawn_link(fun() -> accept_loop(Self, world, World, Listen) end), {reply, ErtsPid, State#state{accept_loop={ErtsPid, WorldPid}}}; -handle_call({connect, Ip, Port}, {From, _}, State) -> +handle_call({connect, Driver, Ip, Port}, {From, _}, State) -> Me = self(), - Pid = spawn_link(fun() -> setup_proxy(Ip, Port, Me) end), + Pid = spawn_link(fun() -> setup_proxy(Driver, Ip, Port, Me) end), receive {Pid, go_ahead, LPort} -> Res = {ok, Socket} = try_connect(LPort), @@ -263,10 +264,11 @@ try_connect(Port) -> try_connect(Port) end. -setup_proxy(Ip, Port, Parent) -> +setup_proxy(Driver, Ip, Port, Parent) -> process_flag(trap_exit, true), Opts = connect_options(get_ssl_options(client)), - case ssl:connect(Ip, Port, [{active, true}, binary, {packet,?PPRE}, nodelay()] ++ Opts) of + case ssl:connect(Ip, Port, [{active, true}, binary, {packet,?PPRE}, nodelay(), + Driver:family()] ++ Opts) of {ok, World} -> {ok, ErtsL} = gen_tcp:listen(0, [{active, true}, {ip, loopback}, binary, {packet,?PPRE}]), {ok, #net_address{address={_,LPort}}} = get_tcp_address(ErtsL), diff --git a/lib/stdlib/doc/src/filename.xml b/lib/stdlib/doc/src/filename.xml index 77e262dbe6..65009753f3 100644 --- a/lib/stdlib/doc/src/filename.xml +++ b/lib/stdlib/doc/src/filename.xml @@ -47,7 +47,12 @@ <p>The module supports raw file names in the way that if a binary is present, or the file name cannot be interpreted according to the return value of <seealso marker="kernel:file#native_name_encoding/0">file:native_name_encoding/0</seealso>, a raw file name will also be returned. For example filename:join/1 provided with a path component being a binary (and also not being possible to interpret under the current native file name encoding) will result in a raw file name being returned (the join operation will have been performed of course). For more information about raw file names, see the <seealso marker="kernel:file">file</seealso> module.</p> </description> - + <datatypes> + <datatype> + <name name="basedir_type"/> + </datatype> + </datatypes> + <funcs> <func> <name name="absname" arity="1"/> @@ -102,6 +107,155 @@ </desc> </func> <func> + <name name="basedir" arity="2"/> + <fsummary>Equivalent to <c>basedir(<anno>Type</anno>,<anno>Application</anno>,#{})</c>.</fsummary> + <desc> + <p> + Equivalent to <seealso marker="#basedir-3"> + basedir(<anno>Type</anno>, <anno>Application</anno>, #{})</seealso>. + </p> + </desc> + </func> + <func> + <name name="basedir" arity="3"/> + <fsummary></fsummary> + <desc><marker id="basedir-3"/> + <p> + Returns a suitable path, or paths, for a given type. + If <c>os</c> is not set in <c><anno>Opts</anno></c> the function will default to + the native option, i.e. <c>'linux'</c>, <c>'darwin'</c> or <c>'windows'</c>, as understood + by <c>os:type/0</c>. Anything not recognized as <c>'darwin'</c> or <c>'windows'</c> is + interpreted as <c>'linux'</c>.</p> + <p> + The options <c>'author'</c> and <c>'version'</c> are only used with <c>'windows'</c> option mode. + </p> + <list type="bulleted"> + <item><c>user_cache</c> + <p>The path location is intended for transient data files on a local machine.</p> + <p> + On Linux: + Respects the os environment variable <c>XDG_CACHE_HOME</c>. + </p> + <pre> +1> <input>filename:basedir(user_cache, "my_application", #{os=>linux}).</input> +"/home/otptest/.cache/my_application"</pre> + On Darwin: <pre> +1> <input>filename:basedir(user_cache, "my_application", #{os=>darwin}).</input> +"/home/otptest/Library/Caches/my_application"</pre> + On Windows: <pre> +1> <input>filename:basedir(user_cache, "My App").</input> +"c:/Users/otptest/AppData/Local/My App/Cache" +2> <input>filename:basedir(user_cache, "My App").</input> +"c:/Users/otptest/AppData/Local/My App/Cache" +3> <input>filename:basedir(user_cache, "My App", #{author=>"Erlang"}).</input> +"c:/Users/otptest/AppData/Local/Erlang/My App/Cache" +4> <input>filename:basedir(user_cache, "My App", #{version=>"1.2"}).</input> +"c:/Users/otptest/AppData/Local/My App/1.2/Cache" +5> <input>filename:basedir(user_cache, "My App", #{author=>"Erlang",version=>"1.2"}).</input> +"c:/Users/otptest/AppData/Local/Erlang/My App/1.2/Cache"</pre> + </item> + <item><c>user_config</c> + <p> + The path location is intended for persistent configuration files. + </p> + <p> + On Linux: + Respects the os environment variable <c>XDG_CONFIG_HOME</c>. + </p> + <pre> +2> <input>filename:basedir(user_config, "my_application", #{os=>linux}).</input> +"/home/otptest/.config/my_application"</pre> + On Darwin:<pre> +2> <input>filename:basedir(user_config, "my_application", #{os=>darwin}).</input> +"/home/otptest/Library/Application Support/my_application"</pre> + On Windows:<pre> +1> <input>filename:basedir(user_config, "My App").</input> +"c:/Users/otptest/AppData/Roaming/My App" +2> <input>filename:basedir(user_config, "My App", #{author=>"Erlang", version=>"1.2"}).</input> +"c:/Users/otptest/AppData/Roaming/Erlang/My App/1.2"</pre> + </item> + <item><c>user_data</c> + <p> + The path location is intended for persistent data files. + </p> + <p> + On Linux: + Respects the os environment variable <c>XDG_DATA_HOME</c>. + </p> + <pre> +3> <input>filename:basedir(user_data, "my_application", #{os=>linux}).</input> +"/home/otptest/.local/my_application"</pre> + On Darwin:<pre> +3> <input>filename:basedir(user_data, "my_application", #{os=>darwin}).</input> +"/home/otptest/Library/Application Support/my_application"</pre> + On Windows:<pre> +8> <input>filename:basedir(user_data, "My App").</input> +"c:/Users/otptest/AppData/Local/My App" +9> <input>filename:basedir(user_data, "My App",#{author=>"Erlang",version=>"1.2"}).</input> +"c:/Users/otptest/AppData/Local/Erlang/My App/1.2"</pre> + </item> + <item><c>user_log</c> + <p>The path location is intended for transient log files on a local machine.</p> + <p> + On Linux: + Respects the os environment variable <c>XDG_CACHE_HOME</c>.</p> + <pre> +4> <input>filename:basedir(user_log, "my_application", #{os=>linux}).</input> +"/home/otptest/.cache/my_application/log"</pre> + On Darwin:<pre> +4> <input>filename:basedir(user_log, "my_application", #{os=>darwin}).</input> +"/home/otptest/Library/Caches/my_application"</pre> + On Windows:<pre> +12> <input>filename:basedir(user_log, "My App").</input> +"c:/Users/otptest/AppData/Local/My App/Logs" +13> <input>filename:basedir(user_log, "My App",#{author=>"Erlang",version=>"1.2"}).</input> +"c:/Users/otptest/AppData/Local/Erlang/My App/1.2/Logs"</pre> + </item> + <item><c>site_config</c><p> + On Linux: + Respects the os environment variable <c>XDG_CONFIG_DIRS</c>.</p> +<pre> +5> <input>filename:basedir(site_data, "my_application", #{os=>linux}).</input> +["/usr/local/share/my_application", + "/usr/share/my_application"] +6> <input>os:getenv("XDG_CONFIG_DIRS").</input> +"/etc/xdg/xdg-ubuntu:/usr/share/upstart/xdg:/etc/xdg" +7> <input>filename:basedir(site_config, "my_application", #{os=>linux}).</input> +["/etc/xdg/xdg-ubuntu/my_application", + "/usr/share/upstart/xdg/my_application", + "/etc/xdg/my_application"] +8> <input>os:unsetenv("XDG_CONFIG_DIRS").</input> +true +9> <input>filename:basedir(site_config, "my_application", #{os=>linux}).</input> +["/etc/xdg/my_application"]</pre> + On Darwin:<pre> +5> <input>filename:basedir(site_config, "my_application", #{os=>darwin}).</input> +["/Library/Application Support/my_application"]</pre> + </item> + <item><c>site_data</c><p> + On Linux: + Respects the os environment variable <c>XDG_DATA_DIRS</c>.</p> + <pre> +10> <input>os:getenv("XDG_DATA_DIRS").</input> +"/usr/share/ubuntu:/usr/share/gnome:/usr/local/share/:/usr/share/" +11> <input>filename:basedir(site_data, "my_application", #{os=>linux}).</input> +["/usr/share/ubuntu/my_application", + "/usr/share/gnome/my_application", + "/usr/local/share/my_application", + "/usr/share/my_application"] +12> <input>os:unsetenv("XDG_DATA_DIRS").</input> +true +13> <input>filename:basedir(site_data, "my_application", #{os=>linux}).</input> +["/usr/local/share/my_application", + "/usr/share/my_application"]</pre> + On Darwin:<pre> +5> <input>filename:basedir(site_data, "my_application", #{os=>darwin}).</input> +["/Library/Application Support/my_application"]</pre> + </item> + </list> + </desc> + </func> + <func> <name name="basename" arity="1"/> <fsummary>Return the last component of a filename</fsummary> <desc> diff --git a/lib/stdlib/src/filename.erl b/lib/stdlib/src/filename.erl index 008beb8b67..d921a69108 100644 --- a/lib/stdlib/src/filename.erl +++ b/lib/stdlib/src/filename.erl @@ -36,6 +36,7 @@ extension/1, join/1, join/2, pathtype/1, rootname/1, rootname/2, split/1, nativename/1]). -export([find_src/1, find_src/2, flatten/1]). +-export([basedir/2, basedir/3]). %% Undocumented and unsupported exports. -export([append/2]). @@ -139,6 +140,7 @@ absname_join(AbsBase, Name) -> -spec basename(Filename) -> file:filename_all() when Filename :: file:name_all(). + basename(Name) when is_binary(Name) -> case os:type() of {win32,_} -> @@ -954,3 +956,161 @@ filename_string_to_binary(List) -> Bin end. +%% Application Base Directories +%% basedir +%% http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html + +-type basedir_type() :: 'user_cache' | 'user_config' | 'user_data' + | 'user_log' + | 'site_config' | 'site_data'. + +-spec basedir(Type,Application) -> file:filename_all() when + Type :: basedir_type(), + Application :: string() | binary(). + +basedir(Type,Application) when is_atom(Type), is_list(Application) orelse + is_binary(Application) -> + basedir(Type, Application, #{}). + +-spec basedir(Type,Application,Opts) -> file:filename_all() when + Type :: basedir_type(), + Application :: string() | binary(), + Opts :: #{author => string() | binary(), + os => 'windows' | 'darwin' | 'linux', + version => string() | binary()}. + +basedir(Type,Application,Opts) when is_atom(Type), is_map(Opts), + is_list(Application) orelse + is_binary(Application) -> + Os = basedir_os_from_opts(Opts), + Name = basedir_name_from_opts(Os,Application,Opts), + Base = basedir_from_os(Type,Os), + case {Type,Os} of + {user_log,linux} -> + filename:join([Base,Name,"log"]); + {user_log,windows} -> + filename:join([Base,Name,"Logs"]); + {user_cache,windows} -> + filename:join([Base,Name,"Cache"]); + {Type,_} when Type =:= site_config orelse Type =:= site_data -> + [filename:join([B,Name]) || B <- Base]; + _ -> + filename:join([Base,Name]) + end. + +basedir_os_from_opts(#{os := linux}) -> linux; +basedir_os_from_opts(#{os := windows}) -> windows; +basedir_os_from_opts(#{os := darwin}) -> darwin; +basedir_os_from_opts(#{}) -> basedir_os_type(). + +basedir_name_from_opts(windows,App,#{author:=Author,version:=Vsn}) -> + filename:join([Author,App,Vsn]); +basedir_name_from_opts(windows,App,#{author:=Author}) -> + filename:join([Author,App]); +basedir_name_from_opts(_,App,#{version:=Vsn}) -> + filename:join([App,Vsn]); +basedir_name_from_opts(_,App,_) -> + App. + +basedir_from_os(Type,Os) -> + case Os of + linux -> basedir_linux(Type); + darwin -> basedir_darwin(Type); + windows -> basedir_windows(Type) + end. + +-define(basedir_linux_user_data, ".local/share"). +-define(basedir_linux_user_config, ".config"). +-define(basedir_linux_user_cache, ".cache"). +-define(basedir_linux_user_log, ".cache"). %% .cache/App/log +-define(basedir_linux_site_data, "/usr/local/share/:/usr/share/"). +-define(basedir_linux_site_config, "/etc/xdg"). + +basedir_linux(Type) -> + case Type of + user_data -> getenv("XDG_DATA_HOME", ?basedir_linux_user_data, true); + user_config -> getenv("XDG_CONFIG_HOME",?basedir_linux_user_config,true); + user_cache -> getenv("XDG_CACHE_HOME", ?basedir_linux_user_cache, true); + user_log -> getenv("XDG_CACHE_HOME", ?basedir_linux_user_log, true); + site_data -> + Base = getenv("XDG_DATA_DIRS",?basedir_linux_site_data,false), + string:tokens(Base,":"); + site_config -> + Base = getenv("XDG_CONFIG_DIRS",?basedir_linux_site_config,false), + string:tokens(Base,":") + end. + +-define(basedir_darwin_user_data, "Library/Application Support"). +-define(basedir_darwin_user_config, "Library/Application Support"). +-define(basedir_darwin_user_cache, "Library/Caches"). +-define(basedir_darwin_user_log, "Library/Logs"). +-define(basedir_darwin_site_data, "/Library/Application Support"). +-define(basedir_darwin_site_config, "/Library/Application Support"). + +basedir_darwin(Type) -> + case Type of + user_data -> basedir_join_home(?basedir_darwin_user_data); + user_config -> basedir_join_home(?basedir_darwin_user_config); + user_cache -> basedir_join_home(?basedir_darwin_user_cache); + user_log -> basedir_join_home(?basedir_darwin_user_log); + site_data -> [?basedir_darwin_site_data]; + site_config -> [?basedir_darwin_site_config] + end. + +%% On Windows: +%% ex. C:\Users\egil\AppData\Local\Ericsson\Erlang +%% %LOCALAPPDATA% is defined on Windows 7 and onwards +%% %APPDATA% is used instead of %LOCALAPPDATA% if it's not defined. +%% %APPDATA% is used for roaming, i.e. for user_config on Windows 7 and beyond. +%% +%% user_data %LOCALAPPDATA%[/$author]/$appname[/$version] +%% user_config %APPDATA%[/$author]/$appname[/$version] +%% user_cache %LOCALAPPDATA%[/$author]/$appname[/$version]/Cache +%% user_log %LOCALAPPDATA%[/$author]/$appname[/$version]/Logs + +basedir_windows(Type) -> + %% If LOCALAPPDATA is not defined we are likely on an + %% XP machine. Use APPDATA instead. + AppData = basedir_windows_appdata(), + case Type of + user_data -> getenv("LOCALAPPDATA", AppData); + user_config -> AppData; + user_cache -> getenv("LOCALAPPDATA", AppData); + user_log -> getenv("LOCALAPPDATA", AppData); + site_data -> []; + site_config -> [] + end. + +basedir_windows_appdata() -> + case os:getenv("APPDATA") of + Invalid when Invalid =:= false orelse Invalid =:= [] -> + erlang:error(noappdata); + Val -> Val + end. + +%% basedir aux + +getenv(K,Def,false) -> getenv(K,Def); +getenv(K,Def,true) -> getenv(K,basedir_join_home(Def)). + +getenv(K,Def) -> + case os:getenv(K) of + [] -> Def; + false -> Def; + Val -> Val + end. + +basedir_join_home(Dir) -> + case os:getenv("HOME") of + false -> + {ok,[[Home]]} = init:get_argument(home), + filename:join(Home,Dir); + Home -> filename:join(Home,Dir) + end. + +basedir_os_type() -> + case os:type() of + {unix,darwin} -> darwin; + {win32,_} -> windows; + _ -> linux + end. diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl index 0dc2626ae8..6f546da7b8 100644 --- a/lib/stdlib/src/otp_internal.erl +++ b/lib/stdlib/src/otp_internal.erl @@ -650,7 +650,7 @@ obsolete_1(code, rehash, 0) -> {deprecated, "deprecated because the code path cache feature has been removed"}; obsolete_1(overload, _, _) -> - {deprecated, "deprecated; will be removed in OTP 19"}; + {removed, "removed in OTP 19"}; obsolete_1(_, _, _) -> no. diff --git a/lib/stdlib/src/stdlib.appup.src b/lib/stdlib/src/stdlib.appup.src index 04cdf31ada..15d8857656 100644 --- a/lib/stdlib/src/stdlib.appup.src +++ b/lib/stdlib/src/stdlib.appup.src @@ -18,9 +18,9 @@ %% %CopyrightEnd% {"%VSN%", %% Up from - max one major revision back - [{<<"2\\.[5-7](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.* - {<<"2\\.[0-4](\\.[0-9]+)*">>,[restart_new_emulator]}], % 17.0-17.5 + [{<<"3\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.* + {<<"2\\.[5-8](\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-18.* %% Down to - max one major revision back - [{<<"2\\.[5-7](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-18.* - {<<"2\\.[0-4](\\.[0-9]+)*">>,[restart_new_emulator]}] % 17.0-17.5 + [{<<"3\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.* + {<<"2\\.[5-8](\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-18.* }. diff --git a/lib/stdlib/test/filename_SUITE.erl b/lib/stdlib/test/filename_SUITE.erl index 8ecbc7eadf..7f2e4771f3 100644 --- a/lib/stdlib/test/filename_SUITE.erl +++ b/lib/stdlib/test/filename_SUITE.erl @@ -28,21 +28,29 @@ basename_bin_1/1, basename_bin_2/1, dirname_bin/1, extension_bin/1, join_bin/1, t_nativename_bin/1]). -export([pathtype_bin/1,rootname_bin/1,split_bin/1]). +-export([t_basedir_api/1, t_basedir_xdg/1, t_basedir_windows/1]). -include_lib("common_test/include/ct.hrl"). suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [absname, absname_2, basename_1, basename_2, dirname, - extension, - join, pathtype, rootname, split, t_nativename, find_src, - absname_bin, absname_bin_2, basename_bin_1, basename_bin_2, dirname_bin, - extension_bin, - join_bin, pathtype_bin, rootname_bin, split_bin, t_nativename_bin]. + [absname, absname_2, + find_src, + absname_bin, absname_bin_2, + {group,p}, + t_basedir_xdg, t_basedir_windows]. groups() -> - []. + [{p, [parallel], + [dirname, + extension, extension_bin, + join, pathtype, rootname, split, t_nativename, + basename_1, basename_2, + basename_bin_1, basename_bin_2, dirname_bin, + join_bin, pathtype_bin, rootname_bin, split_bin, + t_nativename_bin, + t_basedir_api]}]. init_per_suite(Config) -> Config. @@ -61,58 +69,59 @@ end_per_group(_GroupName, Config) -> absname(Config) when is_list(Config) -> case os:type() of - {win32, _} -> - ?line [Drive|_] = ?config(priv_dir, Config), - ?line Temp = filename:join([Drive|":/"], "temp"), - ?line case file:make_dir(Temp) of - ok -> ok; - {error,eexist} -> ok - end, - ?line {ok,Cwd} = file:get_cwd(), - ?line ok = file:set_cwd(Temp), - ?line [Drive|":/temp/foo"] = filename:absname(foo), - ?line [Drive|":/temp/foo"] = filename:absname("foo"), - ?line [Drive|":/temp/../ebin"] = filename:absname("../ebin"), - ?line [Drive|":/erlang"] = filename:absname("/erlang"), - ?line [Drive|":/erlang/src"] = filename:absname("/erlang/src"), - ?line [Drive|":/erlang/src"] = filename:absname("\\erlang\\src"), - ?line [Drive|":/temp/erlang"] = filename:absname([Drive|":erlang"]), - ?line [Drive|":/temp/erlang/src"] = - filename:absname([Drive|":erlang/src"]), - ?line [Drive|":/temp/erlang/src"] = - filename:absname([Drive|":erlang\\src\\"]), - ?line "a:/erlang" = filename:absname("a:erlang"), - - ?line file:set_cwd([Drive|":/"]), - ?line [Drive|":/foo"] = filename:absname(foo), - ?line [Drive|":/foo"] = filename:absname("foo"), - ?line [Drive|":/../ebin"] = filename:absname("../ebin"), - ?line [Drive|":/erlang"] = filename:absname("/erlang"), - ?line [Drive|":/erlang/src"] = filename:absname("/erlang/src"), - ?line [Drive|":/erlang/src"] = filename:absname(["/erlang",'/src']), - ?line [Drive|":/erlang/src"] = filename:absname("\\erlang\\\\src"), - ?line [Drive|":/erlang"] = filename:absname([Drive|":erlang"]), - ?line [Drive|":/erlang/src"] = filename:absname([Drive|":erlang/src"]), - ?line "a:/erlang" = filename:absname("a:erlang"), - - ?line file:set_cwd(Cwd), - ok; - {unix, _} -> - ?line ok = file:set_cwd("/usr"), - ?line "/usr/foo" = filename:absname(foo), - ?line "/usr/foo" = filename:absname("foo"), - ?line "/usr/../ebin" = filename:absname("../ebin"), - ?line file:set_cwd("/"), - ?line "/foo" = filename:absname(foo), - ?line "/foo" = filename:absname("foo"), - ?line "/../ebin" = filename:absname("../ebin"), - ?line "/erlang" = filename:absname("/erlang"), - ?line "/erlang/src" = filename:absname("/erlang/src"), - ?line "/erlang/src" = filename:absname(["/erl",'ang/s',"rc"]), - ?line "/erlang/src" = filename:absname(["/erl",'a','ng',"/",'s',"rc"]), - ?line "/erlang/src" = filename:absname("/erlang///src"), - ?line "/file_sorter.erl" = filename:absname([file_sorter|'.erl']), - ok + {win32, _} -> + [Drive|_] = ?config(priv_dir, Config), + Temp = filename:join([Drive|":/"], "temp"), + case file:make_dir(Temp) of + ok -> ok; + {error,eexist} -> ok + end, + {ok,Cwd} = file:get_cwd(), + ok = file:set_cwd(Temp), + [Drive|":/temp/foo"] = filename:absname(foo), + [Drive|":/temp/foo"] = filename:absname("foo"), + [Drive|":/temp/../ebin"] = filename:absname("../ebin"), + [Drive|":/erlang"] = filename:absname("/erlang"), + [Drive|":/erlang/src"] = filename:absname("/erlang/src"), + [Drive|":/erlang/src"] = filename:absname("\\erlang\\src"), + [Drive|":/temp/erlang"] = filename:absname([Drive|":erlang"]), + [Drive|":/temp/erlang/src"] = + filename:absname([Drive|":erlang/src"]), + [Drive|":/temp/erlang/src"] = + filename:absname([Drive|":erlang\\src\\"]), + "a:/erlang" = filename:absname("a:erlang"), + + file:set_cwd([Drive|":/"]), + [Drive|":/foo"] = filename:absname(foo), + [Drive|":/foo"] = filename:absname("foo"), + [Drive|":/../ebin"] = filename:absname("../ebin"), + [Drive|":/erlang"] = filename:absname("/erlang"), + [Drive|":/erlang/src"] = filename:absname("/erlang/src"), + [Drive|":/erlang/src"] = filename:absname(["/erlang",'/src']), + [Drive|":/erlang/src"] = filename:absname("\\erlang\\\\src"), + [Drive|":/erlang"] = filename:absname([Drive|":erlang"]), + [Drive|":/erlang/src"] = filename:absname([Drive|":erlang/src"]), + "a:/erlang" = filename:absname("a:erlang"), + + file:set_cwd(Cwd), + ok; + {unix, _} -> + ok = file:set_cwd("/usr"), + "/usr/foo" = filename:absname(foo), + "/usr/foo" = filename:absname("foo"), + "/usr/../ebin" = filename:absname("../ebin"), + + file:set_cwd("/"), + "/foo" = filename:absname(foo), + "/foo" = filename:absname("foo"), + "/../ebin" = filename:absname("../ebin"), + "/erlang" = filename:absname("/erlang"), + "/erlang/src" = filename:absname("/erlang/src"), + "/erlang/src" = filename:absname(["/erl",'ang/s',"rc"]), + "/erlang/src" = filename:absname(["/erl",'a','ng',"/",'s',"rc"]), + "/erlang/src" = filename:absname("/erlang///src"), + "/file_sorter.erl" = filename:absname([file_sorter|'.erl']), + ok end. @@ -120,125 +129,123 @@ absname(Config) when is_list(Config) -> absname_2(Config) when is_list(Config) -> case os:type() of - {win32, _} -> - ?line [Drive|_] = ?config(priv_dir, Config), - ?line [Drive|":/temp/foo"] = filename:absname(foo, [Drive|":/temp"]), - ?line [Drive|":/temp/foo"] = filename:absname("foo", [Drive|":/temp"]), - ?line [Drive|":/temp/../ebin"] = filename:absname("../ebin", - [Drive|":/temp"]), - ?line [Drive|":/erlang"] = filename:absname("/erlang", [Drive|":/temp"]), - ?line [Drive|":/erlang/src"] = filename:absname("/erlang/src", - [Drive|":/temp"]), - ?line [Drive|":/erlang/src"] = filename:absname("\\erlang\\src", - [Drive|":/temp"]), - ?line [Drive|":/temp/erlang"] = filename:absname([Drive|":erlang"], - [Drive|":/temp"]), - ?line [Drive|":/temp/erlang/src"] = filename:absname([Drive|":erlang/src"], - [Drive|":/temp"]), - ?line [Drive|":/temp/erlang/src"] = - filename:absname([Drive|":erlang\\src\\"], [Drive|":/temp"]), - ?line "a:/erlang" = filename:absname("a:erlang", [Drive|":/temp"]), - - ?line file:set_cwd([Drive|":/"]), - ?line [Drive|":/foo"] = filename:absname(foo, [Drive|":/"]), - ?line [Drive|":/foo"] = filename:absname("foo", [Drive|":/"]), - ?line [Drive|":/../ebin"] = filename:absname("../ebin", [Drive|":/"]), - ?line [Drive|":/erlang"] = filename:absname("/erlang", [Drive|":/"]), - ?line [Drive|":/erlang/src"] = filename:absname("/erlang/src", - [Drive|":/"]), - ?line [Drive|":/erlang/src"] = filename:absname("\\erlang\\\\src", - [Drive|":/"]), - ?line [Drive|":/erlang"] = filename:absname([Drive|":erlang"], - [Drive|":/"]), - ?line [Drive|":/erlang/src"] = filename:absname([Drive|":erlang/src"], - [Drive|":/"]), - ?line "a:/erlang" = filename:absname("a:erlang", [Drive|":/"]), - - ok; - _ -> - ?line "/usr/foo" = filename:absname(foo, "/usr"), - ?line "/usr/foo" = filename:absname("foo", "/usr"), - ?line "/usr/../ebin" = filename:absname("../ebin", "/usr"), - - ?line "/foo" = filename:absname(foo, "/"), - ?line "/foo" = filename:absname("foo", "/"), - ?line "/../ebin" = filename:absname("../ebin", "/"), - ?line "/erlang" = filename:absname("/erlang", "/"), - ?line "/erlang/src" = filename:absname("/erlang/src", "/"), - ?line "/erlang/src" = filename:absname("/erlang///src", "/"), - ok + {win32, _} -> + [Drive|_] = ?config(priv_dir, Config), + [Drive|":/temp/foo"] = filename:absname(foo, [Drive|":/temp"]), + [Drive|":/temp/foo"] = filename:absname("foo", [Drive|":/temp"]), + [Drive|":/temp/../ebin"] = filename:absname("../ebin", + [Drive|":/temp"]), + [Drive|":/erlang"] = filename:absname("/erlang", [Drive|":/temp"]), + [Drive|":/erlang/src"] = filename:absname("/erlang/src", + [Drive|":/temp"]), + [Drive|":/erlang/src"] = filename:absname("\\erlang\\src", + [Drive|":/temp"]), + [Drive|":/temp/erlang"] = filename:absname([Drive|":erlang"], + [Drive|":/temp"]), + [Drive|":/temp/erlang/src"] = filename:absname([Drive|":erlang/src"], + [Drive|":/temp"]), + [Drive|":/temp/erlang/src"] = + filename:absname([Drive|":erlang\\src\\"], [Drive|":/temp"]), + "a:/erlang" = filename:absname("a:erlang", [Drive|":/temp"]), + + file:set_cwd([Drive|":/"]), + [Drive|":/foo"] = filename:absname(foo, [Drive|":/"]), + [Drive|":/foo"] = filename:absname("foo", [Drive|":/"]), + [Drive|":/../ebin"] = filename:absname("../ebin", [Drive|":/"]), + [Drive|":/erlang"] = filename:absname("/erlang", [Drive|":/"]), + [Drive|":/erlang/src"] = filename:absname("/erlang/src", + [Drive|":/"]), + [Drive|":/erlang/src"] = filename:absname("\\erlang\\\\src", + [Drive|":/"]), + [Drive|":/erlang"] = filename:absname([Drive|":erlang"], + [Drive|":/"]), + [Drive|":/erlang/src"] = filename:absname([Drive|":erlang/src"], + [Drive|":/"]), + "a:/erlang" = filename:absname("a:erlang", [Drive|":/"]), + + ok; + _ -> + "/usr/foo" = filename:absname(foo, "/usr"), + "/usr/foo" = filename:absname("foo", "/usr"), + "/usr/../ebin" = filename:absname("../ebin", "/usr"), + + "/foo" = filename:absname(foo, "/"), + "/foo" = filename:absname("foo", "/"), + "/../ebin" = filename:absname("../ebin", "/"), + "/erlang" = filename:absname("/erlang", "/"), + "/erlang/src" = filename:absname("/erlang/src", "/"), + "/erlang/src" = filename:absname("/erlang///src", "/"), + ok end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% basename_1(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(10)), - ?line "." = filename:basename("."), - ?line "foo" = filename:basename("foo"), - ?line "foo" = filename:basename("/usr/foo"), - ?line "foo.erl" = filename:basename("A:usr/foo.erl"), - ?line "foo" = filename:basename('/usr/foo'), - ?line "foo" = filename:basename(["/usr","/","f","o","o"]), - ?line "foo" = filename:basename(["/usr/",foo]), - ?line "foo" = filename:basename(["/usr/f",oo]), - ?line "foo" = filename:basename(["usr/", "foo"]), - ?line "foo" = filename:basename(["usr/"|foo]), - ?line "foo" = filename:basename(["usr/foo/"]), - ?line case os:type() of - {win32, _} -> - ?line "foo" = filename:basename(["usr\\foo\\"]), - ?line "foo" = filename:basename("A:\\usr\\foo"), - ?line "foo" = filename:basename("A:foo"); - _ -> - ?line "strange\\but\\true" = - filename:basename("strange\\but\\true") - end, - ?line test_server:timetrap_cancel(Dog), + Dog = test_server:timetrap(test_server:seconds(10)), + "." = filename:basename("."), + "foo" = filename:basename("foo"), + "foo" = filename:basename("/usr/foo"), + "foo.erl" = filename:basename("A:usr/foo.erl"), + "foo" = filename:basename('/usr/foo'), + "foo" = filename:basename(["/usr","/","f","o","o"]), + "foo" = filename:basename(["/usr/",foo]), + "foo" = filename:basename(["/usr/f",oo]), + "foo" = filename:basename(["usr/", "foo"]), + "foo" = filename:basename(["usr/"|foo]), + "foo" = filename:basename(["usr/foo/"]), + case os:type() of + {win32, _} -> + "foo" = filename:basename(["usr\\foo\\"]), + "foo" = filename:basename("A:\\usr\\foo"), + "foo" = filename:basename("A:foo"); + _ -> + "strange\\but\\true" = + filename:basename("strange\\but\\true") + end, + test_server:timetrap_cancel(Dog), ok. basename_2(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(10)), - ?line "." = filename:basename(".", ".erl"), - ?line "foo" = filename:basename("foo.erl", ".erl"), - ?line "foo" = filename:basename('foo.erl', ".erl"), - ?line "foo" = filename:basename("foo.erl", '.erl'), - ?line "foo" = filename:basename(["/usr","/","f","oo"], ".erl"), - ?line "foo.erl" = filename:basename("/usr/foo.erl", ".hrl"), - ?line "foo.erl" = filename:basename("/usr.hrl/foo.erl", ".hrl"), - ?line "foo" = filename:basename("/usr.hrl/foo", ".hrl"), - ?line "foo" = filename:basename("usr/foo/", ".erl"), - ?line "foo.erl" = filename:basename("usr/foo.erl/", ".erl"), - ?line "foo.erl" = filename:basename("usr/foo.erl/", '.erl'), - ?line "foo" = filename:basename(["/usr",'/','f','oo'], ".erl"), - ?line "foo.erl" = filename:basename(["usr/foo.e",'rl/'], ".erl"), - ?line case os:type() of - {win32, _} -> - ?line "foo" = filename:basename("A:foo", ".erl"), - ?line "foo.erl" = filename:basename("a:\\usr\\foo.erl", - ".hrl"), - ?line "foo.erl" = filename:basename("c:\\usr.hrl\\foo.erl", - ".hrl"), - ?line "foo" = filename:basename("A:\\usr\\foo", ".hrl"); - _ -> - ?line "strange\\but\\true" = - filename:basename("strange\\but\\true.erl", ".erl"), - ?line "strange\\but\\true" = - filename:basename("strange\\but\\true", ".erl") - end, - ?line test_server:timetrap_cancel(Dog), + Dog = test_server:timetrap(test_server:seconds(10)), + "." = filename:basename(".", ".erl"), + "foo" = filename:basename("foo.erl", ".erl"), + "foo" = filename:basename('foo.erl', ".erl"), + "foo" = filename:basename("foo.erl", '.erl'), + "foo" = filename:basename(["/usr","/","f","oo"], ".erl"), + "foo.erl" = filename:basename("/usr/foo.erl", ".hrl"), + "foo.erl" = filename:basename("/usr.hrl/foo.erl", ".hrl"), + "foo" = filename:basename("/usr.hrl/foo", ".hrl"), + "foo" = filename:basename("usr/foo/", ".erl"), + "foo.erl" = filename:basename("usr/foo.erl/", ".erl"), + "foo.erl" = filename:basename("usr/foo.erl/", '.erl'), + "foo" = filename:basename(["/usr",'/','f','oo'], ".erl"), + "foo.erl" = filename:basename(["usr/foo.e",'rl/'], ".erl"), + case os:type() of + {win32, _} -> + "foo" = filename:basename("A:foo", ".erl"), + "foo.erl" = filename:basename("a:\\usr\\foo.erl", ".hrl"), + "foo.erl" = filename:basename("c:\\usr.hrl\\foo.erl", ".hrl"), + "foo" = filename:basename("A:\\usr\\foo", ".hrl"); + _ -> + "strange\\but\\true" = + filename:basename("strange\\but\\true.erl", ".erl"), + "strange\\but\\true" = + filename:basename("strange\\but\\true", ".erl") + end, + test_server:timetrap_cancel(Dog), ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% dirname(Config) when is_list(Config) -> case os:type() of - {win32,_} -> - "A:/usr" = filename:dirname("A:/usr/foo.erl"), - "A:usr" = filename:dirname("A:usr/foo.erl"), - "/usr" = filename:dirname("\\usr\\foo.erl"), - "/" = filename:dirname("\\usr"), - "A:" = filename:dirname("A:"); - _ -> true + {win32,_} -> + "A:/usr" = filename:dirname("A:/usr/foo.erl"), + "A:usr" = filename:dirname("A:usr/foo.erl"), + "/usr" = filename:dirname("\\usr\\foo.erl"), + "/" = filename:dirname("\\usr"), + "A:" = filename:dirname("A:"); + _ -> true end, "usr" = filename:dirname("usr///foo.erl"), "." = filename:dirname("foo.erl"), @@ -258,23 +265,22 @@ dirname(Config) when is_list(Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% extension(Config) when is_list(Config) -> - ?line ".erl" = filename:extension("A:/usr/foo.erl"), - ?line ".erl" = filename:extension("A:/usr/foo.nisse.erl"), - ?line ".erl" = filename:extension(["A:/usr/", 'foo.ni', "sse.erl"]), - ?line ".erl" = filename:extension(["A:/usr/", 'foo.ni', "sse.e", 'rl']), - ?line ".erl" = filename:extension(["A:/usr/", 'foo.ni', "sse.e"|'rl']), - ?line ".erl" = filename:extension("A:/usr.bar/foo.nisse.erl"), - ?line "" = filename:extension("A:/usr.bar/foo"), - ?line "" = filename:extension("A:/usr/foo"), - ?line case os:type() of - {win32, _} -> - ?line "" = filename:extension("A:\\usr\\foo"), - ?line ".erl" = - filename:extension("A:/usr.bar/foo.nisse.erl"), - ?line "" = filename:extension("A:/usr.bar/foo"), - ok; - _ -> ok - end. + ".erl" = filename:extension("A:/usr/foo.erl"), + ".erl" = filename:extension("A:/usr/foo.nisse.erl"), + ".erl" = filename:extension(["A:/usr/", 'foo.ni', "sse.erl"]), + ".erl" = filename:extension(["A:/usr/", 'foo.ni', "sse.e", 'rl']), + ".erl" = filename:extension(["A:/usr/", 'foo.ni', "sse.e"|'rl']), + ".erl" = filename:extension("A:/usr.bar/foo.nisse.erl"), + "" = filename:extension("A:/usr.bar/foo"), + "" = filename:extension("A:/usr/foo"), + case os:type() of + {win32, _} -> + "" = filename:extension("A:\\usr\\foo"), + ".erl" = filename:extension("A:/usr.bar/foo.nisse.erl"), + "" = filename:extension("A:/usr.bar/foo"), + ok; + _ -> ok + end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -282,8 +288,8 @@ join(Config) when is_list(Config) -> %% Whenever joining two elements, test the equivalence between %% join/1 and join/2 (OTP-12158) by using help function %% filename_join/2. - ?line "/" = filename:join(["/"]), - ?line "/" = filename:join(["//"]), + "/" = filename:join(["/"]), + "/" = filename:join(["//"]), "usr/foo.erl" = filename_join("usr","foo.erl"), "/src/foo.erl" = filename_join(usr, "/src/foo.erl"), "/src/foo.erl" = filename_join("/src/",'foo.erl'), @@ -291,7 +297,7 @@ join(Config) when is_list(Config) -> "/src/foo.erl" = filename_join("usr", "/src/foo.erl"), %% Make sure that redundant slashes work too. - ?line "a/b/c/d/e/f/g" = filename:join(["a//b/c/////d//e/f/g"]), + "a/b/c/d/e/f/g" = filename:join(["a//b/c/////d//e/f/g"]), "a/b/c/d/e/f/g" = filename_join("a//b/c/", "d//e/f/g"), "a/b/c/d/e/f/g" = filename_join("a//b/c", "d//e/f/g"), "/d/e/f/g" = filename_join("a//b/c", "/d//e/f/g"), @@ -324,30 +330,25 @@ join(Config) when is_list(Config) -> "/b" = filename_join("/a/","/b/"), "/a/b" = filename_join("/a/","b/"), - ?line case os:type() of - {win32, _} -> - ?line "d:/" = filename:join(["D:/"]), - ?line "d:/" = filename:join(["D:\\"]), - "d:/abc" = filename_join("D:/", "abc"), - "d:abc" = filename_join("D:", "abc"), - ?line "a/b/c/d/e/f/g" = - filename:join(["a//b\\c//\\/\\d/\\e/f\\g"]), - ?line "a:usr/foo.erl" = - filename:join(["A:","usr","foo.erl"]), - ?line "/usr/foo.erl" = - filename:join(["A:","/usr","foo.erl"]), - "c:usr" = filename_join("A:","C:usr"), - "a:usr" = filename_join("A:","usr"), - "c:/usr" = filename_join("A:", "C:/usr"), - ?line "c:/usr/foo.erl" = - filename:join(["A:","C:/usr","foo.erl"]), - ?line "c:usr/foo.erl" = - filename:join(["A:","C:usr","foo.erl"]), - ?line "d:/foo" = filename:join([$D, $:, $/, []], "foo"), - ok; - _ -> - ok - end. + case os:type() of + {win32, _} -> + "d:/" = filename:join(["D:/"]), + "d:/" = filename:join(["D:\\"]), + "d:/abc" = filename_join("D:/", "abc"), + "d:abc" = filename_join("D:", "abc"), + "a/b/c/d/e/f/g" = filename:join(["a//b\\c//\\/\\d/\\e/f\\g"]), + "a:usr/foo.erl" = filename:join(["A:","usr","foo.erl"]), + "/usr/foo.erl" = filename:join(["A:","/usr","foo.erl"]), + "c:usr" = filename_join("A:","C:usr"), + "a:usr" = filename_join("A:","usr"), + "c:/usr" = filename_join("A:", "C:/usr"), + "c:/usr/foo.erl" = filename:join(["A:","C:/usr","foo.erl"]), + "c:usr/foo.erl" = filename:join(["A:","C:usr","foo.erl"]), + "d:/foo" = filename:join([$D, $:, $/, []], "foo"), + ok; + _ -> + ok + end. %% Make sure join([A,B]) is equivalent to join(A,B) (OTP-12158) filename_join(A,B) -> @@ -355,92 +356,92 @@ filename_join(A,B) -> Res = filename:join([A,B]). pathtype(Config) when is_list(Config) -> - ?line relative = filename:pathtype(".."), - ?line relative = filename:pathtype("foo"), - ?line relative = filename:pathtype("foo/bar"), - ?line relative = filename:pathtype('foo/bar'), - ?line relative = filename:pathtype(['f','oo',"/bar"]), + relative = filename:pathtype(".."), + relative = filename:pathtype("foo"), + relative = filename:pathtype("foo/bar"), + relative = filename:pathtype('foo/bar'), + relative = filename:pathtype(['f','oo',"/bar"]), case os:type() of - {win32, _} -> - ?line volumerelative = filename:pathtype("/usr/local/bin"), - ?line volumerelative = filename:pathtype("A:usr/local/bin"), - ok; - _ -> - ?line absolute = filename:pathtype("/"), - ?line absolute = filename:pathtype("/usr/local/bin"), - ok + {win32, _} -> + volumerelative = filename:pathtype("/usr/local/bin"), + volumerelative = filename:pathtype("A:usr/local/bin"), + ok; + _ -> + absolute = filename:pathtype("/"), + absolute = filename:pathtype("/usr/local/bin"), + ok end. rootname(Config) when is_list(Config) -> - ?line "/jam.src/kalle" = filename:rootname("/jam.src/kalle"), - ?line "/jam.src/foo" = filename:rootname("/jam.src/foo.erl"), - ?line "/jam.src/foo" = filename:rootname(["/ja",'m.sr',"c/foo.erl"]), - ?line "/jam.src/foo" = filename:rootname("/jam.src/foo.erl", ".erl"), - ?line "/jam.src/foo.jam" = filename:rootname("/jam.src/foo.jam", ".erl"), - ?line "/jam.src/foo.jam" = filename:rootname(["/jam.sr",'c/foo.j',"am"],".erl"), - ?line "/jam.src/foo.jam" = filename:rootname(["/jam.sr",'c/foo.j'|am],".erl"), + "/jam.src/kalle" = filename:rootname("/jam.src/kalle"), + "/jam.src/foo" = filename:rootname("/jam.src/foo.erl"), + "/jam.src/foo" = filename:rootname(["/ja",'m.sr',"c/foo.erl"]), + "/jam.src/foo" = filename:rootname("/jam.src/foo.erl", ".erl"), + "/jam.src/foo.jam" = filename:rootname("/jam.src/foo.jam", ".erl"), + "/jam.src/foo.jam" = filename:rootname(["/jam.sr",'c/foo.j',"am"],".erl"), + "/jam.src/foo.jam" = filename:rootname(["/jam.sr",'c/foo.j'|am],".erl"), ok. split(Config) when is_list(Config) -> - ?line ["/","usr","local","bin"] = filename:split("/usr/local/bin"), - ?line ["foo","bar"]= filename:split("foo/bar"), - ?line ["foo", "bar", "hello"]= filename:split("foo////bar//hello"), - ?line ["foo", "bar", "hello"]= filename:split(["foo//",'//bar//h',"ello"]), - ?line ["foo", "bar", "hello"]= filename:split(["foo//",'//bar//h'|ello]), + ["/","usr","local","bin"] = filename:split("/usr/local/bin"), + ["foo","bar"]= filename:split("foo/bar"), + ["foo", "bar", "hello"]= filename:split("foo////bar//hello"), + ["foo", "bar", "hello"]= filename:split(["foo//",'//bar//h',"ello"]), + ["foo", "bar", "hello"]= filename:split(["foo//",'//bar//h'|ello]), ["/"] = filename:split("/"), [] = filename:split(""), case os:type() of - {win32,_} -> - ?line ["a:/","msdev","include"] = - filename:split("a:/msdev/include"), - ?line ["a:/","msdev","include"] = - filename:split("A:/msdev/include"), - ?line ["msdev","include"] = - filename:split("msdev\\include"), - ?line ["a:/","msdev","include"] = - filename:split("a:\\msdev\\include"), - ?line ["a:","msdev","include"] = - filename:split("a:msdev\\include"), - ok; - _ -> + {win32,_} -> + ["a:/","msdev","include"] = + filename:split("a:/msdev/include"), + ["a:/","msdev","include"] = + filename:split("A:/msdev/include"), + ["msdev","include"] = + filename:split("msdev\\include"), + ["a:/","msdev","include"] = + filename:split("a:\\msdev\\include"), + ["a:","msdev","include"] = + filename:split("a:msdev\\include"), + ok; + _ -> ok end. t_nativename(Config) when is_list(Config) -> - ?line "abcedf" = filename:nativename(abcedf), - ?line "abcedf" = filename:nativename(["abc", "edf"]), - ?line "abcgluff" = filename:nativename(["abc", gluff]), + "abcedf" = filename:nativename(abcedf), + "abcedf" = filename:nativename(["abc", "edf"]), + "abcgluff" = filename:nativename(["abc", gluff]), case os:type() of - {win32, _} -> - ?line "a:\\temp\\arne.exe" = - filename:nativename("A:/temp//arne.exe/"); - _ -> - ?line "/usr/tmp/arne" = - filename:nativename("/usr/tmp//arne/") + {win32, _} -> + "a:\\temp\\arne.exe" = + filename:nativename("A:/temp//arne.exe/"); + _ -> + "/usr/tmp/arne" = + filename:nativename("/usr/tmp//arne/") end. find_src(Config) when is_list(Config) -> - ?line {Source,_} = filename:find_src(file), - ?line ["file"|_] = lists:reverse(filename:split(Source)), - ?line {_,_} = filename:find_src(init, [{".","."}, {"ebin","src"}]), + {Source,_} = filename:find_src(file), + ["file"|_] = lists:reverse(filename:split(Source)), + {_,_} = filename:find_src(init, [{".","."}, {"ebin","src"}]), %% Try to find the source for a preloaded module. - ?line {error,{preloaded,init}} = filename:find_src(init), + {error,{preloaded,init}} = filename:find_src(init), %% Make sure that find_src works for a slim BEAM file. OldPath = code:get_path(), try - PrivDir = ?config(priv_dir, Config), - code:add_patha(PrivDir), - Src = "simple", - SrcPath = filename:join(PrivDir, Src) ++ ".erl", - SrcContents = "-module(simple).\n", - ok = file:write_file(SrcPath, SrcContents), - {ok,simple} = compile:file(SrcPath, [slim,{outdir,PrivDir}]), - BeamPath = filename:join(PrivDir, Src), - {BeamPath,[]} = filename:find_src(simple) + PrivDir = ?config(priv_dir, Config), + code:add_patha(PrivDir), + Src = "simple", + SrcPath = filename:join(PrivDir, Src) ++ ".erl", + SrcContents = "-module(simple).\n", + ok = file:write_file(SrcPath, SrcContents), + {ok,simple} = compile:file(SrcPath, [slim,{outdir,PrivDir}]), + BeamPath = filename:join(PrivDir, Src), + {BeamPath,[]} = filename:find_src(simple) after - code:set_path(OldPath) + code:set_path(OldPath) end, ok. @@ -452,50 +453,51 @@ find_src(Config) when is_list(Config) -> absname_bin(Config) when is_list(Config) -> case os:type() of - {win32, _} -> - ?line [Drive|_] = ?config(priv_dir, Config), - ?line Temp = filename:join([Drive|":/"], "temp"), - ?line case file:make_dir(Temp) of - ok -> ok; - {error,eexist} -> ok - end, - ?line {ok,Cwd} = file:get_cwd(), - ?line ok = file:set_cwd(Temp), - ?line <<Drive:8,":/temp/foo">> = filename:absname(<<"foo">>), - ?line <<Drive:8,":/temp/../ebin">> = filename:absname(<<"../ebin">>), - ?line <<Drive:8,":/erlang">> = filename:absname(<<"/erlang">>), - ?line <<Drive:8,":/erlang/src">> = filename:absname(<<"/erlang/src">>), - ?line <<Drive:8,":/erlang/src">> = filename:absname(<<"\\erlang\\src">>), - ?line <<Drive:8,":/temp/erlang">> = filename:absname(<<Drive:8,":erlang">>), - ?line <<Drive:8,":/temp/erlang/src">> = - filename:absname(<<Drive:8,":erlang/src">>), - ?line <<Drive:8,":/temp/erlang/src">> = - filename:absname(<<Drive:8,":erlang\\src\\">>), - ?line <<"a:/erlang">> = filename:absname(<<"a:erlang">>), - - ?line file:set_cwd(<<Drive:8,":/">>), - ?line <<Drive:8,":/foo">> = filename:absname(<<"foo">>), - ?line <<Drive:8,":/../ebin">> = filename:absname(<<"../ebin">>), - ?line <<Drive:8,":/erlang">> = filename:absname(<<"/erlang">>), - ?line <<Drive:8,":/erlang/src">> = filename:absname(<<"/erlang/src">>), - ?line <<Drive:8,":/erlang/src">> = filename:absname(<<"\\erlang\\\\src">>), - ?line <<Drive:8,":/erlang">> = filename:absname(<<Drive:8,":erlang">>), - ?line <<Drive:8,":/erlang/src">> = filename:absname(<<Drive:8,":erlang/src">>), - ?line <<"a:/erlang">> = filename:absname(<<"a:erlang">>), - - ?line file:set_cwd(Cwd), - ok; - {unix, _} -> - ?line ok = file:set_cwd(<<"/usr">>), - ?line <<"/usr/foo">> = filename:absname(<<"foo">>), - ?line <<"/usr/../ebin">> = filename:absname(<<"../ebin">>), - ?line file:set_cwd(<<"/">>), - ?line <<"/foo">> = filename:absname(<<"foo">>), - ?line <<"/../ebin">> = filename:absname(<<"../ebin">>), - ?line <<"/erlang">> = filename:absname(<<"/erlang">>), - ?line <<"/erlang/src">> = filename:absname(<<"/erlang/src">>), - ?line <<"/erlang/src">> = filename:absname(<<"/erlang///src">>), - ok + {win32, _} -> + [Drive|_] = ?config(priv_dir, Config), + Temp = filename:join([Drive|":/"], "temp"), + case file:make_dir(Temp) of + ok -> ok; + {error,eexist} -> ok + end, + {ok,Cwd} = file:get_cwd(), + ok = file:set_cwd(Temp), + <<Drive:8,":/temp/foo">> = filename:absname(<<"foo">>), + <<Drive:8,":/temp/../ebin">> = filename:absname(<<"../ebin">>), + <<Drive:8,":/erlang">> = filename:absname(<<"/erlang">>), + <<Drive:8,":/erlang/src">> = filename:absname(<<"/erlang/src">>), + <<Drive:8,":/erlang/src">> = filename:absname(<<"\\erlang\\src">>), + <<Drive:8,":/temp/erlang">> = filename:absname(<<Drive:8,":erlang">>), + <<Drive:8,":/temp/erlang/src">> = + filename:absname(<<Drive:8,":erlang/src">>), + <<Drive:8,":/temp/erlang/src">> = + filename:absname(<<Drive:8,":erlang\\src\\">>), + <<"a:/erlang">> = filename:absname(<<"a:erlang">>), + + file:set_cwd(<<Drive:8,":/">>), + <<Drive:8,":/foo">> = filename:absname(<<"foo">>), + <<Drive:8,":/../ebin">> = filename:absname(<<"../ebin">>), + <<Drive:8,":/erlang">> = filename:absname(<<"/erlang">>), + <<Drive:8,":/erlang/src">> = filename:absname(<<"/erlang/src">>), + <<Drive:8,":/erlang/src">> = filename:absname(<<"\\erlang\\\\src">>), + <<Drive:8,":/erlang">> = filename:absname(<<Drive:8,":erlang">>), + <<Drive:8,":/erlang/src">> = filename:absname(<<Drive:8,":erlang/src">>), + <<"a:/erlang">> = filename:absname(<<"a:erlang">>), + + file:set_cwd(Cwd), + ok; + {unix,_} -> + ok = file:set_cwd(<<"/usr">>), + <<"/usr/foo">> = filename:absname(<<"foo">>), + <<"/usr/../ebin">> = filename:absname(<<"../ebin">>), + + file:set_cwd(<<"/">>), + <<"/foo">> = filename:absname(<<"foo">>), + <<"/../ebin">> = filename:absname(<<"../ebin">>), + <<"/erlang">> = filename:absname(<<"/erlang">>), + <<"/erlang/src">> = filename:absname(<<"/erlang/src">>), + <<"/erlang/src">> = filename:absname(<<"/erlang///src">>), + ok end. @@ -503,108 +505,104 @@ absname_bin(Config) when is_list(Config) -> absname_bin_2(Config) when is_list(Config) -> case os:type() of - {win32, _} -> - ?line [Drive|_] = ?config(priv_dir, Config), - ?line <<Drive:8,":/temp/foo">> = filename:absname(<<"foo">>, <<Drive:8,":/temp">>), - ?line <<Drive:8,":/temp/../ebin">> = filename:absname(<<"../ebin">>, - <<Drive:8,":/temp">>), - ?line <<Drive:8,":/erlang">> = filename:absname(<<"/erlang">>, <<Drive:8,":/temp">>), - ?line <<Drive:8,":/erlang/src">> = filename:absname(<<"/erlang/src">>, - <<Drive:8,":/temp">>), - ?line <<Drive:8,":/erlang/src">> = filename:absname(<<"\\erlang\\src">>, - <<Drive:8,":/temp">>), - ?line <<Drive:8,":/temp/erlang">> = filename:absname(<<Drive:8,":erlang">>, - <<Drive:8,":/temp">>), - ?line <<Drive:8,":/temp/erlang/src">> = filename:absname(<<Drive:8,":erlang/src">>, - <<Drive:8,":/temp">>), - ?line <<Drive:8,":/temp/erlang/src">> = - filename:absname(<<Drive:8,":erlang\\src\\">>, <<Drive:8,":/temp">>), - ?line <<"a:/erlang">> = filename:absname(<<"a:erlang">>, <<Drive:8,":/temp">>), - - ?line file:set_cwd(<<Drive:8,":/">>), - ?line <<Drive:8,":/foo">> = filename:absname(foo, <<Drive:8,":/">>), - ?line <<Drive:8,":/foo">> = filename:absname(<<"foo">>, <<Drive:8,":/">>), - ?line <<Drive:8,":/../ebin">> = filename:absname(<<"../ebin">>, <<Drive:8,":/">>), - ?line <<Drive:8,":/erlang">> = filename:absname(<<"/erlang">>, <<Drive:8,":/">>), - ?line <<Drive:8,":/erlang/src">> = filename:absname(<<"/erlang/src">>, - <<Drive:8,":/">>), - ?line <<Drive:8,":/erlang/src">> = filename:absname(<<"\\erlang\\\\src">>, - <<Drive:8,":/">>), - ?line <<Drive:8,":/erlang">> = filename:absname(<<Drive:8,":erlang">>, - <<Drive:8,":/">>), - ?line <<Drive:8,":/erlang/src">> = filename:absname(<<Drive:8,":erlang/src">>, - <<Drive:8,":/">>), - ?line <<"a:/erlang">> = filename:absname(<<"a:erlang">>, <<Drive:8,":/">>), - - ok; - _ -> - ?line <<"/usr/foo">> = filename:absname(<<"foo">>, <<"/usr">>), - ?line <<"/usr/../ebin">> = filename:absname(<<"../ebin">>, <<"/usr">>), - - ?line <<"/foo">> = filename:absname(<<"foo">>, <<"/">>), - ?line <<"/../ebin">> = filename:absname(<<"../ebin">>, <<"/">>), - ?line <<"/erlang">> = filename:absname(<<"/erlang">>, <<"/">>), - ?line <<"/erlang/src">> = filename:absname(<<"/erlang/src">>, <<"/">>), - ?line <<"/erlang/src">> = filename:absname(<<"/erlang///src">>, <<"/">>), - ok + {win32, _} -> + [Drive|_] = ?config(priv_dir, Config), + <<Drive:8,":/temp/foo">> = filename:absname(<<"foo">>, <<Drive:8,":/temp">>), + <<Drive:8,":/temp/../ebin">> = filename:absname(<<"../ebin">>, + <<Drive:8,":/temp">>), + <<Drive:8,":/erlang">> = filename:absname(<<"/erlang">>, <<Drive:8,":/temp">>), + <<Drive:8,":/erlang/src">> = filename:absname(<<"/erlang/src">>, + <<Drive:8,":/temp">>), + <<Drive:8,":/erlang/src">> = filename:absname(<<"\\erlang\\src">>, + <<Drive:8,":/temp">>), + <<Drive:8,":/temp/erlang">> = filename:absname(<<Drive:8,":erlang">>, + <<Drive:8,":/temp">>), + <<Drive:8,":/temp/erlang/src">> = filename:absname(<<Drive:8,":erlang/src">>, + <<Drive:8,":/temp">>), + <<Drive:8,":/temp/erlang/src">> = + filename:absname(<<Drive:8,":erlang\\src\\">>, <<Drive:8,":/temp">>), + <<"a:/erlang">> = filename:absname(<<"a:erlang">>, <<Drive:8,":/temp">>), + + file:set_cwd(<<Drive:8,":/">>), + <<Drive:8,":/foo">> = filename:absname(foo, <<Drive:8,":/">>), + <<Drive:8,":/foo">> = filename:absname(<<"foo">>, <<Drive:8,":/">>), + <<Drive:8,":/../ebin">> = filename:absname(<<"../ebin">>, <<Drive:8,":/">>), + <<Drive:8,":/erlang">> = filename:absname(<<"/erlang">>, <<Drive:8,":/">>), + <<Drive:8,":/erlang/src">> = filename:absname(<<"/erlang/src">>, + <<Drive:8,":/">>), + <<Drive:8,":/erlang/src">> = filename:absname(<<"\\erlang\\\\src">>, + <<Drive:8,":/">>), + <<Drive:8,":/erlang">> = filename:absname(<<Drive:8,":erlang">>, + <<Drive:8,":/">>), + <<Drive:8,":/erlang/src">> = filename:absname(<<Drive:8,":erlang/src">>, + <<Drive:8,":/">>), + <<"a:/erlang">> = filename:absname(<<"a:erlang">>, <<Drive:8,":/">>), + + ok; + _ -> + <<"/usr/foo">> = filename:absname(<<"foo">>, <<"/usr">>), + <<"/usr/../ebin">> = filename:absname(<<"../ebin">>, <<"/usr">>), + <<"/foo">> = filename:absname(<<"foo">>, <<"/">>), + <<"/../ebin">> = filename:absname(<<"../ebin">>, <<"/">>), + <<"/erlang">> = filename:absname(<<"/erlang">>, <<"/">>), + <<"/erlang/src">> = filename:absname(<<"/erlang/src">>, <<"/">>), + <<"/erlang/src">> = filename:absname(<<"/erlang///src">>, <<"/">>), + ok end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% basename_bin_1(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(10)), - ?line <<".">> = filename:basename(<<".">>), - ?line <<"foo">> = filename:basename(<<"foo">>), - ?line <<"foo">> = filename:basename(<<"/usr/foo">>), - ?line <<"foo.erl">> = filename:basename(<<"A:usr/foo.erl">>), - ?line case os:type() of - {win32, _} -> - ?line <<"foo">> = filename:basename(<<"A:\\usr\\foo">>), - ?line <<"foo">> = filename:basename(<<"A:foo">>); - _ -> - ?line <<"strange\\but\\true">> = - filename:basename(<<"strange\\but\\true">>) - end, - ?line test_server:timetrap_cancel(Dog), + Dog = test_server:timetrap(test_server:seconds(10)), + <<".">> = filename:basename(<<".">>), + <<"foo">> = filename:basename(<<"foo">>), + <<"foo">> = filename:basename(<<"/usr/foo">>), + <<"foo.erl">> = filename:basename(<<"A:usr/foo.erl">>), + case os:type() of + {win32, _} -> + <<"foo">> = filename:basename(<<"A:\\usr\\foo">>), + <<"foo">> = filename:basename(<<"A:foo">>); + _ -> + <<"strange\\but\\true">> = filename:basename(<<"strange\\but\\true">>) + end, + test_server:timetrap_cancel(Dog), ok. basename_bin_2(Config) when is_list(Config) -> - ?line Dog = test_server:timetrap(test_server:seconds(10)), - ?line <<".">> = filename:basename(<<".">>, <<".erl">>), - ?line <<"foo">> = filename:basename(<<"foo.erl">>, <<".erl">>), - ?line <<"foo.erl">> = filename:basename(<<"/usr/foo.erl">>, <<".hrl">>), - ?line <<"foo.erl">> = filename:basename(<<"/usr.hrl/foo.erl">>, <<".hrl">>), - ?line <<"foo">> = filename:basename(<<"/usr.hrl/foo">>, <<".hrl">>), - ?line <<"foo">> = filename:basename(<<"usr/foo/">>, <<".erl">>), - ?line <<"foo.erl">> = filename:basename(<<"usr/foo.erl/">>, <<".erl">>), - ?line case os:type() of - {win32, _} -> - ?line <<"foo">> = filename:basename(<<"A:foo">>, <<".erl">>), - ?line <<"foo.erl">> = filename:basename(<<"a:\\usr\\foo.erl">>, - <<".hrl">>), - ?line <<"foo.erl">> = filename:basename(<<"c:\\usr.hrl\\foo.erl">>, - <<".hrl">>), - ?line <<"foo">> = filename:basename(<<"A:\\usr\\foo">>, <<".hrl">>); - _ -> - ?line <<"strange\\but\\true">> = - filename:basename(<<"strange\\but\\true.erl">>, <<".erl">>), - ?line <<"strange\\but\\true">> = - filename:basename(<<"strange\\but\\true">>, <<".erl">>) - end, - ?line test_server:timetrap_cancel(Dog), + Dog = test_server:timetrap(test_server:seconds(10)), + <<".">> = filename:basename(<<".">>, <<".erl">>), + <<"foo">> = filename:basename(<<"foo.erl">>, <<".erl">>), + <<"foo.erl">> = filename:basename(<<"/usr/foo.erl">>, <<".hrl">>), + <<"foo.erl">> = filename:basename(<<"/usr.hrl/foo.erl">>, <<".hrl">>), + <<"foo">> = filename:basename(<<"/usr.hrl/foo">>, <<".hrl">>), + <<"foo">> = filename:basename(<<"usr/foo/">>, <<".erl">>), + <<"foo.erl">> = filename:basename(<<"usr/foo.erl/">>, <<".erl">>), + case os:type() of + {win32, _} -> + <<"foo">> = filename:basename(<<"A:foo">>, <<".erl">>), + <<"foo.erl">> = filename:basename(<<"a:\\usr\\foo.erl">>, <<".hrl">>), + <<"foo.erl">> = filename:basename(<<"c:\\usr.hrl\\foo.erl">>, <<".hrl">>), + <<"foo">> = filename:basename(<<"A:\\usr\\foo">>, <<".hrl">>); + _ -> + <<"strange\\but\\true">> = + filename:basename(<<"strange\\but\\true.erl">>, <<".erl">>), + <<"strange\\but\\true">> = + filename:basename(<<"strange\\but\\true">>, <<".erl">>) + end, + test_server:timetrap_cancel(Dog), ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% dirname_bin(Config) when is_list(Config) -> case os:type() of - {win32,_} -> - <<"A:/usr">> = filename:dirname(<<"A:/usr/foo.erl">>), - <<"A:usr">> = filename:dirname(<<"A:usr/foo.erl">>), - <<"/usr">> = filename:dirname(<<"\\usr\\foo.erl">>), - <<"/">> = filename:dirname(<<"\\usr">>), - <<"A:">> = filename:dirname(<<"A:">>); - _ -> true + {win32,_} -> + <<"A:/usr">> = filename:dirname(<<"A:/usr/foo.erl">>), + <<"A:usr">> = filename:dirname(<<"A:usr/foo.erl">>), + <<"/usr">> = filename:dirname(<<"\\usr\\foo.erl">>), + <<"/">> = filename:dirname(<<"\\usr">>), + <<"A:">> = filename:dirname(<<"A:">>); + _ -> true end, <<"usr">> = filename:dirname(<<"usr///foo.erl">>), <<".">> = filename:dirname(<<"foo.erl">>), @@ -612,7 +610,6 @@ dirname_bin(Config) when is_list(Config) -> <<"/">> = filename:dirname(<<"/">>), <<"/">> = filename:dirname(<<"/usr">>), ok. - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -624,10 +621,9 @@ extension_bin(Config) when is_list(Config) -> <<"">> = filename:extension(<<"A:/usr/foo">>), case os:type() of {win32, _} -> - ?line <<"">> = filename:extension(<<"A:\\usr\\foo">>), - ?line <<".erl">> = - filename:extension(<<"A:/usr.bar/foo.nisse.erl">>), - ?line <<"">> = filename:extension(<<"A:/usr.bar/foo">>), + <<"">> = filename:extension(<<"A:\\usr\\foo">>), + <<".erl">> = filename:extension(<<"A:/usr.bar/foo.nisse.erl">>), + <<"">> = filename:extension(<<"A:/usr.bar/foo">>), ok; _ -> ok end. @@ -635,22 +631,22 @@ extension_bin(Config) when is_list(Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% join_bin(Config) when is_list(Config) -> - ?line <<"/">> = filename:join([<<"/">>]), - ?line <<"/">> = filename:join([<<"//">>]), - ?line <<"usr/foo.erl">> = filename:join(<<"usr">>,<<"foo.erl">>), - ?line <<"/src/foo.erl">> = filename:join(usr, <<"/src/foo.erl">>), - ?line <<"/src/foo.erl">> = filename:join([<<"/src/">>,'foo.erl']), - ?line <<"/src/foo.erl">> = filename:join(<<"usr">>, ["/sr", 'c/foo.erl']), - ?line <<"/src/foo.erl">> = filename:join(<<"usr">>, <<"/src/foo.erl">>), + <<"/">> = filename:join([<<"/">>]), + <<"/">> = filename:join([<<"//">>]), + <<"usr/foo.erl">> = filename:join(<<"usr">>,<<"foo.erl">>), + <<"/src/foo.erl">> = filename:join(usr, <<"/src/foo.erl">>), + <<"/src/foo.erl">> = filename:join([<<"/src/">>,'foo.erl']), + <<"/src/foo.erl">> = filename:join(<<"usr">>, ["/sr", 'c/foo.erl']), + <<"/src/foo.erl">> = filename:join(<<"usr">>, <<"/src/foo.erl">>), %% Make sure that redundant slashes work too. - ?line <<"a/b/c/d/e/f/g">> = filename:join([<<"a//b/c/////d//e/f/g">>]), - ?line <<"a/b/c/d/e/f/g">> = filename:join([<<"a//b/c/">>, <<"d//e/f/g">>]), - ?line <<"a/b/c/d/e/f/g">> = filename:join([<<"a//b/c">>, <<"d//e/f/g">>]), - ?line <<"/d/e/f/g">> = filename:join([<<"a//b/c">>, <<"/d//e/f/g">>]), - ?line <<"/d/e/f/g">> = filename:join([<<"a//b/c">>, <<"//d//e/f/g">>]), + <<"a/b/c/d/e/f/g">> = filename:join([<<"a//b/c/////d//e/f/g">>]), + <<"a/b/c/d/e/f/g">> = filename:join([<<"a//b/c/">>, <<"d//e/f/g">>]), + <<"a/b/c/d/e/f/g">> = filename:join([<<"a//b/c">>, <<"d//e/f/g">>]), + <<"/d/e/f/g">> = filename:join([<<"a//b/c">>, <<"/d//e/f/g">>]), + <<"/d/e/f/g">> = filename:join([<<"a//b/c">>, <<"//d//e/f/g">>]), - ?line <<"foo/bar">> = filename:join([$f,$o,$o,$/,[]], <<"bar">>), + <<"foo/bar">> = filename:join([$f,$o,$o,$/,[]], <<"bar">>), %% Single dots - should be removed if in the middle of the path, %% but not at the end of the path. @@ -699,30 +695,25 @@ join_bin(Config) when is_list(Config) -> <<"/a/b">> = filename:join([<<"/a/">>,<<"b/">>]), <<"/a/b">> = filename:join(<<"/a/">>,<<"b/">>), - ?line case os:type() of - {win32, _} -> - ?line <<"d:/">> = filename:join([<<"D:/">>]), - ?line <<"d:/">> = filename:join([<<"D:\\">>]), - ?line <<"d:/abc">> = filename:join([<<"D:/">>, <<"abc">>]), - ?line <<"d:abc">> = filename:join([<<"D:">>, <<"abc">>]), - ?line <<"a/b/c/d/e/f/g">> = - filename:join([<<"a//b\\c//\\/\\d/\\e/f\\g">>]), - ?line <<"a:usr/foo.erl">> = - filename:join([<<"A:">>,<<"usr">>,<<"foo.erl">>]), - ?line <<"/usr/foo.erl">> = - filename:join([<<"A:">>,<<"/usr">>,<<"foo.erl">>]), - ?line <<"c:usr">> = filename:join(<<"A:">>,<<"C:usr">>), - ?line <<"a:usr">> = filename:join(<<"A:">>,<<"usr">>), - ?line <<"c:/usr">> = filename:join(<<"A:">>, <<"C:/usr">>), - ?line <<"c:/usr/foo.erl">> = - filename:join([<<"A:">>,<<"C:/usr">>,<<"foo.erl">>]), - ?line <<"c:usr/foo.erl">> = - filename:join([<<"A:">>,<<"C:usr">>,<<"foo.erl">>]), - ?line <<"d:/foo">> = filename:join([$D, $:, $/, []], <<"foo">>), - ok; - _ -> - ok - end. + case os:type() of + {win32, _} -> + <<"d:/">> = filename:join([<<"D:/">>]), + <<"d:/">> = filename:join([<<"D:\\">>]), + <<"d:/abc">> = filename:join([<<"D:/">>, <<"abc">>]), + <<"d:abc">> = filename:join([<<"D:">>, <<"abc">>]), + <<"a/b/c/d/e/f/g">> = filename:join([<<"a//b\\c//\\/\\d/\\e/f\\g">>]), + <<"a:usr/foo.erl">> = filename:join([<<"A:">>,<<"usr">>,<<"foo.erl">>]), + <<"/usr/foo.erl">> = filename:join([<<"A:">>,<<"/usr">>,<<"foo.erl">>]), + <<"c:usr">> = filename:join(<<"A:">>,<<"C:usr">>), + <<"a:usr">> = filename:join(<<"A:">>,<<"usr">>), + <<"c:/usr">> = filename:join(<<"A:">>, <<"C:/usr">>), + <<"c:/usr/foo.erl">> = filename:join([<<"A:">>,<<"C:/usr">>,<<"foo.erl">>]), + <<"c:usr/foo.erl">> = filename:join([<<"A:">>,<<"C:usr">>,<<"foo.erl">>]), + <<"d:/foo">> = filename:join([$D, $:, $/, []], <<"foo">>), + ok; + _ -> + ok + end. pathtype_bin(Config) when is_list(Config) -> relative = filename:pathtype(<<"..">>), @@ -730,14 +721,14 @@ pathtype_bin(Config) when is_list(Config) -> relative = filename:pathtype(<<"foo/bar">>), relative = filename:pathtype('foo/bar'), case os:type() of - {win32, _} -> - volumerelative = filename:pathtype(<<"/usr/local/bin">>), - volumerelative = filename:pathtype(<<"A:usr/local/bin">>), - ok; - _ -> - absolute = filename:pathtype(<<"/">>), - absolute = filename:pathtype(<<"/usr/local/bin">>), - ok + {win32, _} -> + volumerelative = filename:pathtype(<<"/usr/local/bin">>), + volumerelative = filename:pathtype(<<"A:usr/local/bin">>), + ok; + _ -> + absolute = filename:pathtype(<<"/">>), + absolute = filename:pathtype(<<"/usr/local/bin">>), + ok end. rootname_bin(Config) when is_list(Config) -> @@ -756,29 +747,204 @@ split_bin(Config) when is_list(Config) -> [<<"/">>] = filename:split(<<"/">>), [] = filename:split(<<"">>), case os:type() of - {win32,_} -> - [<<"a:/">>,<<"msdev">>,<<"include">>] = - filename:split(<<"a:/msdev/include">>), - [<<"a:/">>,<<"msdev">>,<<"include">>] = - filename:split(<<"A:/msdev/include">>), - [<<"msdev">>,<<"include">>] = - filename:split(<<"msdev\\include">>), - [<<"a:/">>,<<"msdev">>,<<"include">>] = - filename:split(<<"a:\\msdev\\include">>), - [<<"a:">>,<<"msdev">>,<<"include">>] = - filename:split(<<"a:msdev\\include">>), - ok; - _ -> - ok + {win32,_} -> + [<<"a:/">>,<<"msdev">>,<<"include">>] = + filename:split(<<"a:/msdev/include">>), + [<<"a:/">>,<<"msdev">>,<<"include">>] = + filename:split(<<"A:/msdev/include">>), + [<<"msdev">>,<<"include">>] = + filename:split(<<"msdev\\include">>), + [<<"a:/">>,<<"msdev">>,<<"include">>] = + filename:split(<<"a:\\msdev\\include">>), + [<<"a:">>,<<"msdev">>,<<"include">>] = + filename:split(<<"a:msdev\\include">>), + ok; + _ -> + ok end. t_nativename_bin(Config) when is_list(Config) -> - ?line <<"abcedf">> = filename:nativename(<<"abcedf">>), + <<"abcedf">> = filename:nativename(<<"abcedf">>), + case os:type() of + {win32, _} -> + <<"a:\\temp\\arne.exe">> = + filename:nativename(<<"A:/temp//arne.exe/">>); + _ -> + <<"/usr/tmp/arne">> = + filename:nativename(<<"/usr/tmp//arne/">>) + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% basedirs +t_basedir_api(Config) when is_list(Config) -> + true = is_list(filename:basedir(site_data, "My App")), + true = is_list(filename:basedir(site_config, "My App")), + true = is_list(filename:basedir(user_data, "My App")), + true = is_list(filename:basedir(user_log, "My App")), + true = is_list(filename:basedir(user_config, "My App")), + true = is_list(filename:basedir(user_cache, "My App")), + + true = is_list(filename:basedir(site_data, <<"My App">>)), + true = is_list(filename:basedir(site_config, <<"My App">>)), + true = is_binary(filename:basedir(user_data, <<"My App">>)), + true = is_binary(filename:basedir(user_log, <<"My App">>)), + true = is_binary(filename:basedir(user_config, <<"My App">>)), + true = is_binary(filename:basedir(user_cache, <<"My App">>)), + + %% simulate for windows + case os:type() of + {win32,_} -> ok; + _ -> + os:putenv("APPDATA", "C:\\Documents and Settings\\otptest\\Application Data") + end, + + true = is_list(filename:basedir(site_data, "My App", #{})), + true = is_list(filename:basedir(site_config, "My App", #{os=>linux})), + true = is_list(filename:basedir(user_data, "My App", #{os=>darwin})), + true = is_list(filename:basedir(user_log, "My App", #{os=>windows})), + true = is_list(filename:basedir(user_config, "My App",#{author=>"Erl"})), + true = is_list(filename:basedir(user_config, "My App",#{os=>darwin, + author=>"Erl"})), + true = is_list(filename:basedir(user_config, "My App",#{os=>linux, + author=>"Erl"})), + true = is_list(filename:basedir(user_cache, "My App",#{os=>windows, + author=>"Erl"})), + true = is_list(filename:basedir(user_config, "My App",#{os=>darwin, + author=>"Erla", + version=>"1.0"})), + true = is_list(filename:basedir(user_config, "My App",#{os=>linux, + version=>"2.0.1", + author=>"Erl"})), + true = is_list(filename:basedir(user_cache, "My App",#{os=>windows, + version=>"3.1.2", + author=>"Erl"})), + true = is_binary(filename:basedir(user_config, "My App",#{os=>darwin, + author=>"Erla", + version=><<"1.0">>})), + true = is_binary(filename:basedir(user_config, "My App",#{os=>windows, + version=>"2.0.1", + author=><<"Erl">>})), + true = is_binary(filename:basedir(user_cache, "My App",#{os=>linux, + version=><<"3.1.2">>, + author=>"Erl"})), + %% simulate for windows + case os:type() of + {win32,_} -> ok; + _ -> os:unsetenv("APPDATA") + end, + + {'EXIT', _} = (catch filename:basedir(wrong_config, "My App")), + {'EXIT', _} = (catch filename:basedir(user_cache, {bad,name})), + {'EXIT', _} = (catch filename:basedir(user_cache, "My App", badopts)), + {'EXIT', _} = (catch filename:basedir(user_cache, "My App", [])), + ok. + +t_basedir_windows(Config) when is_list(Config) -> + Types = [user_data,user_log,user_config,user_cache], case os:type() of - {win32, _} -> - ?line <<"a:\\temp\\arne.exe">> = - filename:nativename(<<"A:/temp//arne.exe/">>); - _ -> - ?line <<"/usr/tmp/arne">> = - filename:nativename(<<"/usr/tmp//arne/">>) + {win32,_} -> + ok = check_basedir_windows(Types, #{}); + _ -> + %% Windows 7 and beyond + os:putenv("APPDATA", "C:\\Users\\otptest\\AppData\\Roaming"), + os:putenv("LOCALAPPDATA", "C:\\Users\\otptest\\AppData\\Local"), + io:format("APPDATA ~p~n", [os:getenv("APPDATA")]), + io:format("LOCALAPPDATA ~p~n", [os:getenv("LOCALAPPDATA")]), + ok = check_basedir_windows(Types,#{os=>windows}), + %% Windows XP + os:unsetenv("LOCALAPPDATA"), + os:putenv("APPDATA", "C:\\Documents and Settings\\otptest\\Application Data"), + io:format("APPDATA ~p~n", [os:getenv("APPDATA")]), + io:format("APPLOCALDATA ~p~n", [os:getenv("APPLOCALDATA")]), + ok = check_basedir_windows(Types,#{os=>windows}), + os:unsetenv("APPDATA") + end, + ok. + +check_basedir_windows([],_) -> ok; +check_basedir_windows([Type|Types],Opt) -> + Name = "Some Application", + io:format("type: ~p~n", [Type]), + ok = check_basedir_windows_path(Type, + [Name], + filename:basedir(Type, Name, Opt)), + ok = check_basedir_windows_path(Type, + ["Erl",Name], + filename:basedir(Type, Name, Opt#{author=>"Erl"})), + ok = check_basedir_windows_path(Type, + [Name,"1.0"], + filename:basedir(Type, Name, Opt#{version=>"1.0"})), + ok = check_basedir_windows_path(Type, + ["Erl",Name,"1.0"], + filename:basedir(Type, Name, Opt#{author=>"Erl", + version=>"1.0"})), + check_basedir_windows(Types, Opt). + +check_basedir_windows_path(Type,Check0,Basedir) -> + BDR = lists:reverse(filename:split(Basedir)), + Check = lists:reverse(Check0), + io:format("~w: ~p ~p~n", [Type,Check,BDR]), + case Type of + user_log -> check_basedir_windows_path_split(["Logs"|Check],BDR); + user_cache -> check_basedir_windows_path_split(["Cache"|Check],BDR); + _ -> check_basedir_windows_path_split(Check,BDR) + end. + +check_basedir_windows_path_split([],_) -> ok; +check_basedir_windows_path_split([Same|Check],[Same|BDR]) -> + check_basedir_windows_path_split(Check,BDR). + + +t_basedir_xdg(Config) when is_list(Config) -> + check_basedir_xdg([user_data,user_log,user_config,user_cache, + site_data,site_config]), + ok. + +check_basedir_xdg([]) -> ok; +check_basedir_xdg([Type|Types]) -> + Name = "some_app", + Opt = #{os=>linux}, + Key = basedir_xdg_env(Type), + io:format("type: ~p~n", [Type]), + Home = os:getenv("HOME"), + NDir = "/some/absolute/path", + DefPath = basedir_xdg_def(Type,Home,Name), + EnvPath = case Type of + user_log -> filename:join([NDir,Name,"log"]); + site_data -> [filename:join([NDir,Name])]; + site_config -> [filename:join([NDir,Name])]; + _ -> filename:join([NDir,Name]) + end, + os:unsetenv(Key), + ok = check_basedir(Type, DefPath, filename:basedir(Type, Name, Opt)), + os:putenv(Key, NDir), + ok = check_basedir(Type, EnvPath, filename:basedir(Type, Name, Opt)), + os:unsetenv(Key), + ok = check_basedir(Type, DefPath, filename:basedir(Type, Name, Opt)), + check_basedir_xdg(Types). + +check_basedir(Type, Path, Basedir) -> + io:format("~w: ~p = ~p~n", [Type,Path,Basedir]), + Path = Basedir, + ok. + +basedir_xdg_env(Type) -> + case Type of + user_data -> "XDG_DATA_HOME"; + user_config -> "XDG_CONFIG_HOME"; + user_cache -> "XDG_CACHE_HOME"; + user_log -> "XDG_CACHE_HOME"; + site_data -> "XDG_DATA_DIRS"; + site_config -> "XDG_CONFIG_DIRS" + end. + +basedir_xdg_def(Type,Home,Name) -> + case Type of + user_data -> filename:join([Home,".local","share",Name]); + user_config -> filename:join([Home,".config",Name]); + user_cache -> filename:join([Home,".cache",Name]); + user_log -> filename:join([Home,".cache",Name,"log"]); + site_data -> [filename:join([Dir,Name]) || + Dir <- ["/usr/local/share/","/usr/share/"]]; + site_config -> [filename:join(["/etc/xdg",Name])] end. diff --git a/lib/tools/emacs/erlang.el b/lib/tools/emacs/erlang.el index 466bf139b9..2ff14dea02 100644 --- a/lib/tools/emacs/erlang.el +++ b/lib/tools/emacs/erlang.el @@ -897,6 +897,7 @@ resulting regexp is surrounded by \\_< and \\_>." "get_module_info" "get_stacktrace" "hash" + "has_prepared_code_on_load" "hibernate" "insert_element" "is_builtin" diff --git a/lib/wx/configure.in b/lib/wx/configure.in index 48fcca640c..bf27b72aa7 100644 --- a/lib/wx/configure.in +++ b/lib/wx/configure.in @@ -164,14 +164,14 @@ case $host_os in CPPFLAGS="$CPPFLAGS -D_MACOSX $PTHR_CFLAGS" ;; mingw32) - CFLAGS="$CFLAGS -DWIN32 -DWINVER=0x0500 -D_WINDOWS -D_UNICODE -DUNICODE" - CPPFLAGS="$CPPFLAGS -D_WIN32_WINNT=0x0500" + CFLAGS="$CFLAGS -DWIN32 -DWINVER=0x0600 -D_WINDOWS -D_UNICODE -DUNICODE" + CPPFLAGS="$CPPFLAGS -D_WIN32_WINNT=0x0600" AC_MSG_WARN([Reverting to 32-bit time_t]) CPPFLAGS="$CPPFLAGS -D_USE_32BIT_TIME_T" ;; win32) - CFLAGS="$CFLAGS -DWIN32 -DWINVER=0x0500 -D_WINDOWS -D_UNICODE -DUNICODE" - CPPFLAGS="$CPPFLAGS -D_WIN32_WINNT=0x0500" + CFLAGS="$CFLAGS -DWIN32 -DWINVER=0x0600 -D_WINDOWS -D_UNICODE -DUNICODE" + CPPFLAGS="$CPPFLAGS -D_WIN32_WINNT=0x0600" ;; *) CFLAGS="$CFLAGS -Wno-deprecated-declarations" |