From 339749764d211bf817fc428757e2c00701d26802 Mon Sep 17 00:00:00 2001 From: Shawn <506895667@qq.com> Date: Tue, 2 Nov 2021 19:13:20 +0800 Subject: [PATCH] fix(bridge): update the testcases for HTTP bridges --- apps/emqx_bridge/src/emqx_bridge_api.erl | 12 +- .../test/emqx_bridge_api_SUITE.erl | 107 +++++++++++++----- 2 files changed, 86 insertions(+), 33 deletions(-) diff --git a/apps/emqx_bridge/src/emqx_bridge_api.erl b/apps/emqx_bridge/src/emqx_bridge_api.erl index bc95b69a2..d827db1f5 100644 --- a/apps/emqx_bridge/src/emqx_bridge_api.erl +++ b/apps/emqx_bridge/src/emqx_bridge_api.erl @@ -50,7 +50,7 @@ req_schema() -> resp_schema() -> #{'oneOf' := Schema} = req_schema(), AddMetadata = fun(Prop) -> - Prop#{is_connected => #{type => boolean}, + Prop#{status => #{type => string, enum => [connected, disconnected, connecting]}, id => #{type => string}, bridge_type => #{type => string, enum => ?TYPES}, node => #{type => string}} @@ -206,9 +206,9 @@ crud_bridges(_, delete, #{bindings := #{id := Id}}) -> manage_bridges(post, #{bindings := #{node := Node, id := Id, operation := Op}}) -> OperFun = - fun (<<"start">>) -> start_bridge; - (<<"stop">>) -> stop_bridge; - (<<"restart">>) -> restart_bridge + fun (<<"start">>) -> start; + (<<"stop">>) -> stop; + (<<"restart">>) -> restart end, ?TRY_PARSE_ID(Id, case rpc_call(binary_to_atom(Node, latin1), emqx_bridge, OperFun(Op), @@ -219,12 +219,12 @@ manage_bridges(post, #{bindings := #{node := Node, id := Id, operation := Op}}) end). format_resp(#{id := Id, raw_config := RawConf, resource_data := #{mod := Mod, status := Status}}) -> - IsConnected = fun(started) -> true; (_) -> false end, + IsConnected = fun(started) -> connected; (_) -> disconnected end, RawConf#{ id => Id, node => node(), bridge_type => emqx_bridge:bridge_type(Mod), - is_connected => IsConnected(Status) + status => IsConnected(Status) }. rpc_call(Node, Fun, Args) -> diff --git a/apps/emqx_bridge/test/emqx_bridge_api_SUITE.erl b/apps/emqx_bridge/test/emqx_bridge_api_SUITE.erl index 12d05da7b..843104af1 100644 --- a/apps/emqx_bridge/test/emqx_bridge_api_SUITE.erl +++ b/apps/emqx_bridge/test/emqx_bridge_api_SUITE.erl @@ -55,8 +55,10 @@ init_per_testcase(_, Config) -> end_per_testcase(_, _Config) -> ok. --define(URL1, <<"http://localhost:9901/path1">>). --define(URL2, <<"http://localhost:9901/path2">>). +-define(URL(PORT, PATH), list_to_binary( + io_lib:format("http://localhost:~s/~s", + [integer_to_list(PORT), PATH]))). + -define(HTTP_BRIDGE(URL), #{ <<"url">> => URL, @@ -73,11 +75,26 @@ end_per_testcase(_, _Config) -> %%------------------------------------------------------------------------------ %% HTTP server for testing %%------------------------------------------------------------------------------ -start_http_server(Port, HandleFun) -> +start_http_server(HandleFun) -> + Parent = self(), spawn_link(fun() -> - {ok, Sock} = gen_tcp:listen(Port, [{active, false}]), + {Port, Sock} = listen_on_random_port(), + Parent ! {port, Port}, loop(Sock, HandleFun) - end). + end), + receive + {port, Port} -> Port + after + 2000 -> error({timeout, start_http_server}) + end. + +listen_on_random_port() -> + Min = 1024, Max = 65000, + Port = rand:uniform(Max - Min) + Min, + case gen_tcp:listen(Port, [{active, false}, {reuseaddr, true}]) of + {ok, Sock} -> {Port, Sock}; + {error, eaddrinuse} -> listen_on_random_port() + end. loop(Sock, HandleFun) -> {ok, Conn} = gen_tcp:accept(Sock), @@ -107,46 +124,50 @@ handle_fun_200_ok(Conn) -> %%------------------------------------------------------------------------------ t_crud_apis(_) -> - start_http_server(9901, fun handle_fun_200_ok/1), + Port = start_http_server(fun handle_fun_200_ok/1), %% assert we there's no bridges at first {ok, 200, <<"[]">>} = request(get, uri(["bridges"]), []), %% then we add a http bridge now %% PUT /bridges/:id will create or update a bridge - {ok, 200, Bridge} = request(put, uri(["bridges", "http:test_bridge"]), ?HTTP_BRIDGE(?URL1)), + URL1 = ?URL(Port, "path1"), + {ok, 200, Bridge} = request(put, uri(["bridges", "http:test_bridge"]), + ?HTTP_BRIDGE(URL1)), %ct:pal("---bridge: ~p", [Bridge]), ?assertMatch([ #{ <<"id">> := <<"http:test_bridge">> , <<"bridge_type">> := <<"http">> - , <<"is_connected">> := _ + , <<"status">> := _ , <<"node">> := _ - , <<"url">> := ?URL1 + , <<"url">> := URL1 }], jsx:decode(Bridge)), %% update the request-path of the bridge - {ok, 200, Bridge2} = request(put, uri(["bridges", "http:test_bridge"]), ?HTTP_BRIDGE(?URL2)), + URL2 = ?URL(Port, "path2"), + {ok, 200, Bridge2} = request(put, uri(["bridges", "http:test_bridge"]), + ?HTTP_BRIDGE(URL2)), ?assertMatch([ #{ <<"id">> := <<"http:test_bridge">> , <<"bridge_type">> := <<"http">> - , <<"is_connected">> := _ + , <<"status">> := _ , <<"node">> := _ - , <<"url">> := ?URL2 + , <<"url">> := URL2 }], jsx:decode(Bridge2)), %% list all bridges again, assert Bridge2 is in it {ok, 200, Bridge2Str} = request(get, uri(["bridges"]), []), ?assertMatch([ #{ <<"id">> := <<"http:test_bridge">> , <<"bridge_type">> := <<"http">> - , <<"is_connected">> := _ + , <<"status">> := _ , <<"node">> := _ - , <<"url">> := ?URL2 + , <<"url">> := URL2 }], jsx:decode(Bridge2Str)), %% get the bridge by id {ok, 200, Bridge3Str} = request(get, uri(["bridges", "http:test_bridge"]), []), ?assertMatch([#{ <<"id">> := <<"http:test_bridge">> , <<"bridge_type">> := <<"http">> - , <<"is_connected">> := _ + , <<"status">> := _ , <<"node">> := _ - , <<"url">> := ?URL2 + , <<"url">> := URL2 }], jsx:decode(Bridge3Str)), %% delete the bridge @@ -154,21 +175,53 @@ t_crud_apis(_) -> {ok, 200, <<"[]">>} = request(get, uri(["bridges"]), []), ok. -t_change_is_connnected_to_status() -> - error(not_implimented). - t_start_stop_bridges(_) -> - start_http_server(9901, fun handle_fun_200_ok/1), - {ok, 200, Bridge} = request(put, uri(["bridges", "http:test_bridge"]), ?HTTP_BRIDGE(?URL1)), - ?assertMatch( #{ <<"id">> := <<"http:test_bridge">> + Port = start_http_server(fun handle_fun_200_ok/1), + URL1 = ?URL(Port, "abc"), + {ok, 200, Bridge} = request(put, uri(["bridges", "http:test_bridge"]), ?HTTP_BRIDGE(URL1)), + %ct:pal("the bridge ==== ~p", [Bridge]), + ?assertMatch( [#{ <<"id">> := <<"http:test_bridge">> , <<"bridge_type">> := <<"http">> - , <<"is_connected">> := true + , <<"status">> := <<"connected">> , <<"node">> := _ - , <<"url">> := ?URL1 - }, jsx:decode(Bridge)), - {ok, 200, <<>>} = request(put, + , <<"url">> := URL1 + }], jsx:decode(Bridge)), + %% stop it + {ok, 200, <<>>} = request(post, uri(["nodes", node(), "bridges", "http:test_bridge", "operation", "stop"]), - ?HTTP_BRIDGE(?URL1)). + <<"">>), + {ok, 200, Bridge2} = request(get, uri(["bridges", "http:test_bridge"]), []), + ?assertMatch([#{ <<"id">> := <<"http:test_bridge">> + , <<"status">> := <<"disconnected">> + }], jsx:decode(Bridge2)), + %% start again + {ok, 200, <<>>} = request(post, + uri(["nodes", node(), "bridges", "http:test_bridge", "operation", "start"]), + <<"">>), + {ok, 200, Bridge3} = request(get, uri(["bridges", "http:test_bridge"]), []), + ?assertMatch([#{ <<"id">> := <<"http:test_bridge">> + , <<"status">> := <<"connected">> + }], jsx:decode(Bridge3)), + %% restart an already started bridge + {ok, 200, <<>>} = request(post, + uri(["nodes", node(), "bridges", "http:test_bridge", "operation", "restart"]), + <<"">>), + {ok, 200, Bridge3} = request(get, uri(["bridges", "http:test_bridge"]), []), + ?assertMatch([#{ <<"id">> := <<"http:test_bridge">> + , <<"status">> := <<"connected">> + }], jsx:decode(Bridge3)), + %% stop it again + {ok, 200, <<>>} = request(post, + uri(["nodes", node(), "bridges", "http:test_bridge", "operation", "stop"]), + <<"">>), + %% restart a stopped bridge + {ok, 200, <<>>} = request(post, + uri(["nodes", node(), "bridges", "http:test_bridge", "operation", "restart"]), + <<"">>), + {ok, 200, Bridge4} = request(get, uri(["bridges", "http:test_bridge"]), []), + ?assertMatch([#{ <<"id">> := <<"http:test_bridge">> + , <<"status">> := <<"connected">> + }], jsx:decode(Bridge4)). %%-------------------------------------------------------------------- %% HTTP Request