diff options
Diffstat (limited to 'erts/emulator/test/nif_SUITE.erl')
-rw-r--r-- | erts/emulator/test/nif_SUITE.erl | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl new file mode 100644 index 0000000000..213ff6637a --- /dev/null +++ b/erts/emulator/test/nif_SUITE.erl @@ -0,0 +1,235 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(nif_SUITE). + +%%-define(line_trace,true). + +-include("test_server.hrl"). + +-export([all/1, fin_per_testcase/2, basic/1, reload/1, upgrade/1, heap_frag/1, + neg/1]). + +-define(nif_stub,nif_stub_error(?LINE)). + +all(suite) -> + [basic, reload, upgrade, heap_frag, neg]. + +fin_per_testcase(_Func, _Config) -> + P1 = code:purge(nif_mod), + Del = code:delete(nif_mod), + P2 = code:purge(nif_mod), + io:format("fin purged=~p, deleted=~p and then purged=~p\n",[P1,Del,P2]). + +basic(doc) -> ["Basic smoke test of load_nif and a simple NIF call"]; +basic(suite) -> []; +basic(Config) when is_list(Config) -> + ensure_lib_loaded(Config), + ?line true = (lib_version() =/= undefined), + ?line [{load,1,1,101},{lib_version,1,2,102}] = call_history(), + ?line [] = call_history(), + ?line [?MODULE] = erlang:system_info(taints), + ok. + +reload(doc) -> ["Test reload callback in nif lib"]; +reload(suite) -> []; +reload(Config) when is_list(Config) -> + ensure_lib_loaded(Config), + + ?line Data = ?config(data_dir, Config), + ?line File = filename:join(Data, "nif_mod"), + ?line {ok,nif_mod,Bin} = compile:file(File, [binary,return_errors]), + ?line {module,nif_mod} = erlang:load_module(nif_mod,Bin), + + ?line nif_mod:load_nif_lib(Config, 1), + + ?line hold_nif_mod_priv_data(nif_mod:get_priv_data_ptr()), + ?line [{load,1,1,101},{get_priv_data_ptr,1,2,102}] = nif_mod_call_history(), + + ?line nif_mod:load_nif_lib(Config, 2), + ?line 2 = nif_mod:lib_version(), + ?line [{reload,2,1,201},{lib_version,2,2,202}] = nif_mod_call_history(), + + ?line nif_mod:load_nif_lib(Config, 1), + ?line 1 = nif_mod:lib_version(), + ?line [{reload,1,1,101},{lib_version,1,2,102}] = nif_mod_call_history(), + + ?line true = erlang:delete_module(nif_mod), + ?line [] = nif_mod_call_history(), + + %%?line false= check_process_code(Pid, nif_mod), + ?line true = erlang:purge_module(nif_mod), + ?line [{unload,1,3,103}] = nif_mod_call_history(), + + ?line [?MODULE, nif_mod] = erlang:system_info(taints), + ok. + +upgrade(doc) -> ["Test upgrade callback in nif lib"]; +upgrade(suite) -> []; +upgrade(Config) when is_list(Config) -> + ensure_lib_loaded(Config), + + ?line Data = ?config(data_dir, Config), + ?line File = filename:join(Data, "nif_mod"), + ?line {ok,nif_mod,Bin} = compile:file(File, [binary,return_errors]), + ?line {module,nif_mod} = erlang:load_module(nif_mod,Bin), + + ?line nif_mod:load_nif_lib(Config, 1), + ?line {Pid,MRef} = nif_mod:start(), + ?line 1 = call(Pid,lib_version), + + ?line hold_nif_mod_priv_data(nif_mod:get_priv_data_ptr()), + ?line [{load,1,1,101},{lib_version,1,2,102},{get_priv_data_ptr,1,3,103}] = nif_mod_call_history(), + + %% Module upgrade with same lib-version + ?line {module,nif_mod} = erlang:load_module(nif_mod,Bin), + ?line undefined = nif_mod:lib_version(), + ?line 1 = call(Pid,lib_version), + ?line [{lib_version,1,4,104}] = nif_mod_call_history(), + + ?line nif_mod:load_nif_lib(Config, 1), + ?line 1 = nif_mod:lib_version(), + ?line [{upgrade,1,5,105},{lib_version,1,6,106}] = nif_mod_call_history(), + + ?line upgraded = call(Pid,upgrade), + ?line false = check_process_code(Pid, nif_mod), + ?line true = erlang:purge_module(nif_mod), + ?line [{unload,1,7,107}] = nif_mod_call_history(), + + ?line 1 = nif_mod:lib_version(), + ?line [{lib_version,1,8,108}] = nif_mod_call_history(), + + ?line true = erlang:delete_module(nif_mod), + ?line [] = nif_mod_call_history(), + + ?line Pid ! die, + ?line {'DOWN', MRef, process, Pid, normal} = receive_any(), + ?line false = check_process_code(Pid, nif_mod), + ?line true = erlang:purge_module(nif_mod), + ?line [{unload,1,9,109}] = nif_mod_call_history(), + + %% Module upgrade with different lib version + ?line {module,nif_mod} = erlang:load_module(nif_mod,Bin), + ?line undefined = nif_mod:lib_version(), + ?line {Pid2,MRef2} = nif_mod:start(), + ?line undefined = call(Pid2,lib_version), + + ?line nif_mod:load_nif_lib(Config, 1), + ?line hold_nif_mod_priv_data(nif_mod:get_priv_data_ptr()), + ?line 1 = call(Pid2,lib_version), + ?line [{load,1,1,101},{get_priv_data_ptr,1,2,102},{lib_version,1,3,103}] = nif_mod_call_history(), + + ?line {module,nif_mod} = erlang:load_module(nif_mod,Bin), + ?line undefined = nif_mod:lib_version(), + ?line [] = nif_mod_call_history(), + ?line 1 = call(Pid2,lib_version), + ?line [{lib_version,1,4,104}] = nif_mod_call_history(), + + ?line nif_mod:load_nif_lib(Config, 2), + ?line 2 = nif_mod:lib_version(), + ?line [{upgrade,2,1,201},{lib_version,2,2,202}] = nif_mod_call_history(), + + ?line 1 = call(Pid2,lib_version), + ?line [{lib_version,1,5,105}] = nif_mod_call_history(), + + ?line upgraded = call(Pid2,upgrade), + ?line false = check_process_code(Pid2, nif_mod), + ?line true = erlang:purge_module(nif_mod), + ?line [{unload,1,6,106}] = nif_mod_call_history(), + + ?line 2 = nif_mod:lib_version(), + ?line [{lib_version,2,3,203}] = nif_mod_call_history(), + + ?line true = erlang:delete_module(nif_mod), + ?line [] = nif_mod_call_history(), + + ?line Pid2 ! die, + ?line {'DOWN', MRef2, process, Pid2, normal} = receive_any(), + ?line false= check_process_code(Pid2, nif_mod), + ?line true = erlang:purge_module(nif_mod), + ?line [{unload,2,4,204}] = nif_mod_call_history(), + + ?line [?MODULE, nif_mod] = erlang:system_info(taints), + ok. + +heap_frag(doc) -> ["Test NIF building heap fragments"]; +heap_frag(suite) -> []; +heap_frag(Config) when is_list(Config) -> + ensure_lib_loaded(Config), + + heap_frag_do(1,1000000), + ok. + +heap_frag_do(N, Max) when N > Max -> + ok; +heap_frag_do(N, Max) -> + io:format("Create list of length ~p\n",[N]), + L = lists:seq(1,N), + L = list_seq(N), + heap_frag_do(((N*5) div 4) + 1, Max). + + +neg(doc) -> ["Negative testing of load_nif"]; +neg(suite) -> []; +neg(Config) when is_list(Config) -> + ?line {'EXIT',{badarg,_}} = (catch erlang:load_nif(badarg, 0)), + ?line {error,load_failed,_} = erlang:load_nif("pink_unicorn", 0), + + ?line Data = ?config(data_dir, Config), + ?line File = filename:join(Data, "nif_mod"), + ?line {ok,nif_mod,Bin} = compile:file(File, [binary,return_errors]), + ?line {module,nif_mod} = erlang:load_module(nif_mod,Bin), + + ?line {error,bad_lib,_} = nif_mod:load_nif_lib(Config, no_init), + ?line ok. + + + +ensure_lib_loaded(Config) -> + ensure_lib_loaded(Config, 1). + +ensure_lib_loaded(Config, Ver) -> + ?line case lib_version() of + undefined -> + ?line Path = ?config(data_dir, Config), + ?line Lib = "nif_SUITE." ++ integer_to_list(Ver), + ?line ok = erlang:load_nif(filename:join(Path,Lib), 0); + Ver when is_integer(Ver) -> + ok + end. + +call(Pid,Cmd) -> + %%io:format("~p calling ~p with ~p\n",[self(), Pid, Cmd]), + Pid ! {self(), Cmd}, + receive + {Pid,Reply} -> Reply + end. + +receive_any() -> + receive M -> M end. + +%% The NIFs: +lib_version() -> undefined. +call_history() -> ?nif_stub. +hold_nif_mod_priv_data(_Ptr) -> ?nif_stub. +nif_mod_call_history() -> ?nif_stub. +list_seq(_To) -> ?nif_stub. + +nif_stub_error(Line) -> + exit({nif_not_loaded,module,?MODULE,line,Line}). |