summaryrefslogtreecommitdiff
path: root/erts/emulator/test/nif_SUITE.erl
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/test/nif_SUITE.erl')
-rw-r--r--erts/emulator/test/nif_SUITE.erl189
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().