aboutsummaryrefslogtreecommitdiffstats
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.erl131
1 files changed, 91 insertions, 40 deletions
diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl
index 9c1694fa8a..8959be8690 100644
--- a/erts/emulator/test/nif_SUITE.erl
+++ b/erts/emulator/test/nif_SUITE.erl
@@ -21,15 +21,17 @@
-module(nif_SUITE).
%%-define(line_trace,true).
--define(CHECK(Exp,Got), check(Exp,Got,?LINE)).
+-define(CHECK(Exp,Got), Exp = check(Exp,Got,?LINE)).
%%-define(CHECK(Exp,Got), Exp = Got).
-include_lib("common_test/include/ct.hrl").
--export([all/0, suite/0,
+-export([all/0, suite/0, groups/0,
+ init_per_group/2, end_per_group/2,
init_per_testcase/2, end_per_testcase/2,
- basic/1, reload/1, upgrade/1, heap_frag/1,
+ basic/1, reload_error/1, upgrade/1, heap_frag/1,
t_on_load/1,
+ hipe/1,
types/1, many_args/1, binaries/1, get_string/1, get_atom/1,
maps/1,
api_macros/1,
@@ -52,27 +54,20 @@
-export([many_args_100/100]).
-
-%% -export([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,
-%% 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,last_resource_dtor_call/0, suite/0,
-%% make_new_resource/2,make_new_resource_binary/1,send_list_seq/2,send_new_blob/2,
-%% alloc_msgenv/0,clear_msgenv/1,grow_blob/2,send_blob/2,send_blob_thread/3,
-%% join_send_thread/1]).
-
-
-define(nif_stub,nif_stub_error(?LINE)).
suite() -> [{ct_hooks,[ts_install_cth]}].
-all() ->
- [basic, reload, upgrade, heap_frag, types, many_args,
- t_on_load,
+all() ->
+ [basic]
+ ++
+ [{group, G} || G <- api_groups()]
+ ++
+ [reload_error, heap_frag, types, many_args,
+ hipe,
binaries, get_string, get_atom, maps, api_macros, from_array,
iolist_as_binary, resource, resource_binary,
- resource_takeover, threading, send, send2, send3,
+ threading, send, send2, send3,
send_threaded, neg, is_checks, get_length, make_atom,
make_string,reverse_list_test,
otp_9828,
@@ -85,9 +80,35 @@ all() ->
nif_port_command,
nif_snprintf].
+groups() ->
+ [{G, [], api_repeaters()} || G <- api_groups()].
+
+api_groups() -> [api_latest, api_2_4, api_2_0].
+
+api_repeaters() -> [upgrade, resource_takeover, t_on_load].
+
+init_per_group(api_latest, Config) -> Config;
+init_per_group(api_2_4, Config) ->
+ [{nif_api_version, ".2_4"} | Config];
+init_per_group(api_2_0, Config) ->
+ case {os:type(),erlang:system_info({wordsize, internal})} of
+ {{win32,_}, 8} ->
+ %% ERL_NIF_TERM was declared as 32-bit 'long' until 2.3
+ {skip, "API 2.0 buggy on Windows 64-bit"};
+ _ ->
+ [{nif_api_version, ".2_0"} | Config]
+ end.
+
+end_per_group(_,_) -> ok.
+
init_per_testcase(t_on_load, Config) ->
ets:new(nif_SUITE, [named_table]),
Config;
+init_per_testcase(hipe, Config) ->
+ case erlang:system_info(hipe_architecture) of
+ undefined -> {skip, "HiPE is disabled"};
+ _ -> Config
+ end;
init_per_testcase(_Case, Config) ->
Config.
@@ -112,8 +133,8 @@ basic(Config) when is_list(Config) ->
true = lists:member(?MODULE, erlang:system_info(taints)),
ok.
-%% Test reload callback in nif lib
-reload(Config) when is_list(Config) ->
+%% Test old reload feature now always fails
+reload_error(Config) when is_list(Config) ->
TmpMem = tmpmem(),
ensure_lib_loaded(Config),
@@ -127,20 +148,20 @@ reload(Config) when is_list(Config) ->
hold_nif_mod_priv_data(nif_mod:get_priv_data_ptr()),
[{load,1,1,101},{get_priv_data_ptr,1,2,102}] = nif_mod_call_history(),
- ok = nif_mod:load_nif_lib(Config, 2),
- 2 = nif_mod:lib_version(),
- [{reload,2,1,201},{lib_version,2,2,202}] = nif_mod_call_history(),
+ {error, {reload, _}} = nif_mod:load_nif_lib(Config, 2),
+ 1 = nif_mod:lib_version(),
+ [{lib_version,1,3,103}] = nif_mod_call_history(),
- ok = nif_mod:load_nif_lib(Config, 1),
+ {error, {reload, _}} = nif_mod:load_nif_lib(Config, 1),
1 = nif_mod:lib_version(),
- [{reload,1,1,101},{lib_version,1,2,102}] = nif_mod_call_history(),
+ [{lib_version,1,4,104}] = nif_mod_call_history(),
true = erlang:delete_module(nif_mod),
[] = nif_mod_call_history(),
%%false= check_process_code(Pid, nif_mod),
true = erlang:purge_module(nif_mod),
- [{unload,1,3,103}] = nif_mod_call_history(),
+ [{unload,1,5,105}] = nif_mod_call_history(),
true = lists:member(?MODULE, erlang:system_info(taints)),
true = lists:member(nif_mod, erlang:system_info(taints)),
@@ -148,7 +169,7 @@ reload(Config) when is_list(Config) ->
ok.
%% Test upgrade callback in nif lib
-upgrade(Config) when is_list(Config) ->
+upgrade(Config) when is_list(Config) ->
TmpMem = tmpmem(),
ensure_lib_loaded(Config),
@@ -299,6 +320,8 @@ t_on_load(Config) when is_list(Config) ->
%% Use ETS to tell nif_mod:on_load what to do
ets:insert(nif_SUITE, {data_dir, Data}),
ets:insert(nif_SUITE, {lib_version, 1}),
+ API = proplists:get_value(nif_api_version, Config, ""),
+ ets:insert(nif_SUITE, {nif_api_version, API}),
{module,nif_mod} = code:load_binary(nif_mod,File,Bin),
hold_nif_mod_priv_data(nif_mod:get_priv_data_ptr()),
[{load,1,1,101},{get_priv_data_ptr,1,2,102}] = nif_mod_call_history(),
@@ -411,6 +434,17 @@ t_on_load(Config) when is_list(Config) ->
verify_tmpmem(TmpMem),
ok.
+hipe(Config) when is_list(Config) ->
+ Data = proplists:get_value(data_dir, Config),
+ Priv = proplists:get_value(priv_dir, Config),
+ Src = filename:join(Data, "hipe_compiled"),
+ {ok,hipe_compiled} = c:c(Src, [{outdir,Priv},native]),
+ true = code:is_module_native(hipe_compiled),
+ {error, {notsup,_}} = hipe_compiled:try_load_nif(),
+ true = code:delete(hipe_compiled),
+ false = code:purge(hipe_compiled),
+ ok.
+
%% Test NIF building heap fragments
heap_frag(Config) when is_list(Config) ->
@@ -714,7 +748,7 @@ resource_hugo_do(Type) ->
HugoBin = <<"Hugo Hacker">>,
HugoPtr = alloc_resource(Type, HugoBin),
Hugo = make_resource(HugoPtr),
- <<>> = Hugo,
+ true = is_reference(Hugo),
release_resource(HugoPtr),
erlang:garbage_collect(),
{HugoPtr,HugoBin} = get_resource(Type,Hugo),
@@ -748,7 +782,7 @@ resource_otto_do(Type) ->
OttoBin = <<"Otto Ordonnans">>,
OttoPtr = alloc_resource(Type, OttoBin),
Otto = make_resource(OttoPtr),
- <<>> = Otto,
+ true = is_reference(Otto),
%% forget resource term but keep referenced by NIF
{OttoPtr, OttoBin}.
@@ -771,8 +805,9 @@ resource_new_do2(Type) ->
BinB = <<"NewB">>,
ResA = make_new_resource(Type, BinA),
ResB = make_new_resource(Type, BinB),
- <<>> = ResA,
- <<>> = ResB,
+ true = is_reference(ResA),
+ true = is_reference(ResB),
+ ResA /= ResB,
{PtrA,BinA} = get_resource(Type, ResA),
{PtrB,BinB} = get_resource(Type, ResB),
true = (PtrA =/= PtrB),
@@ -828,7 +863,7 @@ resource_binary_do() ->
-define(RT_CREATE,1).
-define(RT_TAKEOVER,2).
-%% Test resource takeover by module reload and upgrade
+%% Test resource takeover by module upgrade
resource_takeover(Config) when is_list(Config) ->
TmpMem = tmpmem(),
ensure_lib_loaded(Config),
@@ -893,6 +928,7 @@ resource_takeover(Config) when is_list(Config) ->
ok = forget_resource(NGX1),
?CHECK([], nif_mod_call_history()), % no dtor
+ {module,nif_mod} = erlang:load_module(nif_mod,ModBin),
ok = nif_mod:load_nif_lib(Config, 2,
[{resource_type, 0, ?RT_TAKEOVER, "resource_type_A",resource_dtor_A,
?RT_TAKEOVER},
@@ -911,7 +947,9 @@ resource_takeover(Config) when is_list(Config) ->
{resource_type, 4, ?RT_CREATE, "resource_type_null_goneY",null,
?RT_CREATE}
]),
- ?CHECK([{reload,2,1,201}], nif_mod_call_history()),
+ ?CHECK([{upgrade,2,1,201}], nif_mod_call_history()),
+ true = erlang:purge_module(nif_mod),
+ ?CHECK([], nif_mod_call_history()), % BGX2 keeping lib loaded
BinA2 = read_resource(0,A2),
ok = forget_resource(A2),
@@ -924,8 +962,8 @@ resource_takeover(Config) when is_list(Config) ->
?CHECK([], nif_mod_call_history()), % no dtor
ok = forget_resource(BGX2), % calling dtor in orphan library v1 still loaded
- ?CHECK([{{resource_dtor_B_v1,BinBGX2},1,6,106}], nif_mod_call_history()),
- % How to test that lib v1 is closed here?
+ ?CHECK([{{resource_dtor_B_v1,BinBGX2},1,6,106}, {unload,1,7,107}],
+ nif_mod_call_history()),
ok = forget_resource(NGX2),
?CHECK([], nif_mod_call_history()), % no dtor
@@ -1148,6 +1186,9 @@ resource_takeover(Config) when is_list(Config) ->
ok = forget_resource(AN7),
[] = nif_mod_call_history(),
+ true = erlang:delete_module(nif_mod),
+ true = erlang:purge_module(nif_mod),
+
true = lists:member(?MODULE, erlang:system_info(taints)),
true = lists:member(nif_mod, erlang:system_info(taints)),
verify_tmpmem(TmpMem),
@@ -1221,11 +1262,19 @@ threading_do(Config) ->
ok = tester:load_nif_lib(Config, "basic"),
ok = tester:run(),
+ erlang:load_module(tester,ModBin),
+ erlang:purge_module(tester),
ok = tester:load_nif_lib(Config, "rwlock"),
ok = tester:run(),
+ erlang:load_module(tester,ModBin),
+ erlang:purge_module(tester),
ok = tester:load_nif_lib(Config, "tsd"),
- ok = tester:run().
+ ok = tester:run(),
+
+ erlang:delete_module(tester),
+ erlang:purge_module(tester).
+
%% Test NIF message sending
send(Config) when is_list(Config) ->
@@ -1513,13 +1562,13 @@ send3_new_state(State, Blob) ->
neg(Config) when is_list(Config) ->
TmpMem = tmpmem(),
{'EXIT',{badarg,_}} = (catch erlang:load_nif(badarg, 0)),
- {error,{load_failed,_}} = erlang:load_nif("pink_unicorn", 0),
Data = proplists:get_value(data_dir, Config),
File = filename:join(Data, "nif_mod"),
{ok,nif_mod,Bin} = compile:file(File, [binary,return_errors]),
{module,nif_mod} = erlang:load_module(nif_mod,Bin),
+ {error,{load_failed,_}} = nif_mod:load_nif_lib(Config, 0),
{error,{bad_lib,_}} = nif_mod:load_nif_lib(Config, no_init),
verify_tmpmem(TmpMem),
ok.
@@ -1640,7 +1689,8 @@ consume_timeslice(Config) when is_list(Config) ->
end.
consume_timeslice_test(Config) when is_list(Config) ->
- CONTEXT_REDS = 2000,
+ ensure_lib_loaded(Config),
+ CONTEXT_REDS = 4000,
Me = self(),
Go = make_ref(),
RedDiff = make_ref(),
@@ -1716,7 +1766,7 @@ consume_timeslice_test(Config) when is_list(Config) ->
io:format("Reductions = ~p~n", [Reductions]),
ok;
{RedDiff, Reductions} ->
- ct:fail({unexpected_reduction_count, Reductions})
+ ct:fail({unexpected_reduction_count, Reductions, ExpReds})
end,
none = next_msg(P),
@@ -1870,7 +1920,8 @@ check(Exp,Got,Line) ->
case Got of
Exp -> Exp;
_ ->
- io:format("CHECK at ~p: Expected ~p but got ~p\n",[Line,Exp,Got]),
+ io:format("CHECK at line ~p\nExpected: ~p\nGot : ~p\n",
+ [Line,Exp,Got]),
Got
end.