|
|
@@ -37,6 +37,7 @@ all() ->
|
|
|
, {group, runtime}
|
|
|
, {group, events}
|
|
|
, {group, multi_actions}
|
|
|
+ , {group, bugs}
|
|
|
].
|
|
|
|
|
|
suite() ->
|
|
|
@@ -123,11 +124,15 @@ groups() ->
|
|
|
{events, [],
|
|
|
[t_events
|
|
|
]},
|
|
|
+ {bugs, [],
|
|
|
+ [t_sqlparse_payload_as
|
|
|
+ ]},
|
|
|
{multi_actions, [],
|
|
|
[t_sqlselect_multi_actoins_1,
|
|
|
t_sqlselect_multi_actoins_1_1,
|
|
|
t_sqlselect_multi_actoins_2,
|
|
|
t_sqlselect_multi_actoins_3,
|
|
|
+ t_sqlselect_multi_actoins_3_1,
|
|
|
t_sqlselect_multi_actoins_4
|
|
|
]}
|
|
|
].
|
|
|
@@ -200,6 +205,7 @@ init_per_testcase(Test, Config)
|
|
|
;Test =:= t_sqlselect_multi_actoins_1_1
|
|
|
;Test =:= t_sqlselect_multi_actoins_2
|
|
|
;Test =:= t_sqlselect_multi_actoins_3
|
|
|
+ ;Test =:= t_sqlselect_multi_actoins_3_1
|
|
|
;Test =:= t_sqlselect_multi_actoins_4
|
|
|
->
|
|
|
ok = emqx_rule_engine:load_providers(),
|
|
|
@@ -209,6 +215,12 @@ init_per_testcase(Test, Config)
|
|
|
types=[], params_spec = #{},
|
|
|
title = #{en => <<"Crash Action">>},
|
|
|
description = #{en => <<"This action will always fail!">>}}),
|
|
|
+ ok = emqx_rule_registry:add_action(
|
|
|
+ #action{name = 'failure_action', app = ?APP,
|
|
|
+ module = ?MODULE, on_create = failure_action,
|
|
|
+ types=[], params_spec = #{},
|
|
|
+ title = #{en => <<"Crash Action">>},
|
|
|
+ description = #{en => <<"This action will always fail!">>}}),
|
|
|
ok = emqx_rule_registry:add_action(
|
|
|
#action{name = 'plus_by_one', app = ?APP,
|
|
|
module = ?MODULE, on_create = plus_by_one_action,
|
|
|
@@ -1288,6 +1300,44 @@ t_sqlselect_multi_actoins_3(Config) ->
|
|
|
|
|
|
emqx_rule_registry:remove_rule(Rule).
|
|
|
|
|
|
+t_sqlselect_multi_actoins_3_1(Config) ->
|
|
|
+ %% We create 2 actions in the same rule (on_action_failed = continue):
|
|
|
+ %% The first will fail (with a 'badact' return) and we need to make sure the
|
|
|
+ %% fallback actions can be executed, and the next actoins
|
|
|
+ %% will be run without influence
|
|
|
+ {ok, Rule} = emqx_rule_engine:create_rule(
|
|
|
+ #{rawsql => ?config(connsql, Config),
|
|
|
+ on_action_failed => continue,
|
|
|
+ actions => [
|
|
|
+ #{name => 'failure_action', args => #{}, fallbacks =>[
|
|
|
+ #{name => 'plus_by_one', args => #{}, fallbacks =>[]},
|
|
|
+ #{name => 'plus_by_one', args => #{}, fallbacks =>[]}
|
|
|
+ ]},
|
|
|
+ #{name => 'republish',
|
|
|
+ args => #{<<"target_topic">> => <<"t2">>,
|
|
|
+ <<"target_qos">> => -1,
|
|
|
+ <<"payload_tmpl">> => <<"clientid=${clientid}">>
|
|
|
+ },
|
|
|
+ fallbacks => []}
|
|
|
+ ]
|
|
|
+ }),
|
|
|
+
|
|
|
+ (?config(conn_event, Config))(),
|
|
|
+ timer:sleep(100),
|
|
|
+
|
|
|
+ %% verfiy the fallback actions has been run
|
|
|
+ ?assertEqual(2, ets:lookup_element(plus_by_one_action, num, 2)),
|
|
|
+
|
|
|
+ %% verfiy the next actions can be run
|
|
|
+ receive {publish, #{topic := T, payload := Payload}} ->
|
|
|
+ ?assertEqual(<<"t2">>, T),
|
|
|
+ ?assertEqual(<<"clientid=c_emqx1">>, Payload)
|
|
|
+ after 1000 ->
|
|
|
+ ct:fail(wait_for_t2)
|
|
|
+ end,
|
|
|
+
|
|
|
+ emqx_rule_registry:remove_rule(Rule).
|
|
|
+
|
|
|
t_sqlselect_multi_actoins_4(Config) ->
|
|
|
%% We create 2 actions in the same rule (on_action_failed = continue):
|
|
|
%% The first will fail and we need to make sure the
|
|
|
@@ -1920,6 +1970,44 @@ t_sqlparse_new_map(_Config) ->
|
|
|
<<"c">> := [#{}]
|
|
|
}, Res00).
|
|
|
|
|
|
+t_sqlparse_payload_as(_Config) ->
|
|
|
+ %% https://github.com/emqx/emqx/issues/3866
|
|
|
+ Sql00 = "SELECT "
|
|
|
+ " payload, map_get('engineWorkTime', payload.params, -1) as payload.params.engineWorkTime, "
|
|
|
+ " map_get('hydOilTem', payload.params, -1) as payload.params.hydOilTem "
|
|
|
+ "FROM \"t/#\" ",
|
|
|
+ Payload1 = <<"{ \"msgId\": 1002, \"params\": { \"convertTemp\": 20, \"engineSpeed\": 42, \"hydOilTem\": 30 } }">>,
|
|
|
+ {ok, Res01} = emqx_rule_sqltester:test(
|
|
|
+ #{<<"rawsql">> => Sql00,
|
|
|
+ <<"ctx">> => #{<<"payload">> => Payload1,
|
|
|
+ <<"topic">> => <<"t/a">>}}),
|
|
|
+ ?assertMatch(#{
|
|
|
+ <<"payload">> := #{
|
|
|
+ <<"params">> := #{
|
|
|
+ <<"convertTemp">> := 20,
|
|
|
+ <<"engineSpeed">> := 42,
|
|
|
+ <<"engineWorkTime">> := -1,
|
|
|
+ <<"hydOilTem">> := 30
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }, Res01),
|
|
|
+
|
|
|
+ Payload2 = <<"{ \"msgId\": 1002, \"params\": { \"convertTemp\": 20, \"engineSpeed\": 42 } }">>,
|
|
|
+ {ok, Res02} = emqx_rule_sqltester:test(
|
|
|
+ #{<<"rawsql">> => Sql00,
|
|
|
+ <<"ctx">> => #{<<"payload">> => Payload2,
|
|
|
+ <<"topic">> => <<"t/a">>}}),
|
|
|
+ ?assertMatch(#{
|
|
|
+ <<"payload">> := #{
|
|
|
+ <<"params">> := #{
|
|
|
+ <<"convertTemp">> := 20,
|
|
|
+ <<"engineSpeed">> := 42,
|
|
|
+ <<"engineWorkTime">> := -1,
|
|
|
+ <<"hydOilTem">> := -1
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }, Res02).
|
|
|
+
|
|
|
%%------------------------------------------------------------------------------
|
|
|
%% Internal helpers
|
|
|
%%------------------------------------------------------------------------------
|
|
|
@@ -2006,6 +2094,12 @@ mfa_action(Id, _Params) ->
|
|
|
mfa_action_do(_Data, _Envs, K) ->
|
|
|
persistent_term:put(K, 1).
|
|
|
|
|
|
+failure_action(_Id, _Params) ->
|
|
|
+ fun(Data, _Envs) ->
|
|
|
+ ct:pal("applying crash action, Data: ~p", [Data]),
|
|
|
+ {badact, intentional_failure}
|
|
|
+ end.
|
|
|
+
|
|
|
crash_action(_Id, _Params) ->
|
|
|
fun(Data, _Envs) ->
|
|
|
ct:pal("applying crash action, Data: ~p", [Data]),
|