rabbitmq-server/deps/rabbitmq_mqtt/test/util.erl

141 lines
4.5 KiB
Erlang

-module(util).
-include("rabbit_mqtt.hrl").
-include_lib("rabbit_common/include/rabbit.hrl").
-include_lib("eunit/include/eunit.hrl").
-export([all_connection_pids/1,
publish_qos1_timeout/4,
sync_publish_result/3,
get_global_counters/2,
get_global_counters/3,
get_global_counters/4,
expect_publishes/3,
connect/2,
connect/3,
connect/4,
get_events/1,
assert_event_type/2,
assert_event_prop/2,
await_exit/1,
await_exit/2
]).
all_connection_pids(Config) ->
Nodes = rabbit_ct_broker_helpers:get_node_configs(Config, nodename),
Result = erpc:multicall(Nodes, rabbit_mqtt, local_connection_pids, [], 5000),
lists:foldl(fun({ok, Pids}, Acc) ->
Pids ++ Acc;
(_, Acc) ->
Acc
end, [], Result).
publish_qos1_timeout(Client, Topic, Payload, Timeout) ->
Mref = erlang:monitor(process, Client),
ok = emqtt:publish_async(Client, Topic, #{}, Payload, [{qos, 1}], infinity,
{fun ?MODULE:sync_publish_result/3, [self(), Mref]}),
receive
{Mref, Reply} ->
erlang:demonitor(Mref, [flush]),
Reply;
{'DOWN', Mref, process, Client, Reason} ->
ct:fail("client is down: ~tp", [Reason])
after
Timeout ->
erlang:demonitor(Mref, [flush]),
puback_timeout
end.
sync_publish_result(Caller, Mref, Result) ->
erlang:send(Caller, {Mref, Result}).
expect_publishes(_, _, []) ->
ok;
expect_publishes(Client, Topic, [Payload|Rest])
when is_pid(Client) ->
receive
{publish, #{client_pid := Client,
topic := Topic,
payload := Payload}} ->
expect_publishes(Client, Topic, Rest);
{publish, #{client_pid := Client,
topic := Topic,
payload := Other}} ->
ct:fail("Received unexpected PUBLISH payload. Expected: ~p Got: ~p",
[Payload, Other])
after 3000 ->
{publish_not_received, Payload}
end.
get_global_counters(Config, ProtoVer) ->
get_global_counters(Config, ProtoVer, 0, []).
get_global_counters(Config, ProtoVer, Node) ->
get_global_counters(Config, ProtoVer, Node, []).
get_global_counters(Config, v3, Node, QType) ->
get_global_counters(Config, ?MQTT_PROTO_V3, Node, QType);
get_global_counters(Config, v4, Node, QType) ->
get_global_counters(Config, ?MQTT_PROTO_V4, Node, QType);
get_global_counters(Config, Proto, Node, QType) ->
maps:get([{protocol, Proto}] ++ QType,
rabbit_ct_broker_helpers:rpc(Config, Node, rabbit_global_counters, overview, [])).
get_events(Node) ->
timer:sleep(300), %% events are sent and processed asynchronously
Result = gen_event:call({rabbit_event, Node}, event_recorder, take_state),
?assert(is_list(Result)),
Result.
assert_event_type(ExpectedType, #event{type = ActualType}) ->
?assertEqual(ExpectedType, ActualType).
assert_event_prop(ExpectedProp = {Key, _Value}, #event{props = Props}) ->
?assertEqual(ExpectedProp, lists:keyfind(Key, 1, Props));
assert_event_prop(ExpectedProps, Event)
when is_list(ExpectedProps) ->
lists:foreach(fun(P) ->
assert_event_prop(P, Event)
end, ExpectedProps).
await_exit(Pid) ->
receive
{'EXIT', Pid, _} -> ok
after
20_000 -> ct:fail({missing_exit, Pid})
end.
await_exit(Pid, Reason) ->
receive
{'EXIT', Pid, Reason} -> ok
after
20_000 -> ct:fail({missing_exit, Pid})
end.
connect(ClientId, Config) ->
connect(ClientId, Config, []).
connect(ClientId, Config, AdditionalOpts) ->
connect(ClientId, Config, 0, AdditionalOpts).
connect(ClientId, Config, Node, AdditionalOpts) ->
{Port, WsOpts, Connect} =
case rabbit_ct_helpers:get_config(Config, websocket, false) of
false ->
{rabbit_ct_broker_helpers:get_node_config(Config, Node, tcp_port_mqtt),
[],
fun emqtt:connect/1};
true ->
{rabbit_ct_broker_helpers:get_node_config(Config, Node, tcp_port_web_mqtt),
[{ws_path, "/ws"}],
fun emqtt:ws_connect/1}
end,
Options = [{host, "localhost"},
{port, Port},
{proto_ver, v4},
{clientid, rabbit_data_coercion:to_binary(ClientId)}
] ++ WsOpts ++ AdditionalOpts,
{ok, C} = emqtt:start_link(Options),
{ok, _Properties} = Connect(C),
C.