emqx/test/emqx_bridge_mqtt_tests.erl
spring2maz a056a4cbde Eliminate {error, inflight_full} from publish call to emqx_client
Prior to this change, if a emqx_client:publish/? caller sends in
QoS=1/2 messages too fast, emqx_client may return
`{error, inflight_full}` which could put put the caller to an
awkward situation: there seem to be no ohter option except for
putting self to a sleep-n-retry infinite loop.

In this change, a new gen_statm state 'inflight_full' is introduced
as a sub-state of 'connected'. When emqx_client is in 'inflight_full'
state, it postpone all publish calls (for QoS=1/2) until inflight
window size shrinks.
2019-03-05 03:47:33 +01:00

55 lines
2.0 KiB
Erlang

%% Copyright (c) 2013-2019 EMQ Technologies Co., Ltd. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
-module(emqx_bridge_mqtt_tests).
-include_lib("eunit/include/eunit.hrl").
-include("emqx_mqtt.hrl").
send_and_ack_test() ->
%% delegate from gen_rpc to rpc for unit test
meck:new(emqx_client, [passthrough, no_history]),
meck:expect(emqx_client, start_link, 1,
fun(#{msg_handler := Hdlr}) ->
{ok, spawn_link(fun() -> fake_client(Hdlr) end)}
end),
meck:expect(emqx_client, connect, 1, {ok, dummy}),
meck:expect(emqx_client, stop, 1,
fun(Pid) -> Pid ! stop end),
meck:expect(emqx_client, publish, 2,
fun(Client, Msg) ->
Client ! {publish, Msg},
{ok, Msg} %% as packet id
end),
try
Max = 100,
Batch = lists:seq(1, Max),
{ok, Ref, Conn} = emqx_bridge_mqtt:start(#{address => "127.0.0.1:1883"}),
%% return last packet id as batch reference
{ok, AckRef} = emqx_bridge_mqtt:send(Conn, Batch),
%% expect batch ack
receive {batch_ack, AckRef} -> ok end,
ok = emqx_bridge_mqtt:stop(Ref, Conn)
after
meck:unload(emqx_client)
end.
fake_client(#{puback := PubAckCallback} = Hdlr) ->
receive
{publish, PktId} ->
PubAckCallback(#{packet_id => PktId, reason_code => ?RC_SUCCESS}),
fake_client(Hdlr);
stop ->
exit(normal)
end.