summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRaimo Niskanen <raimo@erlang.org>2021-08-30 14:26:18 +0200
committerRaimo Niskanen <raimo@erlang.org>2021-08-31 09:14:46 +0200
commitb8f6206c198fdc4a4084cbcbdc1432fd5a5293a2 (patch)
treec89af1469cb8bc2de4005cbaddbbf2a611966ae1
parentacf515e4cb20808276e5698fb3c2d582f5ce90c8 (diff)
downloaderlang-b8f6206c198fdc4a4084cbcbdc1432fd5a5293a2.tar.gz
Test API errors
Also, adjust some inconsistent error returns / exceptions.
-rw-r--r--lib/kernel/src/socket.erl29
-rw-r--r--lib/kernel/test/socket_SUITE.erl101
2 files changed, 116 insertions, 14 deletions
diff --git a/lib/kernel/src/socket.erl b/lib/kernel/src/socket.erl
index 295fd37782..c92494ee43 100644
--- a/lib/kernel/src/socket.erl
+++ b/lib/kernel/src/socket.erl
@@ -1349,13 +1349,18 @@ open(FD) ->
Socket :: socket(),
Reason :: posix() | 'protocol'.
-open(FD, Opts) when is_integer(FD), is_map(Opts) ->
- case prim_socket:open(FD, Opts) of
- {ok, SockRef} ->
- Socket = ?socket(SockRef),
- {ok, Socket};
- {error, _} = ERROR ->
- ERROR
+open(FD, Opts) when is_map(Opts) ->
+ if
+ is_integer(FD) ->
+ case prim_socket:open(FD, Opts) of
+ {ok, SockRef} ->
+ Socket = ?socket(SockRef),
+ {ok, Socket};
+ {error, _} = ERROR ->
+ ERROR
+ end;
+ true ->
+ erlang:error(badarg, [FD, Opts])
end;
open(Domain, Type) ->
open(Domain, Type, 0).
@@ -1415,11 +1420,8 @@ open(Domain, Type, Protocol, Opts) ->
Addr :: sockaddr() | 'any' | 'broadcast' | 'loopback',
Reason :: posix() | 'closed' | invalid().
-bind(?socket(SockRef) = Socket, Addr) when is_reference(SockRef) ->
+bind(?socket(SockRef), Addr) when is_reference(SockRef) ->
if
- is_map(Addr) ->
- prim_socket:bind(SockRef, Addr);
- %%
Addr =:= any;
Addr =:= broadcast;
Addr =:= loopback ->
@@ -1434,9 +1436,10 @@ bind(?socket(SockRef) = Socket, Addr) when is_reference(SockRef) ->
{error, _} = ERROR ->
ERROR
end;
- %%
+ is_atom(Addr) ->
+ {error, {invalid, {sockaddr, Addr}}};
true ->
- erlang:error(badarg, [Socket, Addr])
+ prim_socket:bind(SockRef, Addr)
end;
bind(Socket, Addr) ->
erlang:error(badarg, [Socket, Addr]).
diff --git a/lib/kernel/test/socket_SUITE.erl b/lib/kernel/test/socket_SUITE.erl
index 8bb1711efb..5cecd308f3 100644
--- a/lib/kernel/test/socket_SUITE.erl
+++ b/lib/kernel/test/socket_SUITE.erl
@@ -71,6 +71,8 @@
%% *** API Misc ***
api_m_info/1,
api_m_debug/1,
+ api_m_error_open/1,
+ api_m_error_bind/1,
%% *** API Basic ***
api_b_open_and_info_udp4/1,
@@ -849,7 +851,9 @@ api_cases() ->
api_misc_cases() ->
[
api_m_info,
- api_m_debug
+ api_m_debug,
+ api_m_error_open,
+ api_m_error_bind
].
api_basic_cases() ->
@@ -2239,6 +2243,101 @@ api_m_debug() ->
i("ok"),
ok.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Some tests for API misuses
+
+-define(
+ EXCEPTION(Code),
+ exception(fun () -> begin Code end end)).
+
+exception(Fun) ->
+ try Fun() of
+ Result ->
+ error({unexpected_return, Result})
+ catch
+ Class : Reason ->
+ {Class, Reason}
+ end.
+
+
+api_m_error_open(Config) when is_list(Config) ->
+ %%
+ %% open/1
+ {error, badarg} =
+ ?EXCEPTION(
+ socket:open(should_be_fd) ),
+ %%
+ %% open/2
+ {error, badarg} =
+ ?EXCEPTION(
+ socket:open(should_be_fd, #{}) ),
+ %%
+ %% A non-atom, non-integer protocol causes an exception
+ %% in prim_socket, whilst a non-atom, non-integer type
+ %% or domain causes an error return tuple from the NIF
+ %% code. This is a bit inconsistent. Should we change
+ %% that, if so - how, and consolidate in tests?
+ %%
+ {error,{invalid,{domain,should_be_domain}}} =
+ socket:open(should_be_domain, dgram),
+ {error,{invalid,{type,should_be_type}}} =
+ socket:open(inet, should_be_type),
+ %%
+ %% open/3
+ {error,{invalid,{domain,should_be_domain}}} =
+ socket:open(should_be_domain, dgram, #{}),
+ {error,{invalid,{type,should_be_type}}} =
+ socket:open(inet, should_be_type, #{}),
+ {error,{invalid,{protocol,should_be_protocol}}} =
+ socket:open(inet, dgram, should_be_protocol),
+ %%
+ %% open/4
+ {error,{invalid,{domain,should_be_domain}}} =
+ socket:open(should_be_domain, dgram, default, #{}),
+ {error,{invalid,{type,should_be_type}}} =
+ socket:open(inet, should_be_type, default, #{}),
+ {error,{invalid,{protocol,should_be_protocol}}} =
+ socket:open(inet, dgram, should_be_protocol, #{}),
+ {error, badarg} =
+ ?EXCEPTION(
+ socket:open(inet, dgram, default, should_be_options) ).
+
+
+api_m_error_bind(Config) when is_list(Config) ->
+ {ok, S} = socket:open(inet, dgram),
+ try
+ %%
+ %% bind/2
+ {error, badarg} =
+ ?EXCEPTION(
+ socket:bind(should_be_socket, any) ),
+ {error, badarg} =
+ ?EXCEPTION(
+ socket:bind(make_ref(), any) ),
+ %%
+ %% A non-map, non-atom Addr causes an {invalid,_}
+ %% exception. Should that instead be an error
+ %% return?
+ %%
+ {error,{invalid,{sockaddr,should_be_sockaddr}}} =
+ socket:bind(S, should_be_sockaddr),
+ EmptyMap = #{},
+ {error,{invalid,{sockaddr,family,EmptyMap}}} =
+ socket:bind(S, EmptyMap),
+ InvalidKey = #{family => inet, invalid_key => []},
+ {error,{invalid,{sockaddr,{keys,[invalid_key]},InvalidKey}}} =
+ socket:bind(S, InvalidKey),
+ InvalidFamily = #{family => invalid_family},
+ {error,{invalid,{sockaddr,InvalidFamily}}} =
+ socket:bind(S, InvalidFamily)
+ after
+ _ = socket:close(S)
+ end,
+ ok.
+
+
+%% XXX Lots of missing error tests here, for all other API functions...
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%