diff options
Diffstat (limited to 'erts/emulator/test/nif_SUITE.erl')
-rw-r--r-- | erts/emulator/test/nif_SUITE.erl | 189 |
1 files changed, 177 insertions, 12 deletions
diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 9fbcde4e3a..2f28b4a0e9 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2021. All Rights Reserved. +%% Copyright Ericsson AB 2010-2022. 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. @@ -33,6 +33,7 @@ init_per_testcase/2, end_per_testcase/2, basic/1, reload_error/1, upgrade/1, heap_frag/1, t_on_load/1, + t_nifs_attrib/1, t_load_race/1, t_call_nif_early/1, load_traced_nif/1, @@ -71,6 +72,7 @@ nif_whereis/1, nif_whereis_parallel/1, nif_whereis_threaded/1, nif_whereis_proxy/1, nif_ioq/1, + match_state_arg/1, pid/1, id/1, nif_term_type/1 @@ -78,6 +80,115 @@ -export([many_args_100/100]). +-nifs([lib_version/0, + call_history/0, + hold_nif_mod_priv_data/1, + nif_mod_call_history/0, + list_seq/1, + type_test/0, + tuple_2_list/1, + is_identical/2, + compare/2, + hash_nif/3, + many_args_100/100, + clone_bin/1, + make_sub_bin/3, + string_to_bin/2, + atom_to_bin/2, + macros/1, + tuple_2_list_and_tuple/1, + iolist_2_bin/1, + get_resource_type/1, + alloc_resource/2, + make_resource/1, + get_resource/2, + release_resource/1, + release_resource_from_thread/1, + last_resource_dtor_call_nif/0, + make_new_resource/2, + check_is/11, + check_is_exception/0, + length_test/6, + make_atoms/0, + make_strings/0, + make_new_resource_binary/1, + send_list_seq/2, + send_new_blob/2, + alloc_msgenv/0, + clear_msgenv/1, + grow_blob/2, + grow_blob/3, + send_blob/2, + send3_blob/3, + send_blob_thread/3, + join_send_thread/1, + copy_blob/1, + send_term/2, + send_copy_term/2, + reverse_list/1, + echo_int/1, + type_sizes/0, + otp_9668_nif/1, + otp_9828_nif/1, + consume_timeslice_nif/2, + call_nif_schedule/2, + call_nif_exception/1, + call_nif_nan_or_inf/1, + call_nif_atom_too_long/1, + unique_integer_nif/1, + is_process_alive_nif/1, + is_port_alive_nif/1, + term_to_binary_nif/2, + binary_to_term_nif/3, + port_command_nif/2, + format_term_nif/2, + select_nif/6, + dupe_resource_nif/1, + pipe_nif/0, + write_nif/2, + read_nif/2, + close_nif/1, + is_closed_nif/1, + clear_select_nif/1, + last_fd_stop_call/0, + alloc_monitor_resource_nif/0, + monitor_process_nif/4, + demonitor_process_nif/2, + compare_monitors_nif/2, + make_monitor_term_nif/1, + monitor_frenzy_nif/4, + ioq_nif/1, + ioq_nif/2, + ioq_nif/3, + ioq_nif/4, + whereis_send/3, + whereis_term/2, + whereis_thd_lookup/3, + whereis_thd_result/1, + is_map_nif/1, + get_map_size_nif/1, + make_new_map_nif/0, + make_map_put_nif/3, + get_map_value_nif/2, + make_map_update_nif/3, + make_map_remove_nif/2, + maps_from_list_nif/1, + sorted_list_from_maps_nif/1, + monotonic_time/1, + time_offset/1, + convert_time_unit/3, + now_time/0, + cpu_time/0, + get_local_pid_nif/1, + make_pid_nif/1, + set_pid_undefined_nif/0, + is_pid_undefined_nif/1, + compare_pids_nif/2, + term_type_nif/1, + dynamic_resource_call/4, + msa_find_y_nif/1 + ]). + -define(nif_stub,nif_stub_error(?LINE)). -define(is_resource, is_reference). @@ -97,6 +208,7 @@ all() -> {group, monitor}, monitor_frenzy, t_dynamic_resource_call, + t_nifs_attrib, t_load_race, t_call_nif_early, load_traced_nif, @@ -119,6 +231,7 @@ all() -> nif_phash2, nif_whereis, nif_whereis_parallel, nif_whereis_threaded, nif_ioq, + match_state_arg, pid, nif_term_type]. @@ -505,6 +618,34 @@ t_on_load(Config) when is_list(Config) -> verify_tmpmem(TmpMem), ok. +%% Test the -nifs() attribute +t_nifs_attrib(Config) when is_list(Config) -> + TmpMem = tmpmem(), + ensure_lib_loaded(Config), + + Data = proplists:get_value(data_dir, Config), + File = filename:join(Data, "nif_mod"), + {ok,nif_mod,Bin3} = compile:file(File, [binary,return_errors, + {d,'USE_NIFS_ATTRIB',3}]), + + {module,nif_mod} = code:load_binary(nif_mod,File,Bin3), + ok = nif_mod:load_nif_lib(Config, 1), + 1 = nif_mod:lib_version(), + + {ok,nif_mod,Bin2} = compile:file(File, [binary,return_errors, + {d,'USE_NIFS_ATTRIB',2}]), + {module,nif_mod} = code:load_binary(nif_mod,File,Bin2), + {error, {bad_lib, "Function not declared as nif" ++ _}} = + nif_mod:load_nif_lib(Config, 1), + + {ok,nif_mod,Bin1} = compile:file(File, [binary,return_errors, + {d,'USE_NIFS_ATTRIB',1}]), + {module,nif_mod} = code:load_binary(nif_mod,File,Bin1), + {error, {bad_lib, "Function not declared as nif" ++ _}} = + nif_mod:load_nif_lib(Config, 1), + ok. + + %% Test erlang:load_nif/2 waiting for code_write_permission. t_load_race(Config) -> Data = proplists:get_value(data_dir, Config), @@ -1011,6 +1152,7 @@ monitor_process_c(Config) -> Pid = spawn_link(fun() -> R_ptr = alloc_monitor_resource_nif(), {0,Mon} = monitor_process_nif(R_ptr, self(), true, Papa), + receive after 1000 -> ok end, [R_ptr] = monitored_by(self()), put(store, make_resource(R_ptr)), ok = release_resource(R_ptr), @@ -1018,8 +1160,8 @@ monitor_process_c(Config) -> Papa ! {self(), done, R_ptr, Mon}, exit end), - [{Pid, done, R_ptr, Mon1}, - {monitor_resource_down, R_ptr, Pid, Mon2}] = flush(2), + receive {Pid, done, R_ptr, Mon1} -> ok end, + [{monitor_resource_down, R_ptr, Pid, Mon2}] = flush(1), compare_monitors_nif(Mon1, Mon2), {R_ptr, _, 1} = last_resource_dtor_call(), ok. @@ -1298,6 +1440,8 @@ dynamic_resource_call_do(Config, NifModBin) -> {1, 1000} = dynamic_resource_call(nif_mod, with_dyncall, R, 1000), true = erlang:purge_module(nif_mod), [{unload,2,2,202}] = nif_mod_call_history(), + + keep_alive(R), ok. @@ -2505,8 +2649,10 @@ neg(Config) when is_list(Config) -> {ok,nif_mod,Bin} = compile:file(File, [binary,return_errors]), {module,nif_mod} = erlang:load_module(nif_mod,Bin), - {error,{load_failed,_}} = nif_mod:load_nif_lib(Config, 0), - {error,{bad_lib,_}} = nif_mod:load_nif_lib(Config, no_init), + {error,{load_failed,"Failed to load NIF library"++_}} = nif_mod:load_nif_lib(Config, 0), + {error,{bad_lib,"Failed to find library init"++_}} = nif_mod:load_nif_lib(Config, 3), + {error,{bad_lib,"Function not found"++_}} = nif_mod:load_nif_lib(Config, 4), + {error,{bad_lib,"Duplicate NIF entry for"++_}} = nif_mod:load_nif_lib(Config, 5), verify_tmpmem(TmpMem), ok. @@ -3339,12 +3485,7 @@ random_sign() -> end. random_binary() -> - list_to_binary(random_bytes(rand:uniform(32) - 1)). - -random_bytes(0) -> - []; -random_bytes(N) when N > 0 -> - [rand:uniform(256) - 1 | random_bytes(N - 1)]. + rand:bytes(rand:uniform(32) - 1). random_pid() -> Processes = erlang:processes(), @@ -3397,7 +3538,7 @@ nif_whereis(Config) when is_list(Config) -> nif_whereis_parallel(Config) when is_list(Config) -> ensure_lib_loaded(Config), - %% try to be at least a little asymetric + %% try to be at least a little asymmetric NProcs = trunc(3.7 * erlang:system_info(schedulers)), NSeq = lists:seq(1, NProcs), Names = [list_to_atom("nif_whereis_proc_" ++ integer_to_list(N)) @@ -3798,6 +3939,30 @@ nif_term_type(Config) -> ok. +%% Verify match state arguments are not passed to declared NIFs. +match_state_arg(Config) -> + ensure_lib_loaded(Config), + Bin = term_to_binary([<<"x">> | Config]), % a non-literal binary with an $x byte + <<"nif says ok">> = msa_find_x_y(Bin), + ok. + +%% Without declaring msa_find_y_nif/1 as NIF, the compiler would do +%% optimization and pass it a match state as argument. +msa_find_x_y(<<$x, Rest/binary>>) -> + msa_find_y_nif(Rest); +msa_find_x_y(<<_, Rest/binary>>) -> + msa_find_x_y(Rest); +msa_find_x_y(<<>>) -> + "no x". + +msa_find_y_nif(<<$y, Rest/binary>>) -> + Rest; +msa_find_y_nif(<<_, Rest/binary>>) -> + msa_find_y_nif(Rest); +msa_find_y_nif(<<>>) -> + "no y". + + last_resource_dtor_call() -> erts_debug:set_internal_state(wait, aux_work), last_resource_dtor_call_nif(). |