diff options
Diffstat (limited to 'lib/kernel/test')
24 files changed, 872 insertions, 210 deletions
diff --git a/lib/kernel/test/application_SUITE.erl b/lib/kernel/test/application_SUITE.erl index 81407e9d96..866043cfb4 100644 --- a/lib/kernel/test/application_SUITE.erl +++ b/lib/kernel/test/application_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2016. All Rights Reserved. +%% Copyright Ericsson AB 1996-2017. 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. @@ -1498,7 +1498,7 @@ otp_5363(Conf) when is_list(Conf) -> %% Ticket: OTP-5606 %% Slogan: Problems with starting a distributed application %%----------------------------------------------------------------- -%% Test of several processes simultanously starting the same +%% Test of several processes simultaneously starting the same %% distributed application. otp_5606(Conf) when is_list(Conf) -> diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index 62ad7b6a27..6f8e949aac 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -38,6 +38,7 @@ on_load_purge/1, on_load_self_call/1, on_load_pending/1, on_load_deleted/1, big_boot_embedded/1, + module_status/1, native_early_modules/1, get_mode/1, normalized_paths/1]). @@ -68,6 +69,7 @@ all() -> on_load_binary, on_load_embedded, on_load_errors, on_load_update, on_load_purge, on_load_self_call, on_load_pending, on_load_deleted, + module_status, big_boot_embedded, native_early_modules, get_mode, normalized_paths]. groups() -> @@ -93,6 +95,11 @@ init_per_suite(Config) -> end_per_suite(Config) -> Config. +-define(TESTMOD, test_dummy). +-define(TESTMODSTR, "test_dummy"). +-define(TESTMODSRC, ?TESTMODSTR ".erl"). +-define(TESTMODOBJ, ?TESTMODSTR ".beam"). + init_per_testcase(big_boot_embedded, Config) -> case catch crypto:start() of ok -> @@ -100,16 +107,36 @@ init_per_testcase(big_boot_embedded, Config) -> _Else -> {skip, "Needs crypto!"} end; +init_per_testcase(on_load_embedded, Config0) -> + LibRoot = code:lib_dir(), + LinkName = filename:join(LibRoot, "on_load_app-1.0"), + Config = [{link_name,LinkName}|Config0], + init_per_testcase(Config); init_per_testcase(_Func, Config) -> + init_per_testcase(Config). + +init_per_testcase(Config) -> P = code:get_path(), [{code_path, P}|Config]. + +end_per_testcase(module_status, Config) -> + code:purge(?TESTMOD), + code:delete(?TESTMOD), + code:purge(?TESTMOD), + file:delete(?TESTMODOBJ), + file:delete(?TESTMODSRC), + end_per_testcase(Config); end_per_testcase(TC, Config) when TC == mult_lib_roots; TC == big_boot_embedded -> {ok, HostName} = inet:gethostname(), NodeName = list_to_atom(atom_to_list(TC)++"@"++HostName), test_server:stop_node(NodeName), end_per_testcase(Config); +end_per_testcase(on_load_embedded, Config) -> + LinkName = proplists:get_value(link_name, Config), + _ = del_link(LinkName), + end_per_testcase(Config); end_per_testcase(_Func, Config) -> end_per_testcase(Config). @@ -309,7 +336,7 @@ load_abs(Config) when is_list(Config) -> {error, nofile} = code:load_abs(TestDir ++ "/duuuumy_mod"), {error, badfile} = code:load_abs(TestDir ++ "/code_a_test"), {'EXIT', _} = (catch code:load_abs({})), - {'EXIT', _} = (catch code:load_abs("Non-latin-имя-файла")), + {error, nofile} = code:load_abs("Non-latin-имя-файла"), {module, code_b_test} = code:load_abs(TestDir ++ "/code_b_test"), code:stick_dir(TestDir), {error, sticky_directory} = code:load_abs(TestDir ++ "/code_b_test"), @@ -483,23 +510,35 @@ load_binary(Config) when is_list(Config) -> code:delete(code_b_test), ok. + upgrade(Config) -> DataDir = proplists:get_value(data_dir, Config), - %%T = [beam, hipe], - T = [beam], - - [upgrade_do(DataDir, Client, U1, U2, O1, O2) - || Client<-T, U1<-T, U2<-T, O1<-T, O2<-T], - + case erlang:system_info(hipe_architecture) of + undefined -> + upgrade_do(DataDir, beam, [beam]); + + _ -> + T = [beam, hipe], + [upgrade_do(DataDir, Client, T) || Client <- T], + + case hipe:llvm_support_available() of + false -> ok; + true -> + T2 = [beam, hipe_llvm], + [upgrade_do(DataDir, Client, T2) || Client <- T2] + end + end, ok. -upgrade_do(DataDir, Client, U1, U2, O1, O2) -> +upgrade_do(DataDir, Client, T) -> compile_load(upgrade_client, DataDir, undefined, Client), - upgrade_client:run(DataDir, U1, U2, O1, O2), + [upgrade_client:run(DataDir, U1, U2, O1, O2) + || U1<-T, U2<-T, O1<-T, O2<-T], ok. compile_load(Mod, Dir, Ver, CodeType) -> + %%erlang:display({"{{{{{{{{{{{{{{{{Loading",Mod,Ver,CodeType}), Version = case Ver of undefined -> io:format("Compiling '~p' as ~p\n", [Mod, CodeType]), @@ -511,14 +550,21 @@ compile_load(Mod, Dir, Ver, CodeType) -> end, Target = case CodeType of beam -> []; - hipe -> [native] + hipe -> [native]; + hipe_llvm -> [native,{hipe,[to_llvm]}] end, CompOpts = [binary, report] ++ Target ++ Version, Src = filename:join(Dir, atom_to_list(Mod) ++ ".erl"), + T1 = erlang:now(), {ok,Mod,Code} = compile:file(Src, CompOpts), + T2 = erlang:now(), ObjFile = filename:basename(Src,".erl") ++ ".beam", {module,Mod} = code:load_binary(Mod, ObjFile, Code), + T3 = erlang:now(), + io:format("Compile time ~p ms, Load time ~p ms\n", + [timer:now_diff(T2,T1) div 1000, timer:now_diff(T3,T2) div 1000]), + %%erlang:display({"}}}}}}}}}}}}}}}Loaded",Mod,Ver,CodeType}), ok. dir_req(Config) when is_list(Config) -> @@ -818,8 +864,6 @@ check_funs({'$M_EXPR','$F_EXPR',_}, {code_server,start_link,1}]) -> 0; check_funs({'$M_EXPR','$F_EXPR',_}, [{erlang,spawn_link,1},{code_server,start_link,1}]) -> 0; -check_funs({'$M_EXPR',module_info,1}, - [{hipe_unified_loader,patch_to_emu_step1,1} | _]) -> 0; check_funs({'$M_EXPR','$F_EXPR',2}, [{hipe_unified_loader,write_words,3} | _]) -> 0; check_funs({'$M_EXPR','$F_EXPR',2}, @@ -831,11 +875,7 @@ check_funs({'$M_EXPR','$F_EXPR',2}, {hipe_unified_loader,sort_and_write,5} | _]) -> 0; check_funs({'$M_EXPR','$F_EXPR',1}, [{lists,foreach,2}, - {hipe_unified_loader,patch_consts,3} | _]) -> 0; -check_funs({'$M_EXPR','$F_EXPR',1}, - [{lists,foreach,2}, - {hipe_unified_loader,mark_referred_from,1}, - {hipe_unified_loader,get_refs_from,2}| _]) -> 0; + {hipe_unified_loader,patch_consts,4} | _]) -> 0; check_funs({'$M_EXPR',warning_msg,2}, [{code_server,finish_on_load_report,2} | _]) -> 0; check_funs({'$M_EXPR','$F_EXPR',1}, @@ -1244,10 +1284,9 @@ on_load_embedded(Config) when is_list(Config) -> on_load_embedded_1(Config) -> DataDir = proplists:get_value(data_dir, Config), + LinkName = proplists:get_value(link_name, Config), %% Link the on_load_app application into the lib directory. - LibRoot = code:lib_dir(), - LinkName = filename:join(LibRoot, "on_load_app-1.0"), OnLoadApp = filename:join(DataDir, "on_load_app-1.0"), del_link(LinkName), io:format("LinkName :~p, OnLoadApp: ~p~n",[LinkName,OnLoadApp]), @@ -1281,8 +1320,7 @@ on_load_embedded_1(Config) -> ok = rpc:call(Node, on_load_embedded, status, []), %% Clean up. - stop_node(Node), - ok = del_link(LinkName). + stop_node(Node). del_link(LinkName) -> case file:delete(LinkName) of @@ -1333,9 +1371,8 @@ create_big_boot(Config) -> %% corresponding beam file (if hipe is not enabled). filter_app("hipe",_) -> false; -%% Dialyzer and typer depends on hipe +%% Dialyzer depends on hipe filter_app("dialyzer",_) -> false; -filter_app("typer",_) -> false; %% Orber requires explicit configuration filter_app("orber",_) -> false; @@ -1752,6 +1789,185 @@ do_normalized_paths([M|Ms]) -> do_normalized_paths([]) -> ok. +%% Test that module_status/1 behaves as expected +module_status(_Config) -> + case test_server:is_cover() of + true -> + module_status(); + false -> + %% Make sure that we terminate the cover server. + try + module_status() + after + cover:stop() + end + end. + +module_status() -> + %% basics + not_loaded = code:module_status(fubar), % nonexisting + {file, preloaded} = code:is_loaded(erlang), + loaded = code:module_status(erlang), % preloaded + loaded = code:module_status(?MODULE), % normal known loaded + + non_existing = code:which(?TESTMOD), % verify dummy name not in path + code:purge(?TESTMOD), % ensure no previous version in memory + code:delete(?TESTMOD), + code:purge(?TESTMOD), + + %% generated code is detected as such + {ok,?TESTMOD,Bin} = compile:forms(dummy_ast(), []), + {module,?TESTMOD} = code:load_binary(?TESTMOD,"",Bin), % no source file + ok = ?TESTMOD:f(), + "" = code:which(?TESTMOD), % verify empty string for source file + loaded = code:module_status(?TESTMOD), + + %% deleting generated code + true = code:delete(?TESTMOD), + non_existing = code:which(?TESTMOD), % verify still not in path + not_loaded = code:module_status(?TESTMOD), + + %% beam file exists but not loaded + make_source_file(<<"0">>), + compile_beam(0), + true = (non_existing =/= code:which(?TESTMOD)), % verify in path + not_loaded = code:module_status(?TESTMOD), + + %% loading code from disk makes it loaded + load_code(), + loaded = code:module_status(?TESTMOD), % loaded + + %% cover compiling a module + {ok,?TESTMOD} = cover:compile(?TESTMOD), + {file, cover_compiled} = code:is_loaded(?TESTMOD), % verify cover compiled + modified = code:module_status(?TESTMOD), % loaded cover code but file exists + remove_code(), + removed = code:module_status(?TESTMOD), % removed + compile_beam(0), + modified = code:module_status(?TESTMOD), % recreated + load_code(), + loaded = code:module_status(?TESTMOD), % loading removes cover status + code:purge(?TESTMOD), + true = code:delete(?TESTMOD), + not_loaded = code:module_status(?TESTMOD), % deleted + + %% recompilation ignores timestamps, only md5 matters + load_code(), + compile_beam(1100), + loaded = code:module_status(?TESTMOD), + + %% modifying module detects different md5 + make_source_file(<<"1">>), + compile_beam(0), + modified = code:module_status(?TESTMOD), + + %% loading the modified code from disk makes it loaded + load_code(), + loaded = code:module_status(?TESTMOD), + + %% removing and recreating a module with same md5 + remove_code(), + removed = code:module_status(?TESTMOD), + compile_beam(0), + loaded = code:module_status(?TESTMOD), + + case erlang:system_info(hipe_architecture) of + undefined -> + %% no native support + ok; + _ -> + %% native chunk is ignored if beam code is already loaded + load_code(), + loaded = code:module_status(?TESTMOD), + false = has_native(?TESTMOD), + compile_native(0), + BeamMD5 = erlang:get_module_info(?TESTMOD, md5), + {ok,{?TESTMOD,BeamMD5}} = beam_lib:md5(?TESTMODOBJ), % beam md5 unchanged + loaded = code:module_status(?TESTMOD), + + %% native code reported as loaded, though different md5 from beam + load_code(), + true = has_native(?TESTMOD), + NativeMD5 = erlang:get_module_info(?TESTMOD, md5), + true = (BeamMD5 =/= NativeMD5), + loaded = code:module_status(?TESTMOD), + + %% recompilation ignores timestamps, only md5 matters + compile_native(1100), % later timestamp + loaded = code:module_status(?TESTMOD), + + %% modifying native module detects different md5 + make_source_file(<<"2">>), + compile_native(0), + modified = code:module_status(?TESTMOD), + + %% loading the modified native code from disk makes it loaded + load_code(), + true = has_native(?TESTMOD), + NativeMD5_2 = erlang:get_module_info(?TESTMOD, md5), + true = (NativeMD5 =/= NativeMD5_2), % verify native md5 changed + {ok,{?TESTMOD,BeamMD5_2}} = beam_lib:md5(?TESTMODOBJ), + true = (BeamMD5_2 =/= NativeMD5_2), % verify md5 differs from beam + loaded = code:module_status(?TESTMOD), + + %% removing and recreating a native module with same md5 + remove_code(), + removed = code:module_status(?TESTMOD), + compile_native(0), + loaded = code:module_status(?TESTMOD), + + %% purging/deleting native module + code:purge(?TESTMOD), + true = code:delete(?TESTMOD), + not_loaded = code:module_status(?TESTMOD) + end, + ok. + +compile_beam(Sleep) -> + compile(Sleep, []). + +compile_native(Sleep) -> + compile(Sleep, [native]). + +compile(Sleep, Opts) -> + timer:sleep(Sleep), % increment compilation timestamp + {ok,?TESTMOD} = compile:file(?TESTMODSRC, Opts). + +load_code() -> + code:purge(?TESTMOD), + {module,?TESTMOD} = code:load_file(?TESTMOD). + +remove_code() -> + ok = file:delete(?TESTMODOBJ). + +has_native(Module) -> + case erlang:get_module_info(Module, native_addresses) of + [] -> false; + [_|_] -> true + end. + +make_source_file(Body) -> + ok = file:write_file(?TESTMODSRC, dummy_source(Body)). + +dummy_source(Body) -> + [<<"-module(" ?TESTMODSTR ").\n" + "-export([f/0]).\n" + "f() -> ">>, Body, <<".\n">>]. + +dummy_ast() -> + dummy_ast(?TESTMODSTR). + +dummy_ast(Mod) when is_atom(Mod) -> + dummy_ast(atom_to_list(Mod)); +dummy_ast(ModStr) -> + [scan_form("-module(" ++ ModStr ++ ")."), + scan_form("-export([f/0])."), + scan_form("f() -> ok.")]. + +scan_form(String) -> + {ok,Ts,_} = erl_scan:string(String), + {ok,F} = erl_parse:parse_form(Ts), + F. %%----------------------------------------------------------------- %% error_logger handler. diff --git a/lib/kernel/test/code_SUITE_data/upgrade_client.erl b/lib/kernel/test/code_SUITE_data/upgrade_client.erl index bb655e01d3..faa18e1410 100644 --- a/lib/kernel/test/code_SUITE_data/upgrade_client.erl +++ b/lib/kernel/test/code_SUITE_data/upgrade_client.erl @@ -9,6 +9,8 @@ run(Dir, Upgradee1, Upgradee2, Other1, Other2) -> %% Load version 1 of upgradee code_SUITE:compile_load(upgradee, Dir, 1, Upgradee1), + Tracer = start_tracing(), + ?line 1 = upgradee:exp1(), ?line 1 = upgradee:exp1exp2(), ?line 1 = upgradee:exp1loc2(), @@ -56,6 +58,15 @@ run(Dir, Upgradee1, Upgradee2, Other1, Other2) -> ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc1), ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc2), + Env1 = "Env1", + put(loc1_fun, upgradee:get_local_fun(Env1)), + ?line {1,Env1} = (get(loc1_fun))(), + + put(exp1exp2_fun, upgradee:get_exp1exp2_fun()), + ?line 1 = (get(exp1exp2_fun))(), + + ok = check_tracing(Tracer, 13), + %% %% Load version 1 of other %% @@ -78,6 +89,8 @@ run(Dir, Upgradee1, Upgradee2, Other1, Other2) -> ?line {'EXIT',{undef,_}} = proxy_call(P, other, exp2), ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc2), + ok = check_tracing(Tracer, 5), + %% %% Load version 2 of upgradee %% @@ -130,6 +143,15 @@ run(Dir, Upgradee1, Upgradee2, Other1, Other2) -> ?line {'EXIT',{undef,_}} = proxy_call(P, other, exp2), ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc2), + ?line {1,Env1} = (get(loc1_fun))(), + Env2 = "Env2", + put(loc2_fun, upgradee:get_local_fun(Env2)), + ?line {2,Env2} = (get(loc2_fun))(), + + ?line 2 = (get(exp1exp2_fun))(), + + ok = check_tracing(Tracer, 10), + %% %% Load version 2 of other %% @@ -182,17 +204,26 @@ run(Dir, Upgradee1, Upgradee2, Other1, Other2) -> ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc1loc2), ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc2), + ?line {1,Env1} = (get(loc1_fun))(), + ?line {2,Env2} = (get(loc2_fun))(), + ?line 2 = (get(exp1exp2_fun))(), + + ok = check_tracing(Tracer, 10), %% %% Upgrade proxy to version 2 %% P ! upgrade_order, - %% - io:format("Delete version 2 of 'upgradee'\n",[]), + io:format("Purge version 1 of 'upgradee'\n",[]), %% + put(loc1_fun,undefined), code:purge(upgradee), + + %% + io:format("Delete version 2 of 'upgradee'\n",[]), + %% code:delete(upgradee), ?line {'EXIT',{undef,_}} = (catch upgradee:exp2()), @@ -239,17 +270,24 @@ run(Dir, Upgradee1, Upgradee2, Other1, Other2) -> ?line {'EXIT',{undef,_}} = proxy_call(P, other, exp1loc2), ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc1loc2), ?line {'EXIT',{undef,_}} = proxy_call(P, other, loc2), + + ?line {'EXIT',{undef,_}} = (catch (get(exp1exp2_fun))()), + ok = check_tracing(Tracer, 14), + unlink(P), exit(P, die_please), io:format("Purge 'upgradee'\n",[]), + put(loc2_fun,undefined), code:purge(upgradee), io:format("Delete and purge 'other'\n",[]), code:purge(other), code:delete(other), code:purge(other), + + stop_tracing(Tracer), ok. proxy_call(Pid, CallType, Func) -> @@ -257,3 +295,54 @@ proxy_call(Pid, CallType, Func) -> receive {Pid, call_result, Func, Ret} -> Ret end. + + +start_tracing() -> + Self = self(), + {Tracer,_} = spawn_opt(fun() -> tracer_loop(Self) end, [link,monitor]), + ?line 1 = erlang:trace_pattern({error_handler,undefined_function,3}, + true, [global]), + ?line 1 = erlang:trace(Self, true, [call,{tracer,Tracer}]), + Tracer. + + +tracer_loop(Receiver) -> + receive + die_please -> + ok; + {do_trace_delivered, Tracee} -> + _ = erlang:trace_delivered(Tracee), + tracer_loop(Receiver); + + Msg -> + Receiver ! Msg, + tracer_loop(Receiver) + end. + +check_tracing(Tracer, Expected) -> + Tracer ! {do_trace_delivered, self()}, + case check_tracing_loop(0,[]) of + {Expected,_} -> + ok; + {Got, MsgList} -> + io:format("Expected ~p trace msg, got ~p:\n~p\n", + [Expected, Got, lists:reverse(MsgList)]), + "Trace msg mismatch" + end. + +check_tracing_loop(N, MsgList) -> + Self = self(), + receive + {trace, _Pid, call, {_M, _F, _Args}} = Msg -> + check_tracing_loop(N+1, [Msg | MsgList]); + {trace_delivered, Self, _} -> + {N, MsgList} + end. + + +stop_tracing(Tracer) -> + erlang:trace(self(), false, [call]), + Tracer ! die_please, + receive + {'DOWN', _, process, Tracer, _} -> ok + end. diff --git a/lib/kernel/test/code_SUITE_data/upgradee.erl b/lib/kernel/test/code_SUITE_data/upgradee.erl index 62b1d95e30..8ca660c19c 100644 --- a/lib/kernel/test/code_SUITE_data/upgradee.erl +++ b/lib/kernel/test/code_SUITE_data/upgradee.erl @@ -8,6 +8,9 @@ -export([exp1/0]). % only exported in v1 -export([exp1loc2/0]). % exported in v1, local in v2 -export([exp1exp2/0]). % exported in v1 and v2 +-export([get_local_fun/1]). +-export([get_exp1exp2_fun/0]). +-export([exp1exp2_fun/0]). exp1() -> ?VERSION. loc1() -> ?VERSION. @@ -20,6 +23,9 @@ loc1() -> ?VERSION. -export([exp2/0]). -export([loc1exp2/0]). -export([exp1exp2/0]). +-export([get_local_fun/1]). +-export([get_exp1exp2_fun/0]). +-export([exp1exp2_fun/0]). exp2() -> ?VERSION. loc2() -> ?VERSION. @@ -31,6 +37,12 @@ exp1loc2() -> ?VERSION. loc1exp2() -> ?VERSION. loc1loc2() -> ?VERSION. +get_local_fun(Env) -> fun() -> {?VERSION,Env} end. +get_exp1exp2_fun() -> fun ?MODULE:exp1exp2_fun/0. + +exp1exp2_fun() -> + ?VERSION. + dispatch_loop() -> receive upgrade_order -> diff --git a/lib/kernel/test/disk_log_SUITE.erl b/lib/kernel/test/disk_log_SUITE.erl index f7ad9c0c04..2b11a0381f 100644 --- a/lib/kernel/test/disk_log_SUITE.erl +++ b/lib/kernel/test/disk_log_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. 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. @@ -421,7 +421,7 @@ halt_ro_alog(Conf) when is_list(Conf) -> halt_ro_alog_wait_notify(Log, T) -> Term = term_to_binary(T), receive - {disk_log, _, Log,{read_only, Term}} -> + {disk_log, _, Log,{read_only, [Term]}} -> ok; Other -> Other @@ -449,7 +449,7 @@ halt_ro_balog(Conf) when is_list(Conf) -> halt_ro_balog_wait_notify(Log, T) -> Term = list_to_binary(T), receive - {disk_log, _, Log,{read_only, Term}} -> + {disk_log, _, Log,{read_only, [Term]}} -> ok; Other -> Other @@ -481,7 +481,7 @@ halt_ro_crash(Conf) when is_list(Conf) -> %% This is how it was before R6B: %% {C1,T1,15} = disk_log:chunk(a,start), %% {C2,T2} = disk_log:chunk(a,C1), - {C1,_OneItem,7478} = disk_log:chunk(a,start), + {C1,_OneItem,7476} = disk_log:chunk(a,start), {C2, [], 7} = disk_log:chunk(a,C1), eof = disk_log:chunk(a,C2), ok = disk_log:close(a), @@ -1385,15 +1385,15 @@ blocked_notif(Conf) when is_list(Conf) -> "The requested operation" ++ _ = format_error(Error1), ok = disk_log:blog(n, B), ok = disk_log:alog(n, B), - rec(1, {disk_log, node(), n, {format_external, term_to_binary(B)}}), + rec(1, {disk_log, node(), n, {format_external, [term_to_binary(B)]}}), ok = disk_log:alog_terms(n, [B,B,B,B]), rec(1, {disk_log, node(), n, {format_external, lists:map(fun term_to_binary/1, [B,B,B,B])}}), ok = disk_log:block(n, false), ok = disk_log:alog(n, B), - rec(1, {disk_log, node(), n, {blocked_log, term_to_binary(B)}}), + rec(1, {disk_log, node(), n, {blocked_log, [term_to_binary(B)]}}), ok = disk_log:balog(n, B), - rec(1, {disk_log, node(), n, {blocked_log, list_to_binary(B)}}), + rec(1, {disk_log, node(), n, {blocked_log, [list_to_binary(B)]}}), ok = disk_log:balog_terms(n, [B,B,B,B]), disk_log:close(n), rec(1, {disk_log, node(), n, {blocked_log, @@ -2493,6 +2493,7 @@ error_repair(Conf) when is_list(Conf) -> del(File, No), ok = file:del_dir(Dir), + error_logger:add_report_handler(?MODULE, self()), %% repair a file P1 = pps(), {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, @@ -2502,13 +2503,15 @@ error_repair(Conf) when is_list(Conf) -> ok = disk_log:close(n), BadFile = add_ext(File, 2), % current file set_opened(BadFile), - crash(BadFile, 28), % the binary is now invalid - {repaired,n,{recovered,0},{badbytes,26}} = + crash(BadFile, 26), % the binary is now invalid + {repaired,n,{recovered,0},{badbytes,24}} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {format, internal}, {size, {40,No}}]), ok = disk_log:close(n), true = (P1 == pps()), del(File, No), + receive {info_msg, _, "disk_log: repairing" ++ _, _} -> ok + after 1000 -> ct:fail(failed) end, %% yet another repair P2 = pps(), @@ -2518,13 +2521,15 @@ error_repair(Conf) when is_list(Conf) -> ok = disk_log:close(n), BadFile2 = add_ext(File, 1), % current file set_opened(BadFile2), - crash(BadFile2, 51), % the second binary is now invalid - {repaired,n,{recovered,1},{badbytes,26}} = + crash(BadFile2, 47), % the second binary is now invalid + {repaired,n,{recovered,1},{badbytes,24}} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {format, internal}, {size, {4000,No}}]), ok = disk_log:close(n), true = (P2 == pps()), del(File, No), + receive {info_msg, _, "disk_log: repairing" ++ _, _} -> ok + after 1000 -> ct:fail(failed) end, %% Repair, large term Big = term_to_binary(lists:duplicate(66000,$a)), @@ -2540,6 +2545,8 @@ error_repair(Conf) when is_list(Conf) -> ok = disk_log:close(n), Got = Big, del(File, No), + receive {info_msg, _, "disk_log: repairing" ++ _, _} -> ok + after 1000 -> ct:fail(failed) end, %% A term a little smaller than a chunk, then big terms. BigSmall = mk_bytes(1024*64-8-12), @@ -2560,6 +2567,8 @@ error_repair(Conf) when is_list(Conf) -> {type, halt}, {format, internal}]), ok = disk_log:close(n), file:delete(File), + receive {info_msg, _, "disk_log: repairing" ++ _, _} -> ok + after 1000 -> ct:fail(failed) end, %% The header is recovered. {ok,n} = @@ -2571,14 +2580,15 @@ error_repair(Conf) when is_list(Conf) -> ok = disk_log:close(n), set_opened(File), crash(File, 30), - {repaired,n,{recovered,3},{badbytes,16}} = + {repaired,n,{recovered,3},{badbytes,15}} = disk_log:open([{name, n}, {file, File}, {type, halt}, - {format, internal},{repair,true}, + {format, internal},{repair,true}, {quiet, true}, {head_func, {?MODULE, head_fun, [{ok,"head"}]}}]), ["head",'of',terms] = get_all_terms(n), ok = disk_log:close(n), - + error_logger:delete_report_handler(?MODULE), file:delete(File), + {messages, []} = process_info(self(), messages), ok. @@ -2797,7 +2807,7 @@ chunk(Conf) when is_list(Conf) -> ok = disk_log:log_terms(n, [{some,terms}]), % second file full 2 = curf(n), BadFile = add_ext(File, 1), - crash(BadFile, 28), % the _binary_ is now invalid + crash(BadFile, 26), % the _binary_ is now invalid {error, {corrupt_log_file, BFile}} = disk_log:chunk(n, start, 1), BadFile = BFile, ok = disk_log:close(n), @@ -2807,7 +2817,7 @@ chunk(Conf) when is_list(Conf) -> {format, internal}]), ok = disk_log:log_terms(n, [{this,is}]), ok = disk_log:sync(n), - crash(File, 28), % the _binary_ is now invalid + crash(File, 26), % the _binary_ is now invalid {error, {corrupt_log_file, File2}} = disk_log:chunk(n, start, 1), crash(File, 10), {error,{corrupt_log_file,_}} = disk_log:bchunk(n, start, 1), @@ -2901,8 +2911,8 @@ chunk(Conf) when is_list(Conf) -> {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {format, internal}, {mode, read_only}]), CrashFile = add_ext(File, 1), - crash(CrashFile, 51), % the binary term {some,terms} is now bad - {H1, [{this,is}], 18} = disk_log:chunk(n, start, 10), + crash(CrashFile, 46), % the binary term {some,terms} is now bad + {H1, [{this,is}], 16} = disk_log:chunk(n, start, 10), {H2, [{on,a},{wrap,file}]} = disk_log:chunk(n, H1), eof = disk_log:chunk(n, H2), ok = disk_log:close(n), @@ -2916,8 +2926,8 @@ chunk(Conf) when is_list(Conf) -> ok = disk_log:close(n), {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, {format, internal}, {mode, read_only}]), - crash(File, 51), % the binary term {some,terms} is now bad - {J1, [{this,is}], 18} = disk_log:chunk(n, start, 10), + crash(File, 46), % the binary term {some,terms} is now bad + {J1, [{this,is}], 16} = disk_log:chunk(n, start, 10), {J2, [{on,a},{halt,file}]} = disk_log:chunk(n, J1), eof = disk_log:chunk(n, J2), ok = disk_log:close(n), @@ -2932,8 +2942,8 @@ chunk(Conf) when is_list(Conf) -> ok = disk_log:close(n), {ok, n} = disk_log:open([{name, n}, {file, File}, {type, halt}, {format, internal}, {mode, read_only}]), - crash(File, 44), % the binary term {s} is now bad - {J11, [{this,is}], 7} = disk_log:chunk(n, start, 10), + crash(File, 40), % the binary term {s} is now bad + {J11, [{this,is}], 6} = disk_log:chunk(n, start, 10), {J21, [{on,a},{halt,file}]} = disk_log:chunk(n, J11), eof = disk_log:chunk(n, J21), ok = disk_log:close(n), @@ -3052,7 +3062,7 @@ truncate(Conf) when is_list(Conf) -> ok = disk_log:truncate(n, apa), rec(1, {disk_log, node(), n, {truncated, 6}}), {0, 0} = no_overflows(n), - 23 = curb(n), + 22 = curb(n), 1 = curf(n), 1 = cur_cnt(n), true = (Size == sz(n)), @@ -3072,7 +3082,7 @@ truncate(Conf) when is_list(Conf) -> ok = disk_log:truncate(n, apa), rec(1, {disk_log, node(), n, {truncated, 3}}), {0, 0} = no_overflows(n), - 23 = curb(n), + 22 = curb(n), 1 = curf(n), 1 = cur_cnt(n), true = (Size == sz(n)), @@ -3181,45 +3191,45 @@ info_current(Conf) when is_list(Conf) -> %% Internal with header. {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {head, header}, {size, {100,No}}]), - {26, 1} = {curb(n), cur_cnt(n)}, + {25, 1} = {curb(n), cur_cnt(n)}, {1, 1} = {no_written_items(n), no_items(n)}, ok = disk_log:log(n, B), - {94, 2} = {curb(n), cur_cnt(n)}, + {93, 2} = {curb(n), cur_cnt(n)}, {2, 2} = {no_written_items(n), no_items(n)}, ok = disk_log:close(n), {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, {notify, true}, {head, header}, {size, {100,No}}]), - {94, 2} = {curb(n), cur_cnt(n)}, + {93, 2} = {curb(n), cur_cnt(n)}, {0, 2} = {no_written_items(n), no_items(n)}, ok = disk_log:log(n, B), rec(1, {disk_log, node(), n, {wrap, 0}}), - {94, 2} = {curb(n), cur_cnt(n)}, + {93, 2} = {curb(n), cur_cnt(n)}, {2, 4} = {no_written_items(n), no_items(n)}, disk_log:inc_wrap_file(n), rec(1, {disk_log, node(), n, {wrap, 0}}), - {26, 1} = {curb(n), cur_cnt(n)}, + {25, 1} = {curb(n), cur_cnt(n)}, {3, 4} = {no_written_items(n), no_items(n)}, ok = disk_log:log_terms(n, [B,B,B]), %% Used to be one message, but now one per wrapped file. rec(1, {disk_log, node(), n, {wrap, 0}}), rec(1, {disk_log, node(), n, {wrap, 2}}), - {94, 2} = {curb(n), cur_cnt(n)}, + {93, 2} = {curb(n), cur_cnt(n)}, {8, 7} = {no_written_items(n), no_items(n)}, ok = disk_log:log_terms(n, [B]), rec(1, {disk_log, node(), n, {wrap, 2}}), ok = disk_log:log_terms(n, [B]), rec(1, {disk_log, node(), n, {wrap, 2}}), - {94, 2} = {curb(n), cur_cnt(n)}, + {93, 2} = {curb(n), cur_cnt(n)}, {12, 7} = {no_written_items(n), no_items(n)}, ok = disk_log:log_terms(n, [BB,BB]), %% Used to be one message, but now one per wrapped file. rec(2, {disk_log, node(), n, {wrap, 2}}), - {194, 2} = {curb(n), cur_cnt(n)}, + {193, 2} = {curb(n), cur_cnt(n)}, {16, 7} = {no_written_items(n), no_items(n)}, ok = disk_log:log_terms(n, [SB,SB,SB]), rec(1, {disk_log, node(), n, {wrap, 2}}), - {80, 4} = {curb(n), cur_cnt(n)}, + {79, 4} = {curb(n), cur_cnt(n)}, {20, 9} = {no_written_items(n), no_items(n)}, ok = disk_log:close(n), del(File, No), @@ -4666,7 +4676,7 @@ other_groups(Conf) when is_list(Conf) -> ok. --define(MAX, 16384). % MAX in disk_log_1.erl +-define(MAX, ?MAX_FWRITE_CACHE). % as in disk_log_1.erl %% Evil cases such as closed file descriptor port. evil(Conf) when is_list(Conf) -> Dir = ?privdir(Conf), @@ -4690,7 +4700,7 @@ evil(Conf) when is_list(Conf) -> {size,?MAX+50},{format,external}]), [Fd] = erlang:ports() -- Ports0, {B,_} = x_mk_bytes(30), - ok = disk_log:blog(Log, <<0:(?MAX+1)/unit:8>>), + ok = disk_log:blog(Log, <<0:(?MAX-1)/unit:8>>), exit(Fd, kill), {error, {file_error,_,einval}} = disk_log:blog_terms(Log, [B,B]), ok= disk_log:close(Log), @@ -5007,6 +5017,9 @@ init(Tester) -> handle_event({error_report, _GL, {Pid, crash_report, Report}}, Tester) -> Tester ! {crash_report, Pid, Report}, {ok, Tester}; +handle_event({info_msg, _GL, {Pid, F,A}}, Tester) -> + Tester ! {info_msg, Pid, F, A}, + {ok, Tester}; handle_event(_Event, State) -> {ok, State}. diff --git a/lib/kernel/test/erl_distribution_SUITE.erl b/lib/kernel/test/erl_distribution_SUITE.erl index e43be77428..bbfaa9d147 100644 --- a/lib/kernel/test/erl_distribution_SUITE.erl +++ b/lib/kernel/test/erl_distribution_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. 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. @@ -24,7 +24,9 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2]). --export([tick/1, tick_change/1, illegal_nodenames/1, hidden_node/1, +-export([tick/1, tick_change/1, + nodenames/1, hostnames/1, + illegal_nodenames/1, hidden_node/1, setopts/1, table_waste/1, net_setuptime/1, inet_dist_options_options/1, @@ -53,7 +55,6 @@ -export([pinger/1]). - -define(DUMMY_NODE,dummy@test01). %%----------------------------------------------------------------- @@ -68,8 +69,8 @@ suite() -> {timetrap,{minutes,4}}]. all() -> - [tick, tick_change, illegal_nodenames, hidden_node, - setopts, + [tick, tick_change, nodenames, hostnames, illegal_nodenames, + hidden_node, setopts, table_waste, net_setuptime, inet_dist_options_options, {group, monitor_nodes}]. @@ -179,7 +180,105 @@ table_waste(Config) when is_list(Config) -> stop_node(N), ok. +%% Test that starting nodes with different legal name part works, and that illegal +%% ones are filtered +nodenames(Config) when is_list(Config) -> + legal("a1@b"), + legal("a-1@b"), + legal("a_1@b"), + + illegal("cdé@a"), + illegal("te欢st@a"). + +%% Test that starting nodes with different legal host part works, and that illegal +%% ones are filtered +hostnames(Config) when is_list(Config) -> + Host = gethostname(), + legal([$a,$@|atom_to_list(Host)]), + legal("1@b1"), + legal("b@b1-c"), + legal("c@b1_c"), + legal("d@b1#c"), + legal("f@::1"), + legal("g@1:bc3:4e3f:f20:0:1"), + + case file:native_name_encoding() of + latin1 -> ignore; + _ -> legal("e@b1é") + end, + long_hostnames(net_kernel:longnames()), + + illegal("h@testالع"), + illegal("i@языtest"), + illegal("j@te欢st"). + +long_hostnames(true) -> + legal("[email protected]"), + legal("[email protected]"), + legal("[email protected]_c.d"), + legal("[email protected]"), + legal("[email protected]"); +long_hostnames(false) -> + illegal("[email protected]"). + +legal(Name) -> + case test_node(Name) of + started -> + ok; + not_started -> + ct:fail("no ~p node started", [Name]) + end. + +illegal(Name) -> + case test_node(Name, true) of + not_started -> + ok; + started -> + ct:fail("~p node started with illegal name", [Name]) + end. +test_node(Name) -> + test_node(Name, false). +test_node(Name, Illigal) -> + ProgName = atom_to_list(lib:progname()), + Command = ProgName ++ " -noinput " ++ long_or_short() ++ Name ++ + " -eval \"net_adm:ping('" ++ atom_to_list(node()) ++ "')\"" ++ + case Illigal of + true -> + " -eval \"timer:sleep(10000),init:stop().\""; + false -> + "" + end, + net_kernel:monitor_nodes(true), + BinCommand = unicode:characters_to_binary(Command, utf8), + Prt = open_port({spawn, BinCommand}, [stream]), + Node = list_to_atom(Name), + receive + {nodeup, Node} -> + net_kernel:monitor_nodes(false), + slave:stop(Node), + started + after 5000 -> + net_kernel:monitor_nodes(false), + not_started + end. + +long_or_short() -> + case net_kernel:longnames() of + true -> " -name "; + false -> " -sname " + end. + +% get the localhost's name, depending on the using name policy +gethostname() -> + Hostname = case net_kernel:longnames() of + true-> + net_adm:localhost(); + _-> + {ok, Name}=inet:gethostname(), + Name + end, + list_to_atom(Hostname). %% Test that pinging an illegal nodename does not kill the node. illegal_nodenames(Config) when is_list(Config) -> @@ -230,10 +329,10 @@ time_ping(Node) -> T0 = erlang:monotonic_time(), pang = net_adm:ping(Node), T1 = erlang:monotonic_time(), - erlang:convert_time_unit(T1 - T0, native, milli_seconds). + erlang:convert_time_unit(T1 - T0, native, millisecond). %% Keep the connection with the client node up. -%% This is neccessary as the client node runs with much shorter +%% This is necessary as the client node runs with much shorter %% tick time !! keep_conn(Node) -> sleep(1), @@ -274,7 +373,7 @@ tick_cli_test1(Node) -> receive {whats_the_result, From} -> Diff = erlang:convert_time_unit(T2-T1, native, - milli_seconds), + millisecond), case Diff of T when T > 8000, T < 16000 -> From ! {tick_test, T}; @@ -1059,7 +1158,7 @@ monitor_nodes_otp_6481_test(Config, TestType) when is_list(Config) -> RemotePid = spawn(Node, fun () -> receive after 1500 -> ok end, - %% infinit loop of msgs + %% infinite loop of msgs %% we want an endless stream of messages and the kill %% the node mercilessly. %% We then want to ensure that the nodedown message arrives diff --git a/lib/kernel/test/erl_distribution_wb_SUITE.erl b/lib/kernel/test/erl_distribution_wb_SUITE.erl index 6a23ad0d11..03aaee56b7 100644 --- a/lib/kernel/test/erl_distribution_wb_SUITE.erl +++ b/lib/kernel/test/erl_distribution_wb_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2016. All Rights Reserved. +%% Copyright Ericsson AB 1999-2017. 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. @@ -30,7 +30,7 @@ %% 1) %% -%% Connections are now always set up symetrically with respect to +%% Connections are now always set up symmetrically with respect to %% publication. If connecting node doesn't send DFLAG_PUBLISHED %% the other node wont send DFLAG_PUBLISHED. If the connecting %% node send DFLAG_PUBLISHED but the other node doesn't send @@ -56,10 +56,14 @@ -define(DFLAG_HIDDEN_ATOM_CACHE,16#40). -define(DFLAG_NEW_FUN_TAGS,16#80). -define(DFLAG_EXTENDED_PIDS_PORTS,16#100). +-define(DFLAG_UTF8_ATOMS, 16#10000). %% From R9 and forward extended references is compulsory %% From R10 and forward extended pids and ports are compulsory --define(COMPULSORY_DFLAGS, (?DFLAG_EXTENDED_REFERENCES bor ?DFLAG_EXTENDED_PIDS_PORTS)). +%% From R20 and forward UTF8 atoms are compulsory +-define(COMPULSORY_DFLAGS, (?DFLAG_EXTENDED_REFERENCES bor + ?DFLAG_EXTENDED_PIDS_PORTS bor + ?DFLAG_UTF8_ATOMS)). -define(shutdown(X), exit(X)). diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl index c37d114a58..119e1f24bb 100644 --- a/lib/kernel/test/file_SUITE.erl +++ b/lib/kernel/test/file_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2016. All Rights Reserved. +%% Copyright Ericsson AB 1996-2017. 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. @@ -18,7 +18,7 @@ %% %CopyrightEnd% %% -%% This is a developement feature when developing a new file module, +%% This is a development feature when developing a new file module, %% ugly but practical. -ifndef(FILE_MODULE). -define(FILE_MODULE, file). @@ -3738,7 +3738,7 @@ response_analysis(Module, Function, Arguments) -> {Result, Comment}. micro_ts() -> - erlang:monotonic_time(micro_seconds). + erlang:monotonic_time(microsecond). response_stat(init, Ts) -> {0, 0, Ts, 0, 0}; diff --git a/lib/kernel/test/file_SUITE_data/realmen.html b/lib/kernel/test/file_SUITE_data/realmen.html index c810a5d088..92e13f23b8 100644 --- a/lib/kernel/test/file_SUITE_data/realmen.html +++ b/lib/kernel/test/file_SUITE_data/realmen.html @@ -237,7 +237,7 @@ destroy most of the interesting uses for EQUIVALENCE, and make it impossible to modify the operating system code with negative subscripts. Worst of all, bounds checking is inefficient. -<LI> Source code maintainance systems. A Real Programmer keeps his +<LI> Source code maintenance systems. A Real Programmer keeps his code locked up in a card file, because it implies that its owner cannot leave his important programs unguarded [5]. @@ -396,7 +396,7 @@ double stuff Oreos for special occasions. <LI> Underneath the Oreos is a flow-charting template, left there by the previous occupant of the office. (Real Programmers write programs, -not documentation. Leave that to the maintainence people.) +not documentation. Leave that to the maintenance people.) </UL> <P> diff --git a/lib/kernel/test/file_name_SUITE.erl b/lib/kernel/test/file_name_SUITE.erl index 10b6b105d0..899102c908 100644 --- a/lib/kernel/test/file_name_SUITE.erl +++ b/lib/kernel/test/file_name_SUITE.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2016. All Rights Reserved. +%% Copyright Ericsson AB 1996-2017. 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. @@ -383,7 +383,7 @@ check_icky(Mod) -> ok end, - _ = make_icky_dir(Mod, treat_icky(<<"åäö_dir">>)), + _ = make_icky_dir(Mod, treat_icky(<<"åäö_dir"/utf8>>)), if UniMode and (OS =/= win32) -> {error,enoent} = Mod:set_cwd("åäö_dir"); diff --git a/lib/kernel/test/gen_tcp_api_SUITE.erl b/lib/kernel/test/gen_tcp_api_SUITE.erl index 92a74465b7..3f11e25b93 100644 --- a/lib/kernel/test/gen_tcp_api_SUITE.erl +++ b/lib/kernel/test/gen_tcp_api_SUITE.erl @@ -302,9 +302,9 @@ t_implicit_inet6(Config) when is_list(Config) -> end. t_implicit_inet6(Host, Addr) -> - case gen_tcp:listen(0, [inet6]) of + Loopback = {0,0,0,0,0,0,0,1}, + case gen_tcp:listen(0, [inet6, {ip,Loopback}]) of {ok,S1} -> - Loopback = {0,0,0,0,0,0,0,1}, io:format("~s ~p~n", ["::1",Loopback]), implicit_inet6(S1, Loopback), ok = gen_tcp:close(S1), @@ -524,10 +524,10 @@ local_handshake(S, SAddr, C, CAddr) -> t_accept_inet6_tclass(Config) when is_list(Config) -> TClassOpt = {tclass,8#56 bsl 2}, % Expedited forwarding - case gen_tcp:listen(0, [inet6,TClassOpt]) of + Loopback = {0,0,0,0,0,0,0,1}, + case gen_tcp:listen(0, [inet6, {ip, Loopback}, TClassOpt]) of {ok,L} -> LPort = ok(inet:port(L)), - Loopback = {0,0,0,0,0,0,0,1}, Sa = ok(gen_tcp:connect(Loopback, LPort, [])), Sb = ok(gen_tcp:accept(L)), [TClassOpt] = ok(inet:getopts(Sb, [tclass])), diff --git a/lib/kernel/test/gen_tcp_api_SUITE_data/gen_tcp_api_SUITE.c b/lib/kernel/test/gen_tcp_api_SUITE_data/gen_tcp_api_SUITE.c index 2990ddda41..b91dca61d4 100644 --- a/lib/kernel/test/gen_tcp_api_SUITE_data/gen_tcp_api_SUITE.c +++ b/lib/kernel/test/gen_tcp_api_SUITE_data/gen_tcp_api_SUITE.c @@ -17,7 +17,7 @@ * * %CopyrightEnd% */ -#include "erl_nif.h" +#include <erl_nif.h> #include <stdio.h> #include <string.h> diff --git a/lib/kernel/test/gen_tcp_misc_SUITE.erl b/lib/kernel/test/gen_tcp_misc_SUITE.erl index 6b64c83fc2..929f66d400 100644 --- a/lib/kernel/test/gen_tcp_misc_SUITE.erl +++ b/lib/kernel/test/gen_tcp_misc_SUITE.erl @@ -1914,7 +1914,7 @@ so_priority(Config) when is_list(Config) -> %% Accept test utilities (suites are below) millis() -> - erlang:monotonic_time(milli_seconds). + erlang:monotonic_time(millisecond). collect_accepts(0,_) -> []; collect_accepts(N,Tmo) -> diff --git a/lib/kernel/test/gen_udp_SUITE.erl b/lib/kernel/test/gen_udp_SUITE.erl index 1029d7ef0a..836e0c5a05 100644 --- a/lib/kernel/test/gen_udp_SUITE.erl +++ b/lib/kernel/test/gen_udp_SUITE.erl @@ -717,9 +717,9 @@ implicit_inet6(Config) when is_list(Config) -> implicit_inet6(Host, Addr) -> Active = {active,false}, - case gen_udp:open(0, [inet6,Active]) of + Loopback = {0,0,0,0,0,0,0,1}, + case gen_udp:open(0, [inet6,Active,{ip, Loopback}]) of {ok,S1} -> - Loopback = {0,0,0,0,0,0,0,1}, io:format("~s ~p~n", ["::1",Loopback]), implicit_inet6(S1, Active, Loopback), ok = gen_udp:close(S1), diff --git a/lib/kernel/test/inet_SUITE.erl b/lib/kernel/test/inet_SUITE.erl index f60c13d2e3..3b502be8b8 100644 --- a/lib/kernel/test/inet_SUITE.erl +++ b/lib/kernel/test/inet_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. 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. @@ -40,7 +40,8 @@ lookup_bad_search_option/1, getif/1, getif_ifr_name_overflow/1,getservbyname_overflow/1, getifaddrs/1, - parse_strict_address/1, simple_netns/1, simple_netns_open/1]). + parse_strict_address/1, simple_netns/1, simple_netns_open/1, + simple_bind_to_device/1, simple_bind_to_device_open/1]). -export([get_hosts/1, get_ipv6_hosts/1, parse_hosts/1, parse_address/1, kill_gethost/0, parallell_gethost/0, test_netns/0]). @@ -58,7 +59,8 @@ all() -> gethostnative_debug_level, gethostnative_soft_restart, lookup_bad_search_option, getif, getif_ifr_name_overflow, getservbyname_overflow, - getifaddrs, parse_strict_address, simple_netns, simple_netns_open]. + getifaddrs, parse_strict_address, simple_netns, simple_netns_open, + simple_bind_to_device, simple_bind_to_device_open]. groups() -> [{parse, [], [parse_hosts, parse_address]}]. @@ -445,91 +447,125 @@ parse_hosts(Config) when is_list(Config) -> inet_parse:resolv(ResolvErr1). parse_address(Config) when is_list(Config) -> - V4Strict = + V4Reversable = [{{0,0,0,0},"0.0.0.0"}, - {{1,2,3,4},"1.2.3.4"}, + {{1,2,3,4},"1.2.3.4"}, {{253,252,251,250},"253.252.251.250"}, {{1,2,255,254},"1.2.255.254"}], - V6Strict = + V6Reversable = [{{0,0,0,0,0,0,0,0},"::"}, + {{0,0,0,0,0,0,0,1},"::1"}, + {{0,0,0,0,0,0,0,2},"::0.0.0.2"}, {{15,0,0,0,0,0,0,2},"f::2"}, - {{15,16#f11,0,0,0,0,256,2},"f:f11::0100:2"}, - {{0,0,0,0,0,0,0,16#17},"::17"}, - {{16#700,0,0,0,0,0,0,0},"0700::"}, - {{0,0,0,0,0,0,2,1},"::2:1"}, + {{15,16#f11,0,0,0,0,256,2},"f:f11::100:2"}, + {{16#700,0,0,0,0,0,0,0},"700::"}, + {{0,0,0,0,0,0,2,1},"::0.2.0.1"}, {{0,0,0,0,0,3,2,1},"::3:2:1"}, {{0,0,0,0,4,3,2,1},"::4:3:2:1"}, {{0,0,0,5,4,3,2,1},"::5:4:3:2:1"}, {{0,0,6,5,4,3,2,1},"::6:5:4:3:2:1"}, - {{0,7,6,5,4,3,2,1},"::7:6:5:4:3:2:1"}, + {{0,7,6,5,4,3,2,1},"0:7:6:5:4:3:2:1"}, {{7,0,0,0,0,0,0,0},"7::"}, {{7,6,0,0,0,0,0,0},"7:6::"}, {{7,6,5,0,0,0,0,0},"7:6:5::"}, {{7,6,5,4,0,0,0,0},"7:6:5:4::"}, {{7,6,5,4,3,0,0,0},"7:6:5:4:3::"}, {{7,6,5,4,3,2,0,0},"7:6:5:4:3:2::"}, - {{7,6,5,4,3,2,1,0},"7:6:5:4:3:2:1::"}, + {{7,6,5,4,3,2,1,0},"7:6:5:4:3:2:1:0"}, + {{0,0,6,5,4,3,0,0},"::6:5:4:3:0:0"}, + {{0,0,6,5,4,0,0,0},"0:0:6:5:4::"}, + {{8,0,0,5,4,0,0,1},"8::5:4:0:0:1"}, + {{8,0,0,5,0,0,0,1},"8:0:0:5::1"}, + {{0,7,6,5,4,3,2,0},"0:7:6:5:4:3:2:0"}, + {{0,0,6,5,4,3,0,0},"::6:5:4:3:0:0"}, + {{0,0,0,5,4,0,0,0},"::5:4:0:0:0"}, + {{0,0,0,0,4,0,0,0},"::4:0:0:0"}, + {{0,0,0,5,0,0,0,0},"0:0:0:5::"}, {{16#c11,16#c22,16#5c33,16#c440,16#55c0,16#c66c,16#77,16#88}, - "c11:0c22:5c33:c440:55c0:c66c:77:0088"}, + "c11:c22:5c33:c440:55c0:c66c:77:88"}, + {{0,16#c22,16#5c33,16#c440,16#55c0,16#c66c,16#77,16#88}, + "0:c22:5c33:c440:55c0:c66c:77:88"}, {{16#c11,0,16#5c33,16#c440,16#55c0,16#c66c,16#77,16#88}, - "c11::5c33:c440:55c0:c66c:77:0088"}, + "c11:0:5c33:c440:55c0:c66c:77:88"}, {{16#c11,16#c22,0,16#c440,16#55c0,16#c66c,16#77,16#88}, - "c11:0c22::c440:55c0:c66c:77:0088"}, + "c11:c22:0:c440:55c0:c66c:77:88"}, {{16#c11,16#c22,16#5c33,0,16#55c0,16#c66c,16#77,16#88}, - "c11:0c22:5c33::55c0:c66c:77:0088"}, + "c11:c22:5c33:0:55c0:c66c:77:88"}, {{16#c11,16#c22,16#5c33,16#c440,0,16#c66c,16#77,16#88}, - "c11:0c22:5c33:c440::c66c:77:0088"}, + "c11:c22:5c33:c440:0:c66c:77:88"}, {{16#c11,16#c22,16#5c33,16#c440,16#55c0,0,16#77,16#88}, - "c11:0c22:5c33:c440:55c0::77:0088"}, + "c11:c22:5c33:c440:55c0:0:77:88"}, {{16#c11,16#c22,16#5c33,16#c440,16#55c0,16#c66c,0,16#88}, - "c11:0c22:5c33:c440:55c0:c66c::0088"}, + "c11:c22:5c33:c440:55c0:c66c:0:88"}, + {{16#c11,16#c22,16#5c33,16#c440,16#55c0,16#c66c,16#77,0}, + "c11:c22:5c33:c440:55c0:c66c:77:0"}, + {{0,0,16#5c33,16#c440,16#55c0,16#c66c,16#77,16#88}, + "::5c33:c440:55c0:c66c:77:88"}, {{16#c11,0,0,16#c440,16#55c0,16#c66c,16#77,16#88}, - "c11::c440:55c0:c66c:77:0088"}, + "c11::c440:55c0:c66c:77:88"}, {{16#c11,16#c22,0,0,16#55c0,16#c66c,16#77,16#88}, - "c11:0c22::55c0:c66c:77:0088"}, + "c11:c22::55c0:c66c:77:88"}, {{16#c11,16#c22,16#5c33,0,0,16#c66c,16#77,16#88}, - "c11:0c22:5c33::c66c:77:0088"}, + "c11:c22:5c33::c66c:77:88"}, {{16#c11,16#c22,16#5c33,16#c440,0,0,16#77,16#88}, - "c11:0c22:5c33:c440::77:0088"}, + "c11:c22:5c33:c440::77:88"}, {{16#c11,16#c22,16#5c33,16#c440,16#55c0,0,0,16#88}, - "c11:0c22:5c33:c440:55c0::0088"}, + "c11:c22:5c33:c440:55c0::88"}, + {{16#c11,16#c22,16#5c33,16#c440,16#55c0,16#c66c,0,0}, + "c11:c22:5c33:c440:55c0:c66c::"}, + {{0,0,0,16#c440,16#55c0,16#c66c,16#77,16#88}, + "::c440:55c0:c66c:77:88"}, {{16#c11,0,0,0,16#55c0,16#c66c,16#77,16#88}, - "c11::55c0:c66c:77:0088"}, + "c11::55c0:c66c:77:88"}, {{16#c11,16#c22,0,0,0,16#c66c,16#77,16#88}, - "c11:0c22::c66c:77:0088"}, + "c11:c22::c66c:77:88"}, {{16#c11,16#c22,16#5c33,0,0,0,16#77,16#88}, - "c11:0c22:5c33::77:0088"}, + "c11:c22:5c33::77:88"}, {{16#c11,16#c22,16#5c33,16#c440,0,0,0,16#88}, - "c11:0c22:5c33:c440::0088"}, + "c11:c22:5c33:c440::88"}, + {{16#c11,16#c22,16#5c33,16#c440,16#55c0,0,0,0}, + "c11:c22:5c33:c440:55c0::"}, + {{0,0,0,0,16#55c0,16#c66c,16#77,16#88}, + "::55c0:c66c:77:88"}, {{16#c11,0,0,0,0,16#c66c,16#77,16#88}, - "c11::c66c:77:0088"}, + "c11::c66c:77:88"}, {{16#c11,16#c22,0,0,0,0,16#77,16#88}, - "c11:0c22::77:0088"}, + "c11:c22::77:88"}, {{16#c11,16#c22,16#5c33,0,0,0,0,16#88}, - "c11:0c22:5c33::0088"}, + "c11:c22:5c33::88"}, + {{16#c11,16#c22,16#5c33,16#c440,0,0,0,0}, + "c11:c22:5c33:c440::"}, + {{0,0,0,0,0,16#c66c,16#77,16#88}, + "::c66c:77:88"}, {{16#c11,0,0,0,0,0,16#77,16#88}, - "c11::77:0088"}, + "c11::77:88"}, {{16#c11,16#c22,0,0,0,0,0,16#88}, - "c11:0c22::0088"}, - {{0,0,0,0,0,65535,258,65534},"::FFFF:1.2.255.254"}, + "c11:c22::88"}, + {{16#c11,16#c22,16#5c33,0,0,0,0,0}, + "c11:c22:5c33::"}, + {{0,0,0,0,0,65535,258,65534},"::ffff:1.2.255.254"}, + {{16#fe80,12345,0,0,0,0,0,16#12},"fe80::12%012345"}, {{16#ffff,16#ffff,16#ffff,16#ffff,16#ffff,16#ffff,16#ffff,16#ffff}, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"} - |[{{D2,0,0,0,0,P,(D1 bsl 8) bor D2,(D3 bsl 8) bor D4}, - erlang:integer_to_list(D2, 16)++"::"++Q++S} - || {{D1,D2,D3,D4},S} <- V4Strict, - {P,Q} <- [{0,""},{16#17,"17:"},{16#ff0,"0ff0:"}]]], + |[{list_to_tuple(P++[(D1 bsl 8) bor D2,(D3 bsl 8) bor D4]), + Q++S} + || {{D1,D2,D3,D4},S} <- + tl(V4Reversable), + {P,Q} <- + [{[0,0,0,0,0,16#ffff],"::ffff:"}, + {[0,0,0,0,0,0],"::"}]]], V4Sloppy = [{{10,1,16#98,16#76},"10.0x019876"}, {{8#12,1,8#130,8#321},"012.01.054321"}, - {{255,255,255,255},"255.255.255.0377"}, - {{255,255,255,255},"0Xff.000000000377.0x0000ff.255"}, - {{255,255,255,255},"255.255.65535"}, - {{255,255,255,255},"255.0xFF.0177777"}, - {{255,255,255,255},"255.16777215"}, - {{255,255,255,255},"00377.0XFFFFFF"}, - {{255,255,255,255},"4294967295"}, - {{255,255,255,255},"0xffffffff"}, - {{255,255,255,255},"00000000000037777777777"}, + {{252,253,254,255},"252.253.254.0377"}, + {{252,253,254,255},"0Xfc.000000000375.0x0000fe.255"}, + {{252,253,254,255},"252.253.65279"}, + {{252,253,254,255},"252.0xFD.0177377"}, + {{252,253,254,255},"252.16645887"}, + {{252,253,254,255},"00374.0XFDFEFF"}, + {{252,253,254,255},"4244504319"}, + {{252,253,254,255},"0xfcfdfeff"}, + {{252,253,254,255},"00000000000037477377377"}, {{16#12,16#34,16#56,16#78},"0x12345678"}, {{16#12,16#34,16#56,16#78},"0x12.0x345678"}, {{16#12,16#34,16#56,16#78},"0x12.0X34.0x5678"}, @@ -541,8 +577,14 @@ parse_address(Config) when is_list(Config) -> {{0,0,0,0},"0.00.0.0"}, {{0,0,0,0},"0.0.000000000000.0"}], V6Sloppy = - [{{0,0,0,0,0,65535,(D1 bsl 8) bor D2,(D3 bsl 8) bor D4},S} - || {{D1,D2,D3,D4},S} <- V4Strict++V4Sloppy], + [{{16#a,16#b,16#c,16#0,16#0,16#d,16#e,16#f},"A:B:C::d:e:f"}, + {{16#fe80,0,0,0,0,0,0,16#12},"fe80::12%XXXXXXX"}] + ++ + [{{P,0,0,0,0,D2,(D1 bsl 8) bor D2,(D3 bsl 8) bor D4}, + Q++erlang:integer_to_list(D2, 16)++":"++S} + || {{D1,D2,D3,D4},S} <- V4Reversable, + {P,Q} <- + [{16#2001,"2001::"},{16#177,"177::"},{16#ff0,"Ff0::"}]], V4Err = ["0.256.0.1", "1.2.3.4.5", @@ -586,28 +628,36 @@ parse_address(Config) when is_list(Config) -> "fec0::fFfF:127.0.0.1."], t_parse_address (parse_ipv6_address, - V6Strict++V6Sloppy++V6Err++V4Err), + false, + V6Reversable++V6Sloppy++V6Err++V4Err), t_parse_address (parse_ipv6strict_address, - V6Strict++V6Err++V4Err++[S || {_,S} <- V6Sloppy]), + true, + V6Reversable++V6Err++V4Err), t_parse_address (parse_ipv4_address, - V4Strict++V4Sloppy++V4Err++V6Err++[S || {_,S} <- V6Strict]), + false, + V4Reversable++V4Sloppy++V4Err++V6Err++[S || {_,S} <- V6Reversable]), t_parse_address (parse_ipv4strict_address, - V4Strict++V4Err++V6Err++[S || {_,S} <- V4Sloppy++V6Strict]). + true, + V4Reversable++V4Err++V6Err++[S || {_,S} <- V4Sloppy++V6Reversable]). -t_parse_address(Func, []) -> +t_parse_address(Func, _Reversable, []) -> io:format("~p done.~n", [Func]), ok; -t_parse_address(Func, [{Addr,String}|L]) -> +t_parse_address(Func, Reversable, [{Addr,String}|L]) -> io:format("~p = ~p.~n", [Addr,String]), {ok,Addr} = inet:Func(String), - t_parse_address(Func, L); -t_parse_address(Func, [String|L]) -> + case Reversable of + true ->String = inet:ntoa(Addr); + false -> ok + end, + t_parse_address(Func, Reversable, L); +t_parse_address(Func, Reversable, [String|L]) -> io:format("~p.~n", [String]), {error,einval} = inet:Func(String), - t_parse_address(Func, L). + t_parse_address(Func, Reversable, L). parse_strict_address(Config) when is_list(Config) -> {ok, {127,0,0,1}} = @@ -1247,3 +1297,67 @@ cmd(CmdString) -> io:put_chars(["# ",CmdString,io_lib:nl()]), io:put_chars([os:cmd(CmdString++" ; echo ' =>' $?")]), ok. + +-define(CAP_NET_RAW, 13). %% from /usr/include/linux/capability.h + +can_bind_to_device({unix, linux}, {Major, _, _}) + when Major > 2 -> + Status = os:cmd("cat /proc/self/status | grep CapEff"), + [_, CapEffStr] = string:tokens(Status, [$\n, $\t]), + CapEff = list_to_integer(CapEffStr, 16), + if CapEff band (1 bsl ?CAP_NET_RAW) =/= 0 -> + ok; + true -> + {skip,"insufficient capabilities, CAP_NET_RAW not granted"} + end; +can_bind_to_device(_OS, _Version) -> + {skip,"socket option bind_to_device not supported on this OS or version"}. + +simple_bind_to_device(Config) when is_list(Config) -> + case can_bind_to_device(os:type(), os:version()) of + ok -> + {ok,U} = gen_udp:open(0), + jog_bind_to_device_opt(U), + ok = gen_udp:close(U), + %% + {ok,L} = gen_tcp:listen(0, []), + jog_bind_to_device_opt(L), + ok = gen_tcp:close(L), + %% + case gen_sctp:open() of + {ok,S} -> + jog_bind_to_device_opt(S), + ok = gen_sctp:close(S); + {error,eprotonosupport} -> + ok + end; + Other -> + Other + end. + +%% Smoke test bind_to_device support. +simple_bind_to_device_open(Config) when is_list(Config) -> + case can_bind_to_device(os:type(), os:version()) of + ok -> + {ok,U} = gen_udp:open(0, [binary,{bind_to_device,<<"lo">>},inet]), + ok = gen_udp:close(U), + {ok,T} = gen_tcp:listen(0, [binary,{bind_to_device,<<"lo">>},inet]), + ok = gen_tcp:close(T), + + case gen_sctp:open(0, [binary,{bind_to_device,<<"lo">>},inet]) of + {ok,S} -> + ok = gen_sctp:close(S); + {error,eprotonosupport} -> + ok + end; + Other -> + Other + end. + +jog_bind_to_device_opt(S) -> + %% This is just jogging the option mechanics + ok = inet:setopts(S, [{bind_to_device,<<>>}]), + {ok,[{bind_to_device,<<>>}]} = inet:getopts(S, [bind_to_device]), + ok = inet:setopts(S, [{bind_to_device,<<"lo">>}]), + {ok,[{bind_to_device,<<"lo">>}]} = inet:getopts(S, [bind_to_device]), + ok. diff --git a/lib/kernel/test/inet_sockopt_SUITE.erl b/lib/kernel/test/inet_sockopt_SUITE.erl index 322b9f30fe..9413cbd976 100644 --- a/lib/kernel/test/inet_sockopt_SUITE.erl +++ b/lib/kernel/test/inet_sockopt_SUITE.erl @@ -620,7 +620,7 @@ ipv6_v6only_close(Module, Socket) -> %% Test using socket option ipv6_v6only for UDP. use_ipv6_v6only_udp(Config) when is_list(Config) -> - case gen_udp:open(0, [inet6,{ipv6_v6only,true}]) of + case gen_udp:open(0, [inet6,{ip,{0,0,0,0,0,0,0,1}}, {ipv6_v6only,true}]) of {ok,S6} -> case inet:getopts(S6, [ipv6_v6only]) of {ok,[{ipv6_v6only,true}]} -> diff --git a/lib/kernel/test/interactive_shell_SUITE.erl b/lib/kernel/test/interactive_shell_SUITE.erl index fc3706ba1e..298a364a91 100644 --- a/lib/kernel/test/interactive_shell_SUITE.erl +++ b/lib/kernel/test/interactive_shell_SUITE.erl @@ -711,7 +711,7 @@ toerl_loop(Port,Acc) -> end. millistamp() -> - erlang:monotonic_time(milli_seconds). + erlang:monotonic_time(millisecond). get_data_within(Port, X, Acc) when X =< 0 -> ?dbg({get_data_within, X, Acc, ?LINE}), diff --git a/lib/kernel/test/multi_load_SUITE.erl b/lib/kernel/test/multi_load_SUITE.erl index 369e25ac64..f3258ea520 100644 --- a/lib/kernel/test/multi_load_SUITE.erl +++ b/lib/kernel/test/multi_load_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2016. All Rights Reserved. +%% Copyright Ericsson AB 1999-2017. 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. @@ -144,14 +144,14 @@ prep_magic([H|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 +prep_magic(Ref) when is_reference(Ref) -> + try erlang:has_prepared_code_on_load(Ref) of false -> - %% Create a different kind of magic binary. + %% Create a different kind of magic ref. ets:match_spec_compile([{'_',[true],['$_']}]) catch _:_ -> - Bin + Ref end; prep_magic(Other) -> Other. diff --git a/lib/kernel/test/os_SUITE.erl b/lib/kernel/test/os_SUITE.erl index e76d6ec482..1233e362f2 100644 --- a/lib/kernel/test/os_SUITE.erl +++ b/lib/kernel/test/os_SUITE.erl @@ -319,31 +319,38 @@ perf_counter_api(_Config) -> true = is_integer(os:perf_counter()), true = os:perf_counter() > 0, - T1 = os:perf_counter(), + Conv = fun(T1, T2) -> + erlang:convert_time_unit(T2 - T1, perf_counter, nanosecond) + end, + + do_perf_counter_test([], Conv, 120000000, 80000000), + do_perf_counter_test([1000], fun(T1, T2) -> T2 - T1 end, 120, 80). + +do_perf_counter_test(CntArgs, Conv, Upper, Lower) -> + %% We run the test multiple times to try to get a somewhat + %% stable value... what does this test? That the + %% calculate_perf_counter_unit in sys_time.c works somewhat ok. + do_perf_counter_test(CntArgs, Conv, Upper, Lower, 10). + +do_perf_counter_test(CntArgs, _Conv, Upper, Lower, 0) -> + ct:fail("perf_counter_test ~p ~p ~p",[CntArgs, Upper, Lower]); +do_perf_counter_test(CntArgs, Conv, Upper, Lower, Iters) -> + + T1 = apply(os, perf_counter, CntArgs), timer:sleep(100), - T2 = os:perf_counter(), - TsDiff = erlang:convert_time_unit(T2 - T1, perf_counter, nano_seconds), - ct:pal("T1: ~p~n" + T2 = apply(os, perf_counter, CntArgs), + TsDiff = Conv(T1, T2), + ct:log("T1: ~p~n" "T2: ~p~n" "TsDiff: ~p~n", [T1,T2,TsDiff]), - %% We allow a 15% diff - true = TsDiff < 115000000, - true = TsDiff > 85000000, - - T1Ms = os:perf_counter(1000), - timer:sleep(100), - T2Ms = os:perf_counter(1000), - MsDiff = T2Ms - T1Ms, - ct:pal("T1Ms: ~p~n" - "T2Ms: ~p~n" - "MsDiff: ~p~n", - [T1Ms,T2Ms,MsDiff]), - - %% We allow a 15% diff - true = MsDiff < 115, - true = MsDiff > 85. + if + TsDiff < Upper, TsDiff > Lower -> + ok; + true -> + do_perf_counter_test(CntArgs, Conv, Upper, Lower, Iters-1) + end. %% Util functions diff --git a/lib/kernel/test/pdict_SUITE.erl b/lib/kernel/test/pdict_SUITE.erl index 638d99176e..d105952df9 100644 --- a/lib/kernel/test/pdict_SUITE.erl +++ b/lib/kernel/test/pdict_SUITE.erl @@ -32,10 +32,13 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, mixed/1, + literals/1, simple/1, complicated/1, heavy/1, simple_all_keys/1, info/1]). -export([init_per_testcase/2, end_per_testcase/2]). -export([other_process/2]). +-export([put_do/2, get_do/1, erase_do/1]). + init_per_testcase(_Case, Config) -> Config. @@ -48,6 +51,7 @@ suite() -> all() -> [simple, complicated, heavy, simple_all_keys, info, + literals, mixed]. groups() -> @@ -418,3 +422,59 @@ do_mixed([GoalN | _]=Goals, CurrN, Array0, C, Rand0) -> Array2 = array:resize(CurrN-1, Array1), do_mixed(Goals, CurrN-1, Array2, C+1, Rand2) end. + +%% Test hash precalculation of literal keys +literals(_Config) -> + %% Put literal -> get variable + put(1742, "1742"), + "1742" = ?MODULE:get_do(1742), + "1742" = ?MODULE:erase_do(1742), + + put(-1742, "-1742"), + "-1742" = ?MODULE:get_do(-1742), + "-1742" = ?MODULE:erase_do(-1742), + + put([], "NIL"), + "NIL" = ?MODULE:get_do([]), + "NIL" = ?MODULE:erase_do([]), + + put(<<"binary">>, "binary"), + "binary" = ?MODULE:get_do(<<"binary">>), + "binary" = ?MODULE:erase_do(<<"binary">>), + + BigBin = <<"A large binary with a lot of bytes to make it go off heap as shared and reference counted">>, + put(BigBin, "bigbin"), + "bigbin" = ?MODULE:get_do(BigBin), + "bigbin" = ?MODULE:erase_do(BigBin), + + %% Put variable -> get literal + ?MODULE:put_do(4217, "4217"), + "4217" = get(4217), + "4217" = erase(4217), + + ?MODULE:put_do(-4217, "-4217"), + "-4217" = get(-4217), + "-4217" = erase(-4217), + + ?MODULE:put_do([], "NIL"), + "NIL" = get([]), + "NIL" = erase([]), + + ?MODULE:put_do(<<"bytes">>, "bytes"), + "bytes" = get(<<"bytes">>), + "bytes" = erase(<<"bytes">>), + + ?MODULE:put_do(BigBin, "BigBin"), + "BigBin" = get(BigBin), + "BigBin" = erase(BigBin), + + ok. + +put_do(K, V) -> + put(K, V). + +get_do(K) -> + get(K). + +erase_do(K) -> + erase(K). diff --git a/lib/kernel/test/pg2_SUITE.erl b/lib/kernel/test/pg2_SUITE.erl index fdc268cb5a..acecd34ead 100644 --- a/lib/kernel/test/pg2_SUITE.erl +++ b/lib/kernel/test/pg2_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2016. All Rights Reserved. +%% Copyright Ericsson AB 2008-2017. 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. @@ -31,7 +31,7 @@ -export([ otp_7277/1, otp_8259/1, otp_8653/1, - compat/1, basic/1]). + basic/1]). -define(TESTCASE, testcase_name). -define(testcase, proplists:get_value(?TESTCASE, Config)). @@ -56,7 +56,7 @@ all() -> groups() -> [{tickets, [], - [otp_7277, otp_8259, otp_8653, compat, basic]}]. + [otp_7277, otp_8259, otp_8653, basic]}]. init_per_suite(Config) -> Config. @@ -218,29 +218,6 @@ loop() -> exit(normal) end. -%% OTP-8259. Check that 'exchange' and 'del_member' work. -compat(Config) when is_list(Config) -> - case test_server:is_release_available("r13b") of - true -> - Pid = spawn(forever()), - G = a, - ok = pg2:create(G), - ok = pg2:join(G, Pid), - ok = pg2:join(G, Pid), - {ok, A} = start_node_rel(r13, r13b, slave), - pong = net_adm:ping(A), - wait_for_ready_net(Config), - {ok, _} = rpc:call(A, pg2, start, []), - ?UNTIL([Pid,Pid] =:= rpc:call(A, pg2, get_members, [a])), - true = exit(Pid, kill), - ?UNTIL([] =:= pg2:get_members(a)), - ?UNTIL([] =:= rpc:call(A, pg2, get_members, [a])), - test_server:stop_node(A), - ok; - false -> - {skipped, "No support for old node"} - end. - %% OTP-8259. Some basic tests. basic(Config) when is_list(Config) -> _ = [pg2:delete(G) || G <- pg2:which_groups()], diff --git a/lib/kernel/test/prim_file_SUITE.erl b/lib/kernel/test/prim_file_SUITE.erl index 8be94f1e57..2f4330c217 100644 --- a/lib/kernel/test/prim_file_SUITE.erl +++ b/lib/kernel/test/prim_file_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2016. All Rights Reserved. +%% Copyright Ericsson AB 2000-2017. 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. @@ -19,8 +19,8 @@ %% -module(prim_file_SUITE). -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, - init_per_group/2,end_per_group/2, - read_write_file/1]). + init_per_group/2,end_per_group/2, init_per_testcase/2, end_per_testcase/2, + read_write_file/1, free_memory/0]). -export([cur_dir_0a/1, cur_dir_0b/1, cur_dir_1a/1, cur_dir_1b/1, make_del_dir_a/1, make_del_dir_b/1, @@ -115,6 +115,18 @@ groups() -> [make_link_a, make_link_b, read_link_info_for_non_link, symlinks_a, symlinks_b, list_dir_error]}]. +init_per_testcase(large_write, Config) -> + {ok, Started} = application:ensure_all_started(os_mon), + [{started, Started}|Config]; +init_per_testcase(_TestCase, Config) -> + Config. + +end_per_testcase(large_write, Config) -> + [application:stop(App) || App <- lists:reverse(proplists:get_value(started, Config))], + ok; +end_per_testcase(_, _Config) -> + ok. + init_per_group(_GroupName, Config) -> Config. @@ -2022,11 +2034,13 @@ run_large_file_test(Config, Run, Name) -> {{unix,sunos},OsVersion} when OsVersion < {5,5,1} -> {skip,"Only supported on Win32, Unix or SunOS >= 5.5.1"}; {{unix,_},_} -> - N = unix_free(proplists:get_value(priv_dir, Config)), - io:format("Free disk: ~w KByte~n", [N]), - if N < 5 bsl 20 -> + DiscFree = unix_free(proplists:get_value(priv_dir, Config)), + MemFree = free_memory(), + io:format("Free disk: ~w KByte~n", [DiscFree]), + io:format("Free mem: ~w MByte~n", [MemFree]), + if DiscFree < 5 bsl 20; MemFree < 5 bsl 10 -> %% Less than 5 GByte free - {skip,"Less than 5 GByte free disk"}; + {skip,"Less than 5 GByte free disk/mem"}; true -> do_run_large_file_test(Config, Run, Name) end; @@ -2079,6 +2093,27 @@ zip_data([], Bs) -> zip_data(As, []) -> As. +%% Stolen from emulator -> alloc_SUITE +free_memory() -> + %% Free memory in MB. + try + SMD = memsup:get_system_memory_data(), + {value, {free_memory, Free}} = lists:keysearch(free_memory, 1, SMD), + TotFree = (Free + + case lists:keysearch(cached_memory, 1, SMD) of + {value, {cached_memory, Cached}} -> Cached; + false -> 0 + end + + case lists:keysearch(buffered_memory, 1, SMD) of + {value, {buffered_memory, Buffed}} -> Buffed; + false -> 0 + end), + TotFree div (1024*1024) + catch + error : undef -> + ct:fail({"os_mon not built"}) + end. + %%%----------------------------------------------------------------- %%% Utilities rm_rf(Mod,Dir) -> diff --git a/lib/kernel/test/sendfile_SUITE.erl b/lib/kernel/test/sendfile_SUITE.erl index 2673c38494..e839959623 100644 --- a/lib/kernel/test/sendfile_SUITE.erl +++ b/lib/kernel/test/sendfile_SUITE.erl @@ -100,13 +100,13 @@ init_per_testcase(TC,Config) when TC == t_sendfile_recvduring; %% Check if sendfile is supported on this platform case catch sendfile_send(Send) of ok -> - Config; + init_per_testcase(t_sendfile, Config); Error -> ct:log("Error: ~p",[Error]), {skip,"Not supported"} end; init_per_testcase(_Tc,Config) -> - Config. + Config ++ [{sendfile_opts,[{use_threads,false}]}]. t_sendfile_small(Config) when is_list(Config) -> diff --git a/lib/kernel/test/zlib_SUITE.erl b/lib/kernel/test/zlib_SUITE.erl index f8257bd20c..4b67fce9a8 100644 --- a/lib/kernel/test/zlib_SUITE.erl +++ b/lib/kernel/test/zlib_SUITE.erl @@ -83,7 +83,7 @@ groups() -> [api_open_close, api_deflateInit, api_deflateSetDictionary, api_deflateReset, api_deflateParams, api_deflate, api_deflateEnd, - api_inflateInit, api_inflateSetDictionary, + api_inflateInit, api_inflateSetDictionary, api_inflateGetDictionary, api_inflateSync, api_inflateReset, api_inflate, api_inflateChunk, api_inflateEnd, api_setBufsz, api_getBufsz, api_crc32, api_adler32, api_getQSize, api_un_compress, api_un_zip, @@ -288,6 +288,42 @@ api_inflateSetDictionary(Config) when is_list(Config) -> ?m({'EXIT',{stream_error,_}}, zlib:inflateSetDictionary(Z1,Dict)), ?m(ok, zlib:close(Z1)). +%% Test inflateGetDictionary. +api_inflateGetDictionary(Config) when is_list(Config) -> + Z1 = zlib:open(), + IsOperationSupported = + case catch zlib:inflateGetDictionary(Z1) of + {'EXIT',{einval,_}} -> true; + {'EXIT',{enotsup,_}} -> false + end, + _ = zlib:close(Z1), + api_inflateGetDictionary_if_supported(IsOperationSupported). + +api_inflateGetDictionary_if_supported(false) -> + {skip, "inflateGetDictionary/1 unsupported in current setup"}; +api_inflateGetDictionary_if_supported(true) -> + % Compress payload using custom dictionary + Z1 = zlib:open(), + ?m(ok, zlib:deflateInit(Z1)), + Dict = <<"foobar barfoo foo bar far boo">>, + ?m(_, zlib:deflateSetDictionary(Z1, Dict)), + Payload = <<"foobarbarbar">>, + Compressed = zlib:deflate(Z1, Payload, finish), + ?m(ok, zlib:close(Z1)), + + % Decompress and test dictionary extraction + Z2 = zlib:open(), + ?m(ok, zlib:inflateInit(Z2)), + ?m(<<>>, iolist_to_binary(zlib:inflateGetDictionary(Z2))), + ?m({'EXIT',{stream_error,_}}, zlib:inflateSetDictionary(Z2, Dict)), + ?m({'EXIT',{{need_dictionary,_},_}}, zlib:inflate(Z2, Compressed)), + ?m(ok, zlib:inflateSetDictionary(Z2, Dict)), + ?m(Dict, iolist_to_binary(zlib:inflateGetDictionary(Z2))), + ?m(Payload, iolist_to_binary(zlib:inflate(Z2, Compressed))), + ?m(ok, zlib:close(Z2)), + ?m(?BARG, zlib:inflateSetDictionary(Z2, Dict)), + ok. + %% Test inflateSync. api_inflateSync(Config) when is_list(Config) -> {skip,"inflateSync/1 sucks"}. |