|
|
@@ -1,5 +1,5 @@
|
|
|
%%--------------------------------------------------------------------
|
|
|
-%% Copyright (c) 2023 EMQ Technologies Co., Ltd. All Rights Reserved.
|
|
|
+%% Copyright (c) 2023-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
|
|
%%--------------------------------------------------------------------
|
|
|
|
|
|
-module(emqx_bridge_opents_SUITE).
|
|
|
@@ -12,7 +12,8 @@
|
|
|
-include_lib("snabbkaffe/include/snabbkaffe.hrl").
|
|
|
|
|
|
% DB defaults
|
|
|
--define(BATCH_SIZE, 10).
|
|
|
+-define(BRIDGE_TYPE_BIN, <<"opents">>).
|
|
|
+-define(APPS, [opentsdb, emqx_bridge, emqx_resource, emqx_rule_engine, emqx_bridge_opents_SUITE]).
|
|
|
|
|
|
%%------------------------------------------------------------------------------
|
|
|
%% CT boilerplate
|
|
|
@@ -20,95 +21,34 @@
|
|
|
|
|
|
all() ->
|
|
|
[
|
|
|
- {group, with_batch},
|
|
|
- {group, without_batch}
|
|
|
+ {group, default}
|
|
|
].
|
|
|
|
|
|
groups() ->
|
|
|
- TCs = emqx_common_test_helpers:all(?MODULE),
|
|
|
+ AllTCs = emqx_common_test_helpers:all(?MODULE),
|
|
|
[
|
|
|
- {with_batch, TCs},
|
|
|
- {without_batch, TCs}
|
|
|
+ {default, AllTCs}
|
|
|
].
|
|
|
|
|
|
-init_per_group(with_batch, Config0) ->
|
|
|
- Config = [{batch_size, ?BATCH_SIZE} | Config0],
|
|
|
- common_init(Config);
|
|
|
-init_per_group(without_batch, Config0) ->
|
|
|
- Config = [{batch_size, 1} | Config0],
|
|
|
- common_init(Config);
|
|
|
-init_per_group(_Group, Config) ->
|
|
|
- Config.
|
|
|
-
|
|
|
-end_per_group(Group, Config) when Group =:= with_batch; Group =:= without_batch ->
|
|
|
- ProxyHost = ?config(proxy_host, Config),
|
|
|
- ProxyPort = ?config(proxy_port, Config),
|
|
|
- emqx_common_test_helpers:reset_proxy(ProxyHost, ProxyPort),
|
|
|
- ok;
|
|
|
-end_per_group(_Group, _Config) ->
|
|
|
- ok.
|
|
|
-
|
|
|
init_per_suite(Config) ->
|
|
|
- Config.
|
|
|
-
|
|
|
-end_per_suite(_Config) ->
|
|
|
- emqx_mgmt_api_test_util:end_suite(),
|
|
|
- ok = emqx_common_test_helpers:stop_apps([opentsdb, emqx_bridge, emqx_resource, emqx_conf]),
|
|
|
- ok.
|
|
|
-
|
|
|
-init_per_testcase(_Testcase, Config) ->
|
|
|
- delete_bridge(Config),
|
|
|
- snabbkaffe:start_trace(),
|
|
|
- Config.
|
|
|
-
|
|
|
-end_per_testcase(_Testcase, Config) ->
|
|
|
- ProxyHost = ?config(proxy_host, Config),
|
|
|
- ProxyPort = ?config(proxy_port, Config),
|
|
|
- emqx_common_test_helpers:reset_proxy(ProxyHost, ProxyPort),
|
|
|
- ok = snabbkaffe:stop(),
|
|
|
- delete_bridge(Config),
|
|
|
- ok.
|
|
|
+ emqx_bridge_v2_testlib:init_per_suite(Config, ?APPS).
|
|
|
|
|
|
-%%------------------------------------------------------------------------------
|
|
|
-%% Helper fns
|
|
|
-%%------------------------------------------------------------------------------
|
|
|
+end_per_suite(Config) ->
|
|
|
+ emqx_bridge_v2_testlib:end_per_suite(Config).
|
|
|
|
|
|
-common_init(ConfigT) ->
|
|
|
- Host = os:getenv("OPENTS_HOST", "toxiproxy"),
|
|
|
+init_per_group(default, Config0) ->
|
|
|
+ Host = os:getenv("OPENTS_HOST", "toxiproxy.emqx.net"),
|
|
|
Port = list_to_integer(os:getenv("OPENTS_PORT", "4242")),
|
|
|
-
|
|
|
- Config0 = [
|
|
|
- {opents_host, Host},
|
|
|
- {opents_port, Port},
|
|
|
- {proxy_name, "opents"}
|
|
|
- | ConfigT
|
|
|
- ],
|
|
|
-
|
|
|
- BridgeType = proplists:get_value(bridge_type, Config0, <<"opents">>),
|
|
|
+ ProxyName = "opents",
|
|
|
case emqx_common_test_helpers:is_tcp_server_available(Host, Port) of
|
|
|
true ->
|
|
|
- % Setup toxiproxy
|
|
|
- ProxyHost = os:getenv("PROXY_HOST", "toxiproxy"),
|
|
|
- ProxyPort = list_to_integer(os:getenv("PROXY_PORT", "8474")),
|
|
|
- emqx_common_test_helpers:reset_proxy(ProxyHost, ProxyPort),
|
|
|
- % Ensure enterprise bridge module is loaded
|
|
|
- ok = emqx_common_test_helpers:start_apps([
|
|
|
- emqx_conf, emqx_resource, emqx_bridge
|
|
|
- ]),
|
|
|
- _ = application:ensure_all_started(opentsdb),
|
|
|
- _ = emqx_bridge_enterprise:module_info(),
|
|
|
- emqx_mgmt_api_test_util:init_suite(),
|
|
|
- {Name, OpenTSConf} = opents_config(BridgeType, Config0),
|
|
|
- Config =
|
|
|
- [
|
|
|
- {opents_config, OpenTSConf},
|
|
|
- {opents_bridge_type, BridgeType},
|
|
|
- {opents_name, Name},
|
|
|
- {proxy_host, ProxyHost},
|
|
|
- {proxy_port, ProxyPort}
|
|
|
- | Config0
|
|
|
- ],
|
|
|
- Config;
|
|
|
+ Config = emqx_bridge_v2_testlib:init_per_group(default, ?BRIDGE_TYPE_BIN, Config0),
|
|
|
+ [
|
|
|
+ {bridge_host, Host},
|
|
|
+ {bridge_port, Port},
|
|
|
+ {proxy_name, ProxyName}
|
|
|
+ | Config
|
|
|
+ ];
|
|
|
false ->
|
|
|
case os:getenv("IS_CI") of
|
|
|
"yes" ->
|
|
|
@@ -116,250 +56,200 @@ common_init(ConfigT) ->
|
|
|
_ ->
|
|
|
{skip, no_opents}
|
|
|
end
|
|
|
- end.
|
|
|
+ end;
|
|
|
+init_per_group(_Group, Config) ->
|
|
|
+ Config.
|
|
|
|
|
|
-opents_config(BridgeType, Config) ->
|
|
|
- Port = integer_to_list(?config(opents_port, Config)),
|
|
|
- Server = "http://" ++ ?config(opents_host, Config) ++ ":" ++ Port,
|
|
|
- Name = atom_to_binary(?MODULE),
|
|
|
- BatchSize = ?config(batch_size, Config),
|
|
|
+end_per_group(default, Config) ->
|
|
|
+ emqx_bridge_v2_testlib:end_per_group(Config),
|
|
|
+ ok;
|
|
|
+end_per_group(_Group, _Config) ->
|
|
|
+ ok.
|
|
|
+
|
|
|
+init_per_testcase(TestCase, Config0) ->
|
|
|
+ Type = ?config(bridge_type, Config0),
|
|
|
+ UniqueNum = integer_to_binary(erlang:unique_integer()),
|
|
|
+ Name = <<
|
|
|
+ (atom_to_binary(TestCase))/binary, UniqueNum/binary
|
|
|
+ >>,
|
|
|
+ {_ConfigString, ConnectorConfig} = connector_config(Name, Config0),
|
|
|
+ {_, ActionConfig} = action_config(Name, Config0),
|
|
|
+ Config = [
|
|
|
+ {connector_type, Type},
|
|
|
+ {connector_name, Name},
|
|
|
+ {connector_config, ConnectorConfig},
|
|
|
+ {bridge_type, Type},
|
|
|
+ {bridge_name, Name},
|
|
|
+ {bridge_config, ActionConfig}
|
|
|
+ | Config0
|
|
|
+ ],
|
|
|
+ %% iotdb_reset(Config),
|
|
|
+ ok = snabbkaffe:start_trace(),
|
|
|
+ Config.
|
|
|
+
|
|
|
+end_per_testcase(TestCase, Config) ->
|
|
|
+ emqx_bridge_v2_testlib:end_per_testcase(TestCase, Config).
|
|
|
+
|
|
|
+%%------------------------------------------------------------------------------
|
|
|
+%% Helper fns
|
|
|
+%%------------------------------------------------------------------------------
|
|
|
+
|
|
|
+action_config(Name, Config) ->
|
|
|
+ Type = ?config(bridge_type, Config),
|
|
|
ConfigString =
|
|
|
io_lib:format(
|
|
|
- "bridges.~s.~s {\n"
|
|
|
+ "actions.~s.~s {\n"
|
|
|
" enable = true\n"
|
|
|
- " server = ~p\n"
|
|
|
- " resource_opts = {\n"
|
|
|
- " request_ttl = 500ms\n"
|
|
|
- " batch_size = ~b\n"
|
|
|
- " query_mode = sync\n"
|
|
|
+ " connector = \"~s\"\n"
|
|
|
+ " parameters = {\n"
|
|
|
+ " data = []\n"
|
|
|
" }\n"
|
|
|
- "}",
|
|
|
+ "}\n",
|
|
|
[
|
|
|
- BridgeType,
|
|
|
+ Type,
|
|
|
Name,
|
|
|
- Server,
|
|
|
- BatchSize
|
|
|
+ Name
|
|
|
]
|
|
|
),
|
|
|
- {Name, parse_and_check(ConfigString, BridgeType, Name)}.
|
|
|
-
|
|
|
-parse_and_check(ConfigString, BridgeType, Name) ->
|
|
|
- {ok, RawConf} = hocon:binary(ConfigString, #{format => map}),
|
|
|
- hocon_tconf:check_plain(emqx_bridge_schema, RawConf, #{required => false, atom_key => false}),
|
|
|
- #{<<"bridges">> := #{BridgeType := #{Name := Config}}} = RawConf,
|
|
|
- Config.
|
|
|
+ ct:pal("ActionConfig:~ts~n", [ConfigString]),
|
|
|
+ {ConfigString, parse_action_and_check(ConfigString, Type, Name)}.
|
|
|
+
|
|
|
+connector_config(Name, Config) ->
|
|
|
+ Host = ?config(bridge_host, Config),
|
|
|
+ Port = ?config(bridge_port, Config),
|
|
|
+ Type = ?config(bridge_type, Config),
|
|
|
+ ServerURL = opents_server_url(Host, Port),
|
|
|
+ ConfigString =
|
|
|
+ io_lib:format(
|
|
|
+ "connectors.~s.~s {\n"
|
|
|
+ " enable = true\n"
|
|
|
+ " server = \"~s\"\n"
|
|
|
+ "}\n",
|
|
|
+ [
|
|
|
+ Type,
|
|
|
+ Name,
|
|
|
+ ServerURL
|
|
|
+ ]
|
|
|
+ ),
|
|
|
+ ct:pal("ConnectorConfig:~ts~n", [ConfigString]),
|
|
|
+ {ConfigString, parse_connector_and_check(ConfigString, Type, Name)}.
|
|
|
|
|
|
-create_bridge(Config) ->
|
|
|
- create_bridge(Config, _Overrides = #{}).
|
|
|
-
|
|
|
-create_bridge(Config, Overrides) ->
|
|
|
- BridgeType = ?config(opents_bridge_type, Config),
|
|
|
- Name = ?config(opents_name, Config),
|
|
|
- Config0 = ?config(opents_config, Config),
|
|
|
- Config1 = emqx_utils_maps:deep_merge(Config0, Overrides),
|
|
|
- emqx_bridge:create(BridgeType, Name, Config1).
|
|
|
-
|
|
|
-delete_bridge(Config) ->
|
|
|
- BridgeType = ?config(opents_bridge_type, Config),
|
|
|
- Name = ?config(opents_name, Config),
|
|
|
- emqx_bridge:remove(BridgeType, Name).
|
|
|
-
|
|
|
-create_bridge_http(Params) ->
|
|
|
- Path = emqx_mgmt_api_test_util:api_path(["bridges"]),
|
|
|
- AuthHeader = emqx_mgmt_api_test_util:auth_header_(),
|
|
|
- case emqx_mgmt_api_test_util:request_api(post, Path, "", AuthHeader, Params) of
|
|
|
- {ok, Res} -> {ok, emqx_utils_json:decode(Res, [return_maps])};
|
|
|
- Error -> Error
|
|
|
- end.
|
|
|
-
|
|
|
-send_message(Config, Payload) ->
|
|
|
- Name = ?config(opents_name, Config),
|
|
|
- BridgeType = ?config(opents_bridge_type, Config),
|
|
|
- BridgeID = emqx_bridge_resource:bridge_id(BridgeType, Name),
|
|
|
- emqx_bridge:send_message(BridgeID, Payload).
|
|
|
-
|
|
|
-query_resource(Config, Request) ->
|
|
|
- query_resource(Config, Request, 1_000).
|
|
|
-
|
|
|
-query_resource(Config, Request, Timeout) ->
|
|
|
- Name = ?config(opents_name, Config),
|
|
|
- BridgeType = ?config(opents_bridge_type, Config),
|
|
|
- ResourceID = emqx_bridge_resource:resource_id(BridgeType, Name),
|
|
|
- emqx_resource:query(ResourceID, Request, #{timeout => Timeout}).
|
|
|
+parse_action_and_check(ConfigString, BridgeType, Name) ->
|
|
|
+ parse_and_check(ConfigString, emqx_bridge_schema, <<"actions">>, BridgeType, Name).
|
|
|
|
|
|
-%%------------------------------------------------------------------------------
|
|
|
-%% Testcases
|
|
|
-%%------------------------------------------------------------------------------
|
|
|
+parse_connector_and_check(ConfigString, ConnectorType, Name) ->
|
|
|
+ parse_and_check(
|
|
|
+ ConfigString, emqx_connector_schema, <<"connectors">>, ConnectorType, Name
|
|
|
+ ).
|
|
|
+%% emqx_utils_maps:safe_atom_key_map(Config).
|
|
|
|
|
|
-t_setup_via_config_and_publish(Config) ->
|
|
|
- ?assertMatch(
|
|
|
- {ok, _},
|
|
|
- create_bridge(Config)
|
|
|
- ),
|
|
|
- SentData = make_data(),
|
|
|
- ?check_trace(
|
|
|
- begin
|
|
|
- {_, {ok, #{result := Result}}} =
|
|
|
- ?wait_async_action(
|
|
|
- send_message(Config, SentData),
|
|
|
- #{?snk_kind := buffer_worker_flush_ack},
|
|
|
- 2_000
|
|
|
- ),
|
|
|
- ?assertMatch(
|
|
|
- {ok, 200, #{failed := 0, success := 1}}, Result
|
|
|
- ),
|
|
|
- ok
|
|
|
- end,
|
|
|
- fun(Trace0) ->
|
|
|
- Trace = ?of_kind(opents_connector_query_return, Trace0),
|
|
|
- ?assertMatch([#{result := {ok, 200, #{failed := 0, success := 1}}}], Trace),
|
|
|
- ok
|
|
|
- end
|
|
|
- ),
|
|
|
- ok.
|
|
|
+parse_and_check(ConfigString, SchemaMod, RootKey, Type0, Name) ->
|
|
|
+ Type = to_bin(Type0),
|
|
|
+ {ok, RawConf} = hocon:binary(ConfigString, #{format => map}),
|
|
|
+ hocon_tconf:check_plain(SchemaMod, RawConf, #{required => false, atom_key => false}),
|
|
|
+ #{RootKey := #{Type := #{Name := Config}}} = RawConf,
|
|
|
+ Config.
|
|
|
|
|
|
-t_setup_via_http_api_and_publish(Config) ->
|
|
|
- BridgeType = ?config(opents_bridge_type, Config),
|
|
|
- Name = ?config(opents_name, Config),
|
|
|
- OpentsConfig0 = ?config(opents_config, Config),
|
|
|
- OpentsConfig = OpentsConfig0#{
|
|
|
- <<"name">> => Name,
|
|
|
- <<"type">> => BridgeType
|
|
|
+to_bin(List) when is_list(List) ->
|
|
|
+ unicode:characters_to_binary(List, utf8);
|
|
|
+to_bin(Atom) when is_atom(Atom) ->
|
|
|
+ erlang:atom_to_binary(Atom);
|
|
|
+to_bin(Bin) when is_binary(Bin) ->
|
|
|
+ Bin.
|
|
|
+
|
|
|
+opents_server_url(Host, Port) ->
|
|
|
+ iolist_to_binary([
|
|
|
+ "http://",
|
|
|
+ Host,
|
|
|
+ ":",
|
|
|
+ integer_to_binary(Port)
|
|
|
+ ]).
|
|
|
+
|
|
|
+is_success_check({ok, 200, #{failed := Failed}}) ->
|
|
|
+ ?assertEqual(0, Failed);
|
|
|
+is_success_check(Ret) ->
|
|
|
+ ?assert(false, Ret).
|
|
|
+
|
|
|
+is_error_check(Result) ->
|
|
|
+ ?assertMatch({error, {400, #{failed := 1}}}, Result).
|
|
|
+
|
|
|
+opentds_query(Config, Metric) ->
|
|
|
+ Path = <<"/api/query">>,
|
|
|
+ Opts = #{return_all => true},
|
|
|
+ Body = #{
|
|
|
+ start => <<"1h-ago">>,
|
|
|
+ queries => [
|
|
|
+ #{
|
|
|
+ aggregator => <<"last">>,
|
|
|
+ metric => Metric,
|
|
|
+ tags => #{
|
|
|
+ host => <<"*">>
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ showTSUID => false,
|
|
|
+ showQuery => false,
|
|
|
+ delete => false
|
|
|
},
|
|
|
- ?assertMatch(
|
|
|
- {ok, _},
|
|
|
- create_bridge_http(OpentsConfig)
|
|
|
- ),
|
|
|
- SentData = make_data(),
|
|
|
- ?check_trace(
|
|
|
- begin
|
|
|
- Request = {send_message, SentData},
|
|
|
- Res0 = query_resource(Config, Request, 2_500),
|
|
|
- ?assertMatch(
|
|
|
- {ok, 200, #{failed := 0, success := 1}}, Res0
|
|
|
- ),
|
|
|
- ok
|
|
|
- end,
|
|
|
- fun(Trace0) ->
|
|
|
- Trace = ?of_kind(opents_connector_query_return, Trace0),
|
|
|
- ?assertMatch([#{result := {ok, 200, #{failed := 0, success := 1}}}], Trace),
|
|
|
- ok
|
|
|
- end
|
|
|
- ),
|
|
|
- ok.
|
|
|
-
|
|
|
-t_get_status(Config) ->
|
|
|
- ?assertMatch(
|
|
|
- {ok, _},
|
|
|
- create_bridge(Config)
|
|
|
- ),
|
|
|
-
|
|
|
- Name = ?config(opents_name, Config),
|
|
|
- BridgeType = ?config(opents_bridge_type, Config),
|
|
|
- ResourceID = emqx_bridge_resource:resource_id(BridgeType, Name),
|
|
|
+ opentsdb_request(Config, Path, Body, Opts).
|
|
|
|
|
|
- ?assertEqual({ok, connected}, emqx_resource_manager:health_check(ResourceID)),
|
|
|
- ok.
|
|
|
+opentsdb_request(Config, Path, Body) ->
|
|
|
+ opentsdb_request(Config, Path, Body, #{}).
|
|
|
|
|
|
-t_create_disconnected(Config) ->
|
|
|
- BridgeType = proplists:get_value(bridge_type, Config, <<"opents">>),
|
|
|
- Config1 = lists:keyreplace(opents_port, 1, Config, {opents_port, 61234}),
|
|
|
- {_Name, OpenTSConf} = opents_config(BridgeType, Config1),
|
|
|
+opentsdb_request(Config, Path, Body, Opts) ->
|
|
|
+ Host = ?config(bridge_host, Config),
|
|
|
+ Port = ?config(bridge_port, Config),
|
|
|
+ ServerURL = opents_server_url(Host, Port),
|
|
|
+ URL = <<ServerURL/binary, Path/binary>>,
|
|
|
+ emqx_mgmt_api_test_util:request_api(post, URL, [], [], Body, Opts).
|
|
|
|
|
|
- Config2 = lists:keyreplace(opents_config, 1, Config1, {opents_config, OpenTSConf}),
|
|
|
- ?assertMatch({ok, _}, create_bridge(Config2)),
|
|
|
-
|
|
|
- Name = ?config(opents_name, Config),
|
|
|
- ResourceID = emqx_bridge_resource:resource_id(BridgeType, Name),
|
|
|
- ?assertEqual({ok, disconnected}, emqx_resource_manager:health_check(ResourceID)),
|
|
|
- ok.
|
|
|
-
|
|
|
-t_write_failure(Config) ->
|
|
|
- ProxyName = ?config(proxy_name, Config),
|
|
|
- ProxyPort = ?config(proxy_port, Config),
|
|
|
- ProxyHost = ?config(proxy_host, Config),
|
|
|
- {ok, _} = create_bridge(Config),
|
|
|
- SentData = make_data(),
|
|
|
- emqx_common_test_helpers:with_failure(down, ProxyName, ProxyHost, ProxyPort, fun() ->
|
|
|
- {_, {ok, #{result := Result}}} =
|
|
|
- ?wait_async_action(
|
|
|
- send_message(Config, SentData),
|
|
|
- #{?snk_kind := buffer_worker_flush_ack},
|
|
|
- 2_000
|
|
|
- ),
|
|
|
- ?assertMatch({error, _}, Result),
|
|
|
- ok
|
|
|
- end),
|
|
|
- ok.
|
|
|
+make_data(Metric, Value) ->
|
|
|
+ #{
|
|
|
+ metric => Metric,
|
|
|
+ tags => #{
|
|
|
+ <<"host">> => <<"serverA">>
|
|
|
+ },
|
|
|
+ value => Value
|
|
|
+ }.
|
|
|
|
|
|
-t_write_timeout(Config) ->
|
|
|
- ProxyName = ?config(proxy_name, Config),
|
|
|
- ProxyPort = ?config(proxy_port, Config),
|
|
|
- ProxyHost = ?config(proxy_host, Config),
|
|
|
- {ok, _} = create_bridge(
|
|
|
- Config,
|
|
|
- #{
|
|
|
- <<"resource_opts">> => #{
|
|
|
- <<"request_ttl">> => <<"500ms">>,
|
|
|
- <<"resume_interval">> => <<"100ms">>,
|
|
|
- <<"health_check_interval">> => <<"100ms">>
|
|
|
- }
|
|
|
- }
|
|
|
- ),
|
|
|
- SentData = make_data(),
|
|
|
- emqx_common_test_helpers:with_failure(
|
|
|
- timeout, ProxyName, ProxyHost, ProxyPort, fun() ->
|
|
|
- ?assertMatch(
|
|
|
- {error, {resource_error, #{reason := timeout}}},
|
|
|
- query_resource(Config, {send_message, SentData})
|
|
|
- )
|
|
|
- end
|
|
|
- ),
|
|
|
- ok.
|
|
|
+%%------------------------------------------------------------------------------
|
|
|
+%% Testcases
|
|
|
+%%------------------------------------------------------------------------------
|
|
|
|
|
|
-t_missing_data(Config) ->
|
|
|
- ?assertMatch(
|
|
|
- {ok, _},
|
|
|
- create_bridge(Config)
|
|
|
+t_query_simple(Config) ->
|
|
|
+ Metric = <<"t_query_simple">>,
|
|
|
+ Value = 12,
|
|
|
+ MakeMessageFun = fun() -> make_data(Metric, Value) end,
|
|
|
+ ok = emqx_bridge_v2_testlib:t_sync_query(
|
|
|
+ Config, MakeMessageFun, fun is_success_check/1, opents_bridge_on_query
|
|
|
),
|
|
|
- {_, {ok, #{result := Result}}} =
|
|
|
- ?wait_async_action(
|
|
|
- send_message(Config, #{}),
|
|
|
- #{?snk_kind := buffer_worker_flush_ack},
|
|
|
- 2_000
|
|
|
- ),
|
|
|
+ {ok, {{_, 200, _}, _, IoTDBResult}} = opentds_query(Config, Metric),
|
|
|
+ QResult = emqx_utils_json:decode(IoTDBResult),
|
|
|
?assertMatch(
|
|
|
- {error, {400, #{failed := 1, success := 0}}},
|
|
|
- Result
|
|
|
+ [
|
|
|
+ #{
|
|
|
+ <<"metric">> := Metric,
|
|
|
+ <<"dps">> := _
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ QResult
|
|
|
),
|
|
|
- ok.
|
|
|
+ [#{<<"dps">> := Dps}] = QResult,
|
|
|
+ ?assertMatch([Value | _], maps:values(Dps)).
|
|
|
|
|
|
-t_bad_data(Config) ->
|
|
|
- ?assertMatch(
|
|
|
- {ok, _},
|
|
|
- create_bridge(Config)
|
|
|
- ),
|
|
|
- Data = maps:without([metric], make_data()),
|
|
|
- {_, {ok, #{result := Result}}} =
|
|
|
- ?wait_async_action(
|
|
|
- send_message(Config, Data),
|
|
|
- #{?snk_kind := buffer_worker_flush_ack},
|
|
|
- 2_000
|
|
|
- ),
|
|
|
+t_create_via_http(Config) ->
|
|
|
+ emqx_bridge_v2_testlib:t_create_via_http(Config).
|
|
|
|
|
|
- ?assertMatch(
|
|
|
- {error, {400, #{failed := 1, success := 0}}}, Result
|
|
|
- ),
|
|
|
- ok.
|
|
|
+t_start_stop(Config) ->
|
|
|
+ emqx_bridge_v2_testlib:t_start_stop(Config, opents_bridge_stopped).
|
|
|
|
|
|
-make_data() ->
|
|
|
- make_data(<<"cpu">>, 12).
|
|
|
+t_on_get_status(Config) ->
|
|
|
+ emqx_bridge_v2_testlib:t_on_get_status(Config, #{failure_status => connecting}).
|
|
|
|
|
|
-make_data(Metric, Value) ->
|
|
|
- #{
|
|
|
- metric => Metric,
|
|
|
- tags => #{
|
|
|
- <<"host">> => <<"serverA">>
|
|
|
- },
|
|
|
- value => Value
|
|
|
- }.
|
|
|
+t_query_invalid_data(Config) ->
|
|
|
+ Metric = <<"t_query_invalid_data">>,
|
|
|
+ Value = 12,
|
|
|
+ MakeMessageFun = fun() -> maps:remove(value, make_data(Metric, Value)) end,
|
|
|
+ ok = emqx_bridge_v2_testlib:t_sync_query(
|
|
|
+ Config, MakeMessageFun, fun is_error_check/1, opents_bridge_on_query
|
|
|
+ ).
|