Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add missing specs #275

Merged
merged 3 commits into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ jobs:
- run: make test
- run: make ct
- run: make dialyzer
if: ${{ matrix.otp == '27' }}
if: ${{ matrix.otp_vsn == '27' }}
1 change: 1 addition & 0 deletions src/escalus.app.src
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
{applications, [
kernel,
stdlib,
public_key,
ssl,
exml,
gun,
Expand Down
14 changes: 14 additions & 0 deletions src/escalus.erl
Original file line number Diff line number Diff line change
Expand Up @@ -136,46 +136,60 @@ story(Config, ResourceCounts, Story) ->

%% Assertions

-spec assert(atom(), term()) -> ok | no_return().
assert(PredSpec, Arg) ->
escalus_new_assert:assert(PredSpec, Arg).

-spec assert(atom(), [term()], term()) -> ok | no_return().
assert(PredSpec, Params, Arg) ->
escalus_new_assert:assert(PredSpec, Params, Arg).

-spec assert_many([atom()], [exml:element()]) -> ok | no_return().
assert_many(Predicates, Stanzas) ->
escalus_new_assert:assert_many(Predicates, Stanzas).

%% Client API

-spec send(client(), exml:element()) -> ok.
send(Client, Packet) ->
escalus_client:send(Client, Packet).

-spec send_and_wait(client(), exml:element()) -> exml:element().
send_and_wait(Client, Packet) ->
escalus_client:send_and_wait(Client, Packet).

-spec wait_for_stanza(client()) -> exml:element().
wait_for_stanza(Client) ->
escalus_client:wait_for_stanza(Client).

-spec wait_for_stanza(client(), timeout()) -> exml:element().
wait_for_stanza(Client, Timeout) ->
escalus_client:wait_for_stanza(Client, Timeout).

-spec wait_for_stanzas(client(), non_neg_integer()) -> [exml:element()].
wait_for_stanzas(Client, Count) ->
escalus_client:wait_for_stanzas(Client, Count).

-spec wait_for_stanzas(client(), non_neg_integer(), timeout()) -> [exml:element()].
wait_for_stanzas(Client, Count, Timeout) ->
escalus_client:wait_for_stanzas(Client, Count, Timeout).

-spec peek_stanzas(client()) -> [exml:element()].
peek_stanzas(Client) ->
escalus_client:peek_stanzas(Client).

-spec send_iq_and_wait_for_result(client(), exml:element()) -> exml:element() | no_return().
send_iq_and_wait_for_result(Client, Iq) ->
escalus_client:send_iq_and_wait_for_result(Client, Iq).

-spec send_iq_and_wait_for_result(client(), exml:element(), timeout()) ->
exml:element() | no_return().
send_iq_and_wait_for_result(Client, Iq, Timeout) ->
escalus_client:send_iq_and_wait_for_result(Client, Iq, Timeout).

%% Other functions

-spec override(config(), atom(), {atom(), atom()}) -> config().
override(Config, OverrideName, NewValue) ->
escalus_overridables:override(Config, OverrideName, NewValue).

1 change: 1 addition & 0 deletions src/escalus_assert.erl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
%%==============================================================================

-module(escalus_assert).
-compile(nowarn_missing_spec).

-export([is_chat_message/2,
has_no_stanzas/1,
Expand Down
4 changes: 2 additions & 2 deletions src/escalus_bosh.erl
Original file line number Diff line number Diff line change
Expand Up @@ -412,8 +412,8 @@ handle_info({http_reply, Ref, Body, _Transport} = HttpReply,
{_, true} ->
S1 = handle_http_reply(Ref, XmlBody, S0, Timestamp),
S1#state{ pending_replies = [] };
{{value, {Ref, _Rid, _Pid}}, _} ->
{{value, {Ref, _Rid, _Pid}}, NewRequests} = queue:out(S0#state.requests),
{{value, {Ref, Rid, Pid}}, _} ->
{{value, {Ref, Rid, Pid}}, NewRequests} = queue:out(S0#state.requests),
S1 = handle_http_reply(Ref, XmlBody, S0#state{ requests = NewRequests }, Timestamp),
lists:foreach(fun(PendingReply) -> self() ! PendingReply end,
S1#state.pending_replies),
Expand Down
14 changes: 9 additions & 5 deletions src/escalus_bosh_gun.erl
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@
handle_call/3,
handle_cast/2,
handle_info/2,
terminate/2,
code_change/3]).
terminate/2]).

-record(state, {destination,
options,
Expand All @@ -28,9 +27,11 @@
start_link(Args) ->
gen_server:start_link(?MODULE, [Args], []).

-spec stop(pid()) -> ok.
stop(Pool) ->
gen_server:cast(Pool, stop).

-spec request(pid(), iodata(), gun:req_headers(), iodata()) -> term().
request(Pool, Path, Hdrs, Body) ->
case get_client(Pool) of
{error, _} = Error ->
Expand Down Expand Up @@ -62,6 +63,8 @@ init([Args]) ->
queue = queue:new()
}, 0}.

-spec handle_call(get_client, gen_server:from(), state()) ->
{reply, term(), state()} | {noreply, state()}.
handle_call(get_client, _From, State = #state{free = [Client | Free],
busy = Busy}) ->
{reply, Client, State#state{free = Free,
Expand All @@ -83,6 +86,8 @@ handle_call(get_client, From, State = #state{free = [],
when M == T ->
{noreply, State#state{queue = queue:in(From, Queue)}}.

-spec handle_cast({free_client, pid()} | stop, state()) ->
{noreply, state()} | {stop, term(), state()}.
handle_cast({free_client, Pid}, State = #state{free = Free,
busy = Busy,
queue = Queue}) ->
Expand All @@ -98,6 +103,7 @@ handle_cast({free_client, Pid}, State = #state{free = Free,
handle_cast(stop, State) ->
{stop, normal, State}.

-spec handle_info(term(), state()) -> {noreply, state()}.
handle_info({'EXIT', From, _Reason}, State = #state{free = Free,
busy = Busy,
total = Total}) ->
Expand All @@ -113,14 +119,12 @@ handle_info(_Info, State) ->
ct:pal("Unknown Info in bosh_gun: ~p", [_Info]),
{noreply, State}.

-spec terminate(term(), state()) -> ok.
terminate(_Reason, #state{free = Free, busy = Busy}) ->
[gun:close(F) || F <- Free],
[gun:close(B) || B <- Busy],
ok.

code_change(_OldVsn, State, _Extra) ->
{ok, State}.

connect({Host, Port}, Options) ->
{ok, Pid} = gun:open(Host, Port, Options#{protocols => [http]}),
{ok, http} = gun:await_up(Pid),
Expand Down
5 changes: 5 additions & 0 deletions src/escalus_compat.erl
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
%% Public API
%%--------------------------------------------------------------------

-spec bin(binary() | string() | atom() | integer()) -> binary() | no_return().
bin(Arg) when is_binary(Arg) ->
Arg;
bin(Arg) when is_list(Arg) ->
Expand All @@ -46,17 +47,21 @@ bin(Other) ->
type_complain("???", Other),
error(badarg, [Other]).

-spec deprecated(atom(), atom(), T) -> T.
deprecated(Old, New, Result) ->
error_logger:info_msg("calling deprecated function ~p, use ~p instead~n~p~n",
[Old, New, backtrace(1)]),
Result.

-spec unimplemented() -> no_return().
unimplemented() ->
throw({unimplemented, backtrace(1)}).

-spec complain(term()) -> ok.
complain(What) ->
error_logger:info_msg("~s at ~p~n", [What, backtrace(1)]).

-spec backtrace(non_neg_integer()) -> list().
backtrace(N) ->
{current_stacktrace, Stacktrace} = erlang:process_info(self(), current_stacktrace),
lists:nthtail(N + 1, Stacktrace).
Expand Down
1 change: 1 addition & 0 deletions src/escalus_component.erl
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ handle_info(Info, #component_state{module = M, client = C, user_state = S} = Sta
{noreply, NewState, ?WAIT_AFTER_STANZA}.


-spec terminate(atom(), state()) -> any().
terminate(Reason, #component_state{client = C, module = M, user_state = S}) ->
catch escalus_connection:stop(C),
case erlang:function_exported(M, terminate, 2) of
Expand Down
3 changes: 3 additions & 0 deletions src/escalus_connection.erl
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,7 @@ upgrade_to_tls(#client{module = Mod, rcv_pid = Pid, props = Props}) ->
SSLOpts = proplists:get_value(ssl_opts, Props, DefSslOpts),
Mod:upgrade_to_tls(Pid, SSLOpts).

-spec wait_for_close(client()) -> boolean().
wait_for_close(Client) ->
wait_for_close(Client, default_timeout()).

Expand Down Expand Up @@ -476,6 +477,8 @@ maybe_forward_to_owner(_, State, Stanzas, Fun, Timestamp) ->
stanza_msg(Stanza, Metadata) ->
{stanza, self(), Stanza, Metadata}.

-spec separate_ack_requests({boolean(), non_neg_integer(), term()}, [exml_stream:element()]) ->
{{boolean(), non_neg_integer(), term()}, [exml_stream:element()], [exml_stream:element()]}.
separate_ack_requests({false, H0, A}, Stanzas) ->
%% Don't keep track of H
{{false, H0, A}, [], Stanzas};
Expand Down
1 change: 1 addition & 0 deletions src/escalus_ct.erl
Original file line number Diff line number Diff line change
Expand Up @@ -163,5 +163,6 @@ ct_log_timestamp({MS, S, US}) ->
"~2.10.0B:~2.10.0B:~2.10.0B.~3.10.0B",
[Year, Month, Day, Hour, Min, Sec, MilliSec])).

-spec log_error(term(), [any()]) -> ok.
log_error(Format, Args) ->
ct:pal(error, Format, Args).
35 changes: 29 additions & 6 deletions src/escalus_ejabberd.erl
Original file line number Diff line number Diff line change
Expand Up @@ -53,21 +53,26 @@
%%% Business API
%%%

-spec rpc(atom(), atom(), [any()], timeout()) -> any().
rpc(M, F, A, Timeout) ->
Node = escalus_ct:get_config(ejabberd_node),
Cookie = escalus_ct:get_config(ejabberd_cookie),
escalus_rpc:call(Node, M, F, A, Timeout, Cookie).

-spec rpc(atom(), atom(), [any()]) -> any().
rpc(M, F, A) ->
rpc(M, F, A, 3000).

-spec remote_display(string()) -> true.
remote_display(String) ->
Line = [$\n, [$- || _ <- String], $\n],
remote_format("~s~s~s", [Line, String, Line]).

-spec remote_format(string()) -> true.
remote_format(Format) ->
remote_format(Format, []).

-spec remote_format(string(), [any()]) -> true.
remote_format(Format, Args) ->
group_leader(rpc(erlang, whereis, [user]), self()),
io:format(Format, Args),
Expand Down Expand Up @@ -106,14 +111,17 @@ with_local_option(Option, Value, Fun) ->
end, lists:zip(Hosts, OldValues))
end.

get_c2s_status(#client{jid=Jid}) ->
-spec get_c2s_status(escalus:client()) -> term().
get_c2s_status(#client{jid = Jid}) ->
{match, USR} = re:run(Jid, <<"([^@]*)@([^/]*)/(.*)">>, [{capture, all_but_first, list}]),
Pid = rpc(ejabberd_sm, get_session_pid, USR),
rpc(sys, get_status, [Pid]).

-spec wait_for_session_count(escalus:config(), non_neg_integer()) -> ok | no_return().
wait_for_session_count(Config, Count) ->
wait_for_session_count(Config, Count, 0).

-spec get_remote_sessions(escalus:config()) -> term().
get_remote_sessions(Config) ->
escalus_overridables:do(Config, get_remote_sessions, [],
{?MODULE, default_get_remote_sessions}).
Expand Down Expand Up @@ -203,8 +211,13 @@ reset_option({Option, _, Set, _}, Config) ->
%% escalus_user_db callbacks
%%--------------------------------------------------------------------

start(_) -> ok.
stop(_) -> ok.
-spec start(_) -> ok.
start(_) ->
ok.

-spec stop(_) -> ok.
stop(_) ->
ok.

-spec create_users(escalus:config(), [escalus_users:named_user()]) -> escalus:config().
create_users(Config, Users) ->
Expand All @@ -220,11 +233,17 @@ delete_users(Config, Users) ->
%% escalus_server callbacks
%%--------------------------------------------------------------------

pre_story(Config) -> Config.
-spec pre_story(escalus:config()) -> escalus:config().
pre_story(Config) ->
Config.

post_story(Config) -> Config.
-spec post_story(escalus:config()) -> escalus:config().
post_story(Config) ->
Config.

name() -> ?MODULE.
-spec name() -> atom().
name() ->
?MODULE.

%%--------------------------------------------------------------------
%% Helpers
Expand All @@ -245,16 +264,20 @@ unregister_user(Config, {_UserName, UserSpec}) ->
[U, S, _P] = USP,
rpc(ejabberd_admin, unregister, [U, S], 30000).

-spec default_get_remote_sessions() -> any().
default_get_remote_sessions() ->
rpc(ejabberd_sm, get_full_session_list, []).

-spec legacy_get_remote_sessions() -> any().
legacy_get_remote_sessions() ->
rpc(ejabberd_sm, dirty_get_sessions_list, []).

-spec unify_str_arg(any()) -> any().
unify_str_arg(Arg) ->
StrFormat = escalus_ct:get_config(ejabberd_string_format),
unify_str_arg(Arg, StrFormat).

-spec unify_str_arg(any(), str | string()) -> any().
unify_str_arg(Arg, str) when is_binary(Arg) ->
binary_to_list(Arg);
unify_str_arg(Arg, _) ->
Expand Down
15 changes: 10 additions & 5 deletions src/escalus_event.erl
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@

-include_lib("exml/include/exml.hrl").

-type config() :: escalus_config:config().
-type event_client() :: list({atom(), any()}).
-type manager() :: pid().
-type resource() :: binary().
Expand All @@ -41,40 +40,47 @@ add_handler(Mgr, Handler, Args) ->
delete_handler(Mgr, Handler, Args) ->
gen_event:delete_handler(Mgr, Handler, Args).

-spec incoming_stanza(event_client(), exml_stream:element()) -> ok.
incoming_stanza(Client, Stanza) ->
notify_stanza(Client, incoming_stanza, Stanza).

-spec pop_incoming_stanza(event_client(), exml_stream:element()) -> ok.
pop_incoming_stanza(Client, Stanza) ->
notify_stanza(Client, pop_incoming_stanza, Stanza).

-spec outgoing_stanza(event_client(), exml_stream:element()) -> ok.
outgoing_stanza(Client, Stanza) ->
notify_stanza(Client, outgoing_stanza, Stanza).

-spec story_start(escalus_config:config()) -> ok.
story_start(Config) ->
gen_event:notify(manager(Config), story_start).

-spec story_end(escalus_config:config()) -> ok.
story_end(Config) ->
gen_event:notify(manager(Config), story_end).


%% ====================================================================

%% @doc Start the event manager
%% @end
-spec start(escalus_config:config()) -> escalus_config:config().
start(Config) ->
{ok, Mgr} = gen_event:start_link(),
add_handler(Mgr, escalus_history_h, []),
[{escalus_event_mgr, Mgr} | Config].

%% @doc Stop the event manager
%% @end
-spec stop(escalus_config:config()) -> escalus_config:config().
stop(Config) ->
gen_event:stop(manager(Config)),
Config.

-spec get_history(escalus_config:config()) -> [term()].
get_history(Config) ->
escalus_history_h:get_history(manager(Config)).

-spec print_history(escalus_config:config()) -> ok.
print_history(Config) ->
CaseName = proplists:get_value(tc_name, Config),
PrivDir = proplists:get_value(priv_dir, Config),
Expand Down Expand Up @@ -179,7 +185,7 @@ manager(Config) ->

%% @doc Create a new event emitter.
-spec new_client(Config, User, MaybeResource) -> undefined | EventClient when
Config :: config(),
Config :: escalus_config:config(),
User :: escalus_users:user_name() | escalus_users:user_spec(),
MaybeResource :: undefined | resource(),
EventClient :: event_client().
Expand All @@ -206,7 +212,6 @@ new_client_1(Mgr, UserSpec, Resource) ->

%% @doc Notify the event system of an event
%% <p>The system accepts any term as the event.</p>
%% @end
notify_stanza(undefined, _, _) ->
ok;
notify_stanza(Client, EventName, Stanza) ->
Expand Down
Loading