diff --git a/.ci/docker-compose-file/docker-compose-iotdb.yaml b/.ci/docker-compose-file/docker-compose-iotdb.yaml index ec050b9ff..2a2b0e603 100644 --- a/.ci/docker-compose-file/docker-compose-iotdb.yaml +++ b/.ci/docker-compose-file/docker-compose-iotdb.yaml @@ -31,7 +31,7 @@ services: - emqx_bridge iotdb_0_13: - container_name: iotdb_0_13 + container_name: iotdb013 hostname: iotdb013 image: apache/iotdb:0.13.4-node restart: always @@ -48,7 +48,8 @@ services: - dn_schema_region_consensus_port=10750 - dn_data_region_consensus_port=10760 - dn_target_config_node_list=iotdb013:10710 - # volumes: + volumes: + - ./iotdb013/iotdb-rest.properties:/iotdb/conf/iotdb-rest.properties # - ./data:/iotdb/data # - ./logs:/iotdb/logs expose: diff --git a/.ci/docker-compose-file/docker-compose-toxiproxy.yaml b/.ci/docker-compose-file/docker-compose-toxiproxy.yaml index 88c2cb61a..f15e779db 100644 --- a/.ci/docker-compose-file/docker-compose-toxiproxy.yaml +++ b/.ci/docker-compose-file/docker-compose-toxiproxy.yaml @@ -46,6 +46,7 @@ services: # IOTDB - 14242:4242 - 28080:18080 + - 38080:38080 command: - "-host=0.0.0.0" - "-config=/config/toxiproxy.json" diff --git a/.ci/docker-compose-file/iotdb013/iotdb-rest.properties b/.ci/docker-compose-file/iotdb013/iotdb-rest.properties new file mode 100644 index 000000000..75d0ae1b0 --- /dev/null +++ b/.ci/docker-compose-file/iotdb013/iotdb-rest.properties @@ -0,0 +1,58 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +# + +#################### +### REST Service Configuration +#################### + +# Is the REST service enabled +enable_rest_service=true + +# the binding port of the REST service +# rest_service_port=18080 + +# the default row limit to a REST query response when the rowSize parameter is not given in request +# rest_query_default_row_size_limit=10000 + +# the expiration time of the user login information cache (in seconds) +# cache_expire_in_seconds=28800 + +# maximum number of users can be stored in the user login cache. +# cache_max_num=100 + +# init capacity of users can be stored in the user login cache. +# cache_init_num=10 + +# is SSL enabled +# enable_https=false + +# SSL key store path +# key_store_path= + +# SSL key store password +# key_store_pwd= + +# SSL trust store path +# trust_store_path= + +# SSL trust store password. +# trust_store_pwd= + +# SSL timeout (in seconds) +# idle_timeout_in_seconds=50000 diff --git a/apps/emqx_bridge_iotdb/test/emqx_bridge_iotdb_impl_SUITE.erl b/apps/emqx_bridge_iotdb/test/emqx_bridge_iotdb_impl_SUITE.erl index 0811807db..55d3743d4 100644 --- a/apps/emqx_bridge_iotdb/test/emqx_bridge_iotdb_impl_SUITE.erl +++ b/apps/emqx_bridge_iotdb/test/emqx_bridge_iotdb_impl_SUITE.erl @@ -6,6 +6,7 @@ -compile(nowarn_export_all). -compile(export_all). +-include("emqx_bridge_iotdb.hrl"). -include_lib("eunit/include/eunit.hrl"). -include_lib("common_test/include/ct.hrl"). -include_lib("snabbkaffe/include/snabbkaffe.hrl"). @@ -19,13 +20,15 @@ all() -> [ - {group, plain} + {group, plain}, + {group, legacy} ]. groups() -> AllTCs = emqx_common_test_helpers:all(?MODULE), [ - {plain, AllTCs} + {plain, AllTCs}, + {legacy, AllTCs} ]. init_per_suite(Config) -> @@ -44,7 +47,32 @@ init_per_group(plain = Type, Config0) -> [ {bridge_host, Host}, {bridge_port, Port}, - {proxy_name, ProxyName} + {proxy_name, ProxyName}, + {iotdb_version, ?VSN_1_1_X}, + {iotdb_rest_prefix, <<"/rest/v2/">>} + | Config + ]; + false -> + case os:getenv("IS_CI") of + "yes" -> + throw(no_iotdb); + _ -> + {skip, no_iotdb} + end + end; +init_per_group(legacy = Type, Config0) -> + Host = os:getenv("IOTDB_LEGACY_HOST", "toxiproxy.emqx.net"), + Port = list_to_integer(os:getenv("IOTDB_LEGACY_PORT", "38080")), + ProxyName = "iotdb013", + case emqx_common_test_helpers:is_tcp_server_available(Host, Port) of + true -> + Config = emqx_bridge_testlib:init_per_group(Type, ?BRIDGE_TYPE_BIN, Config0), + [ + {bridge_host, Host}, + {bridge_port, Port}, + {proxy_name, ProxyName}, + {iotdb_version, ?VSN_0_13_X}, + {iotdb_rest_prefix, <<"/rest/v1/">>} | Config ]; false -> @@ -59,7 +87,8 @@ init_per_group(_Group, Config) -> Config. end_per_group(Group, Config) when - Group =:= plain + Group =:= plain; + Group =:= legacy -> emqx_bridge_testlib:end_per_group(Config), ok; @@ -89,6 +118,7 @@ bridge_config(TestCase, _TestGroup, Config) -> UniqueNum = integer_to_binary(erlang:unique_integer()), Host = ?config(bridge_host, Config), Port = ?config(bridge_port, Config), + Version = ?config(iotdb_version, Config), Name = << (atom_to_binary(TestCase))/binary, UniqueNum/binary >>, @@ -102,6 +132,7 @@ bridge_config(TestCase, _TestGroup, Config) -> " username = \"root\"\n" " password = \"root\"\n" " }\n" + "iotdb_version = \"~s\"\n" " pool_size = 1\n" " resource_opts = {\n" " auto_restart_interval = 5000\n" @@ -112,7 +143,8 @@ bridge_config(TestCase, _TestGroup, Config) -> "}\n", [ Name, - ServerURL + ServerURL, + Version ] ), {Name, ConfigString, emqx_bridge_testlib:parse_and_check(Config, ConfigString, Name)}. @@ -182,11 +214,13 @@ iotdb_reset(Config) -> iotdb_reset(Config, Device). iotdb_reset(Config, Device) -> + Prefix = ?config(iotdb_rest_prefix, Config), Body = #{sql => <<"delete from ", Device/binary, ".*">>}, - {ok, _} = iotdb_request(Config, <<"/rest/v2/nonQuery">>, Body). + {ok, _} = iotdb_request(Config, <>, Body). iotdb_query(Config, Query) -> - Path = <<"/rest/v2/query">>, + Prefix = ?config(iotdb_rest_prefix, Config), + Path = <>, Opts = #{return_all => true}, Body = #{sql => Query}, iotdb_request(Config, Path, Body, Opts). @@ -390,11 +424,13 @@ t_device_id(Config) -> emqx_resource:simple_sync_query(ResourceId, {send_message, MessageF1()}) ), {ok, {{_, 200, _}, _, Res1_1}} = iotdb_query(Config, <<"select * from ", DeviceId/binary>>), + ct:pal("device_id result: ~p", [emqx_utils_json:decode(Res1_1)]), #{<<"values">> := Values1_1} = emqx_utils_json:decode(Res1_1), - ?assertNotEqual([], Values1_1), + ?assertNot(is_empty(Values1_1)), {ok, {{_, 200, _}, _, Res1_2}} = iotdb_query(Config, <<"select * from ", TopicDevice/binary>>), + ct:pal("topic device result: ~p", [emqx_utils_json:decode(Res1_2)]), #{<<"values">> := Values1_2} = emqx_utils_json:decode(Res1_2), - ?assertEqual([], Values1_2), + ?assert(is_empty(Values1_2)), %% test without device_id in message, taking it from topic iotdb_reset(Config, DeviceId), @@ -407,10 +443,10 @@ t_device_id(Config) -> ), {ok, {{_, 200, _}, _, Res2_1}} = iotdb_query(Config, <<"select * from ", DeviceId/binary>>), #{<<"values">> := Values2_1} = emqx_utils_json:decode(Res2_1), - ?assertEqual([], Values2_1), + ?assert(is_empty(Values2_1)), {ok, {{_, 200, _}, _, Res2_2}} = iotdb_query(Config, <<"select * from ", TopicDevice/binary>>), #{<<"values">> := Values2_2} = emqx_utils_json:decode(Res2_2), - ?assertNotEqual([], Values2_2), + ?assertNot(is_empty(Values2_2)), iotdb_reset(Config, DeviceId), iotdb_reset(Config, TopicDevice), @@ -427,17 +463,22 @@ t_device_id(Config) -> %% even though we had a device_id in the message it's not being used {ok, {{_, 200, _}, _, Res3_1}} = iotdb_query(Config, <<"select * from ", DeviceId/binary>>), #{<<"values">> := Values3_1} = emqx_utils_json:decode(Res3_1), - ?assertEqual([], Values3_1), + ?assert(is_empty(Values3_1)), {ok, {{_, 200, _}, _, Res3_2}} = iotdb_query(Config, <<"select * from ", TopicDevice/binary>>), #{<<"values">> := Values3_2} = emqx_utils_json:decode(Res3_2), - ?assertEqual([], Values3_2), + ?assert(is_empty(Values3_2)), {ok, {{_, 200, _}, _, Res3_3}} = iotdb_query( Config, <<"select * from ", ConfiguredDevice/binary>> ), #{<<"values">> := Values3_3} = emqx_utils_json:decode(Res3_3), - ?assertNotEqual([], Values3_3), + ?assertNot(is_empty(Values3_3)), iotdb_reset(Config, DeviceId), iotdb_reset(Config, TopicDevice), iotdb_reset(Config, ConfiguredDevice), ok. + +is_empty(null) -> true; +is_empty([]) -> true; +is_empty([[]]) -> true; +is_empty(_) -> false.