mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-07 19:22:14 +09:00
164 lines
5.9 KiB
Erlang
164 lines
5.9 KiB
Erlang
%% SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
-module(gateway_resume_timings_tests).
|
|
-typing([eqwalizer]).
|
|
|
|
-include_lib("eunit/include/eunit.hrl").
|
|
|
|
handle_resume_success_dispatches_gateway_timings_test() ->
|
|
drain_mailbox(),
|
|
SessionPid = spawn(fun() -> fake_resume_session_loop(<<"resume-token">>, 12, true) end),
|
|
meck:new(session_manager, [passthrough, no_link]),
|
|
meck:new(rpc_client, [passthrough, no_link]),
|
|
meck:expect(
|
|
session_manager,
|
|
lookup_or_rehydrate,
|
|
fun(<<"session-with-timings">>, <<"resume-token">>, SocketPid) when is_pid(SocketPid) ->
|
|
{ok, SessionPid}
|
|
end
|
|
),
|
|
meck:expect(rpc_client, call, fun(_Request) -> error(unexpected_resume_api_call) end),
|
|
try
|
|
State0 = maps:remove(peer_ip, new_json_state()),
|
|
{ok, State1} = gateway_handler_identify:handle_resume(
|
|
#{
|
|
<<"token">> => <<"resume-token">>,
|
|
<<"session_id">> => <<"session-with-timings">>,
|
|
<<"seq">> => 7
|
|
},
|
|
State0
|
|
),
|
|
?assertEqual(SessionPid, maps:get(session_pid, State1)),
|
|
assert_resumed_timing_dispatch(12)
|
|
after
|
|
SessionPid ! stop,
|
|
meck:unload(rpc_client),
|
|
meck:unload(session_manager)
|
|
end.
|
|
|
|
handle_resume_omits_gateway_timings_for_non_staff_test() ->
|
|
drain_mailbox(),
|
|
SessionPid = spawn(fun() -> fake_resume_session_loop(<<"resume-token">>, 12, false) end),
|
|
meck:new(session_manager, [passthrough, no_link]),
|
|
meck:new(rpc_client, [passthrough, no_link]),
|
|
meck:expect(
|
|
session_manager,
|
|
lookup_or_rehydrate,
|
|
fun(<<"session-non-staff">>, <<"resume-token">>, SocketPid) when is_pid(SocketPid) ->
|
|
{ok, SessionPid}
|
|
end
|
|
),
|
|
meck:expect(rpc_client, call, fun(_Request) -> error(unexpected_resume_api_call) end),
|
|
try
|
|
State0 = maps:remove(peer_ip, new_json_state()),
|
|
{ok, State1} = gateway_handler_identify:handle_resume(
|
|
#{
|
|
<<"token">> => <<"resume-token">>,
|
|
<<"session_id">> => <<"session-non-staff">>,
|
|
<<"seq">> => 7
|
|
},
|
|
State0
|
|
),
|
|
?assertEqual(SessionPid, maps:get(session_pid, State1)),
|
|
assert_resumed_dispatch_without_timings(12)
|
|
after
|
|
SessionPid ! stop,
|
|
meck:unload(rpc_client),
|
|
meck:unload(session_manager)
|
|
end.
|
|
|
|
handle_resume_missing_session_sends_invalid_session_without_api_test() ->
|
|
drain_mailbox(),
|
|
meck:new(session_manager, [passthrough, no_link]),
|
|
meck:expect(
|
|
session_manager,
|
|
lookup_or_rehydrate,
|
|
fun(<<"missing-session">>, <<"resume-token">>, SocketPid) when is_pid(SocketPid) ->
|
|
{error, not_found}
|
|
end
|
|
),
|
|
try
|
|
{Frames, _State1} = gateway_handler_identify:handle_resume(
|
|
#{
|
|
<<"token">> => <<"resume-token">>,
|
|
<<"session_id">> => <<"missing-session">>,
|
|
<<"seq">> => 7
|
|
},
|
|
new_json_state()
|
|
),
|
|
?assertMatch([_Frame], Frames)
|
|
after
|
|
meck:unload(session_manager)
|
|
end.
|
|
|
|
assert_resumed_dispatch_without_timings(ExpectedSeq) ->
|
|
receive
|
|
{dispatch, resumed, ResumedData, ExpectedSeq} ->
|
|
?assertNot(maps:is_key(<<"_timings_gw">>, ResumedData))
|
|
after 1000 ->
|
|
?assert(false, resumed_not_dispatched)
|
|
end.
|
|
|
|
assert_resumed_timing_dispatch(ExpectedSeq) ->
|
|
receive
|
|
{dispatch, resumed, ResumedData, ExpectedSeq} ->
|
|
Timings = maps:get(<<"_timings_gw">>, ResumedData),
|
|
?assertEqual(<<"microseconds">>, maps:get(<<"unit">>, Timings)),
|
|
?assert(is_binary(maps:get(<<"pod_name">>, Timings))),
|
|
Trace = maps:get(<<"trace">>, Timings),
|
|
TraceNames = [maps:get(<<"name">>, Span) || Span <- Trace],
|
|
?assert(
|
|
lists:member(<<"gateway_handler_identify:validate_resume_data/1">>, TraceNames)
|
|
),
|
|
?assert(lists:member(<<"session_manager:lookup_or_rehydrate/3">>, TraceNames)),
|
|
?assert(lists:member(<<"session_lifecycle:handle_token_verify/2">>, TraceNames)),
|
|
?assert(lists:member(<<"session_lifecycle:handle_resume/3">>, TraceNames)),
|
|
?assert(
|
|
lists:member(<<"gateway_handler_identify:replay_missed_events/2">>, TraceNames)
|
|
),
|
|
ResumeSpan = find_trace_span(<<"session_lifecycle:handle_resume/3">>, Trace),
|
|
ResumeRemote = maps:get(<<"remote">>, ResumeSpan),
|
|
?assertEqual(<<"session">>, maps:get(<<"operation">>, ResumeRemote)),
|
|
?assert(is_binary(maps:get(<<"pod_name">>, ResumeRemote)))
|
|
after 1000 ->
|
|
?assert(false, resumed_not_dispatched)
|
|
end.
|
|
|
|
fake_resume_session_loop(Token, CurrentSeq, IsStaff) ->
|
|
receive
|
|
{'$gen_call', From, {token_verify, Candidate}} ->
|
|
gen_server:reply(From, Candidate =:= Token),
|
|
fake_resume_session_loop(Token, CurrentSeq, IsStaff);
|
|
{'$gen_call', From, {resume, _Seq, SocketPid}} when is_pid(SocketPid) ->
|
|
gen_server:reply(From, {ok, [], CurrentSeq}),
|
|
fake_resume_session_loop(Token, CurrentSeq, IsStaff);
|
|
{'$gen_call', From, {is_staff}} ->
|
|
gen_server:reply(From, IsStaff),
|
|
fake_resume_session_loop(Token, CurrentSeq, IsStaff);
|
|
stop ->
|
|
ok
|
|
after 30000 ->
|
|
ok
|
|
end.
|
|
|
|
find_trace_span(Name, Trace) ->
|
|
case [Span || Span <- Trace, maps:get(<<"name">>, Span, undefined) =:= Name] of
|
|
[Span | _] -> Span;
|
|
[] -> error({trace_span_not_found, Name})
|
|
end.
|
|
|
|
drain_mailbox() ->
|
|
receive
|
|
_ -> drain_mailbox()
|
|
after 0 ->
|
|
ok
|
|
end.
|
|
|
|
new_json_state() ->
|
|
(gateway_handler:new_state())#{
|
|
version => 1,
|
|
encoding => json,
|
|
compress_ctx => gateway_compress:new_context(none),
|
|
peer_ip => <<"127.0.0.1">>
|
|
}.
|