diff options
Diffstat (limited to 'lib/kernel/test')
-rw-r--r-- | lib/kernel/test/code_SUITE.erl | 3 | ||||
-rw-r--r-- | lib/kernel/test/file_name_SUITE.erl | 52 | ||||
-rw-r--r-- | lib/kernel/test/gen_sctp_SUITE.erl | 198 |
3 files changed, 248 insertions, 5 deletions
diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index 3e8bdaf1ff..827208b048 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -1550,7 +1550,8 @@ native_early_modules_1(Architecture) -> true -> ?line true = lists:all(fun code:is_module_native/1, [ets,file,filename,gb_sets,gb_trees, - hipe_unified_loader,lists,os,packages]), + %%hipe_unified_loader, no_native as workaround + lists,os,packages]), ok end. diff --git a/lib/kernel/test/file_name_SUITE.erl b/lib/kernel/test/file_name_SUITE.erl index 53bcb1162d..be33ec2c06 100644 --- a/lib/kernel/test/file_name_SUITE.erl +++ b/lib/kernel/test/file_name_SUITE.erl @@ -74,7 +74,7 @@ init_per_suite/1,end_per_suite/1, init_per_group/2,end_per_group/2, init_per_testcase/2, end_per_testcase/2]). --export([normal/1,icky/1,very_icky/1,normalize/1]). +-export([normal/1,icky/1,very_icky/1,normalize/1,home_dir/1]). init_per_testcase(_Func, Config) -> @@ -88,7 +88,7 @@ end_per_testcase(_Func, Config) -> suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [normal, icky, very_icky, normalize]. + [normal, icky, very_icky, normalize, home_dir]. groups() -> []. @@ -105,6 +105,54 @@ init_per_group(_GroupName, Config) -> end_per_group(_GroupName, Config) -> Config. +home_dir(suite) -> + []; +home_dir(doc) -> + ["Check that Erlang can be started with unicode named home directory"]; +home_dir(Config) when is_list(Config) -> + try + Name=[960,945,964,961,953,954], + Priv = ?config(priv_dir, Config), + UniMode = file:native_name_encoding() =/= latin1, + if + not UniMode -> + throw(need_unicode_mode); + true -> + ok + end, + NewHome=filename:join(Priv,Name), + file:make_dir(NewHome), + {SaveOldName,SaveOldValue} = case os:type() of + {win32,nt} -> + HomePath=re:replace(filename:nativename(NewHome),"^[a-zA-Z]:","",[{return,list},unicode]), + Save = os:getenv("HOMEPATH"), + os:putenv("HOMEPATH",HomePath), + {"HOMEPATH",Save}; + {unix,_} -> + Save = os:getenv("HOME"), + os:putenv("HOME",NewHome), + {"HOME",Save}; + _ -> + rm_rf(prim_file,NewHome), + throw(unsupported_os) + end, + try + {ok,Node} = test_server:start_node(test_unicode_homedir,slave,[{args,"-setcookie "++atom_to_list(erlang:get_cookie())}]), + test_server:stop_node(Node), + ok + after + os:putenv(SaveOldName,SaveOldValue), + rm_rf(prim_file,NewHome) + end + catch + throw:need_unicode_mode -> + io:format("Sorry, can only run in unicode mode.~n"), + {skipped,"VM needs to be started in Unicode filename mode"}; + throw:unsupported_os -> + io:format("Sorry, can only run on Unix/Windows.~n"), + {skipped,"Runs only on Unix/Windows"} + end. + normalize(suite) -> []; normalize(doc) -> diff --git a/lib/kernel/test/gen_sctp_SUITE.erl b/lib/kernel/test/gen_sctp_SUITE.erl index 8f490b6643..f4bf6e719e 100644 --- a/lib/kernel/test/gen_sctp_SUITE.erl +++ b/lib/kernel/test/gen_sctp_SUITE.erl @@ -31,14 +31,22 @@ [basic/1, api_open_close/1,api_listen/1,api_connect_init/1,api_opts/1, xfer_min/1,xfer_active/1,def_sndrcvinfo/1,implicit_inet6/1, - basic_stream/1, xfer_stream_min/1, peeloff/1, buffers/1]). + basic_stream/1, xfer_stream_min/1, peeloff/1, buffers/1, + open_multihoming_ipv4_socket/1, + open_unihoming_ipv6_socket/1, + open_multihoming_ipv6_socket/1, + open_multihoming_ipv4_and_ipv6_socket/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [basic, api_open_close, api_listen, api_connect_init, api_opts, xfer_min, xfer_active, def_sndrcvinfo, implicit_inet6, - basic_stream, xfer_stream_min, peeloff, buffers]. + basic_stream, xfer_stream_min, peeloff, buffers, + open_multihoming_ipv4_socket, + open_unihoming_ipv6_socket, + open_multihoming_ipv6_socket, + open_multihoming_ipv4_and_ipv6_socket]. groups() -> []. @@ -1105,6 +1113,192 @@ mk_data(N, Bytes, Bin) when N < Bytes -> mk_data(_, _, Bin) -> Bin. + + +open_multihoming_ipv4_socket(doc) -> + "Test opening a multihoming ipv4 socket"; +open_multihoming_ipv4_socket(suite) -> + []; +open_multihoming_ipv4_socket(Config) when is_list(Config) -> + ?line case get_addrs_by_family(inet, 2) of + {ok, [Addr1, Addr2]} -> + ?line do_open_and_connect([Addr1, Addr2], Addr1); + {error, Reason} -> + {skip, Reason} + end. + +open_unihoming_ipv6_socket(doc) -> + %% This test is mostly aimed to indicate + %% whether host has a non-working ipv6 setup + "Test opening a unihoming (non-multihoming) ipv6 socket"; +open_unihoming_ipv6_socket(suite) -> + []; +open_unihoming_ipv6_socket(Config) when is_list(Config) -> + ?line case get_addrs_by_family(inet6, 1) of + {ok, [Addr]} -> + ?line do_open_and_connect([Addr], Addr); + {error, Reason} -> + {skip, Reason} + end. + + +open_multihoming_ipv6_socket(doc) -> + "Test opening a multihoming ipv6 socket"; +open_multihoming_ipv6_socket(suite) -> + []; +open_multihoming_ipv6_socket(Config) when is_list(Config) -> + ?line case get_addrs_by_family(inet6, 2) of + {ok, [Addr1, Addr2]} -> + ?line do_open_and_connect([Addr1, Addr2], Addr1); + {error, Reason} -> + {skip, Reason} + end. + +open_multihoming_ipv4_and_ipv6_socket(doc) -> + "Test opening a multihoming ipv6 socket with ipv4 and ipv6 addresses"; +open_multihoming_ipv4_and_ipv6_socket(suite) -> + []; +open_multihoming_ipv4_and_ipv6_socket(Config) when is_list(Config) -> + ?line case get_addrs_by_family(inet_and_inet6, 2) of + {ok, [[InetAddr1, InetAddr2], [Inet6Addr1, Inet6Addr2]]} -> + %% Connect to the first address to test bind + ?line do_open_and_connect([InetAddr1, Inet6Addr1, InetAddr2], + InetAddr1), + ?line do_open_and_connect([Inet6Addr1, InetAddr1], + Inet6Addr1), + + %% Connect an address, not the first, + %% to test sctp_bindx + ?line do_open_and_connect([Inet6Addr1, Inet6Addr2, InetAddr1], + Inet6Addr2), + ?line do_open_and_connect([Inet6Addr1, Inet6Addr2, InetAddr1], + InetAddr1); + {error, Reason} -> + {skip, Reason} + end. + + +get_addrs_by_family(Family, NumAddrs) -> + case os:type() of + {unix,linux} -> + get_addrs_by_family_aux(Family, NumAddrs); + {unix,freebsd} -> + get_addrs_by_family_aux(Family, NumAddrs); + {unix,sunos} -> + case get_addrs_by_family_aux(Family, NumAddrs) of + {ok, [InetAddrs, Inet6Addrs]} when Family =:= inet_and_inet6 -> + %% Man page for sctp_bindx on Solaris says: "If sock is an + %% Internet Protocol Version 6 (IPv6) socket, addrs should + %% be an array of sockaddr_in6 structures containing IPv6 + %% or IPv4-mapped IPv6 addresses." + {ok, [ipv4_map_addrs(InetAddrs), Inet6Addrs]}; + {ok, Addrs} -> + {ok, Addrs}; + {error, Reason} -> + {error, Reason} + end; + Os -> + Reason = if Family =:= inet_and_inet6 -> + f("Mixing ipv4 and ipv6 addresses for multihoming " + " has not been verified on ~p", [Os]); + true -> + f("Multihoming for ~p has not been verified on ~p", + [Family, Os]) + end, + {error, Reason} + end. + +get_addrs_by_family_aux(Family, NumAddrs) when Family =:= inet; + Family =:= inet6 -> + ?line + case inet:getaddr(localhost, Family) of + {error,eafnosupport} -> + {skip, f("No support for ~p", Family)}; + {ok, _} -> + ?line IfAddrs = ok(inet:getifaddrs()), + ?line case filter_addrs_by_family(IfAddrs, Family) of + Addrs when length(Addrs) >= NumAddrs -> + {ok, lists:sublist(Addrs, NumAddrs)}; + [] -> + {error, f("Need ~p ~p address(es) found none~n", + [NumAddrs, Family])}; + Addrs -> + {error, + f("Need ~p ~p address(es) found only ~p: ~p~n", + [NumAddrs, Family, length(Addrs), Addrs])} + end + end; +get_addrs_by_family_aux(inet_and_inet6, NumAddrs) -> + ?line catch {ok, [case get_addrs_by_family_aux(Family, NumAddrs) of + {ok, Addrs} -> Addrs; + {error, Reason} -> throw({error, Reason}) + end || Family <- [inet, inet6]]}. + +filter_addrs_by_family(IfAddrs, Family) -> + lists:flatten([[Addr || {addr, Addr} <- Info, + is_good_addr(Addr, Family)] + || {_IfName, Info} <- IfAddrs]). + +is_good_addr(Addr, inet) when tuple_size(Addr) =:= 4 -> + true; +is_good_addr({0,0,0,0,0,16#ffff,_,_}, inet6) -> + false; %% ipv4 mapped +is_good_addr({16#fe80,_,_,_,_,_,_,_}, inet6) -> + false; %% link-local +is_good_addr(Addr, inet6) when tuple_size(Addr) =:= 8 -> + true; +is_good_addr(_Addr, _Family) -> + false. + +ipv4_map_addrs(InetAddrs) -> + [begin + <<AB:16>> = <<A,B>>, + <<CD:16>> = <<C,D>>, + {0, 0, 0, 0, 0, 16#ffff, AB, CD} + end || {A,B,C,D} <- InetAddrs]. + +f(F, A) -> + lists:flatten(io_lib:format(F, A)). + +do_open_and_connect(ServerAddresses, AddressToConnectTo) -> + ?line ServerFamily = get_family_by_addrs(ServerAddresses), + ?line io:format("Serving ~p addresses: ~p~n", + [ServerFamily, ServerAddresses]), + ?line S1 = ok(gen_sctp:open(0, [{ip,Addr} || Addr <- ServerAddresses] ++ + [ServerFamily])), + ?line ok = gen_sctp:listen(S1, true), + ?line P1 = ok(inet:port(S1)), + ?line ClientFamily = get_family_by_addr(AddressToConnectTo), + ?line io:format("Connecting to ~p ~p~n", + [ClientFamily, AddressToConnectTo]), + ?line S2 = ok(gen_sctp:open(0, [ClientFamily])), + %% Verify client can connect + ?line #sctp_assoc_change{state=comm_up} = + ok(gen_sctp:connect(S2, AddressToConnectTo, P1, [])), + %% verify server side also receives comm_up from client + ?line recv_comm_up_eventually(S1), + ?line ok = gen_sctp:close(S2), + ?line ok = gen_sctp:close(S1). + +%% If at least one of the addresses is an ipv6 address, return inet6, else inet. +get_family_by_addrs(Addresses) -> + ?line case lists:usort([get_family_by_addr(Addr) || Addr <- Addresses]) of + [inet, inet6] -> inet6; + [inet] -> inet; + [inet6] -> inet6 + end. + +get_family_by_addr(Addr) when tuple_size(Addr) =:= 4 -> inet; +get_family_by_addr(Addr) when tuple_size(Addr) =:= 8 -> inet6. + +recv_comm_up_eventually(S) -> + ?line case ok(gen_sctp:recv(S)) of + {_Addr, _Port, _Info, #sctp_assoc_change{state=comm_up}} -> + ok; + {_Addr, _Port, _Info, _OtherSctpMsg} -> + ?line recv_comm_up_eventually(S) + end. + %%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% socket gen_server ultra light |