fix: rule SQL mongo_date function should return a string in test mode
The rule SQL mongo_date function should return a string with the format ISODate(*), where * is an ISO date string when running the rule in test mode. Fixes: https://emqx.atlassian.net/browse/EMQX-10727
This commit is contained in:
parent
2b03436552
commit
3ed031db70
|
@ -2,7 +2,7 @@
|
|||
{application, emqx_rule_engine, [
|
||||
{description, "EMQX Rule Engine"},
|
||||
% strict semver, bump manually!
|
||||
{vsn, "5.0.22"},
|
||||
{vsn, "5.0.23"},
|
||||
{modules, []},
|
||||
{registered, [emqx_rule_engine_sup, emqx_rule_engine]},
|
||||
{applications, [kernel, stdlib, rulesql, getopt, emqx_ctl, uuid]},
|
||||
|
|
|
@ -1185,16 +1185,31 @@ function_literal(Fun, Args) ->
|
|||
{invalid_func, {Fun, Args}}.
|
||||
|
||||
mongo_date() ->
|
||||
erlang:timestamp().
|
||||
maybe_isodate_format(erlang:timestamp()).
|
||||
|
||||
mongo_date(MillisecondsTimestamp) ->
|
||||
convert_timestamp(MillisecondsTimestamp).
|
||||
maybe_isodate_format(convert_timestamp(MillisecondsTimestamp)).
|
||||
|
||||
mongo_date(Timestamp, Unit) ->
|
||||
InsertedTimeUnit = time_unit(Unit),
|
||||
ScaledEpoch = erlang:convert_time_unit(Timestamp, InsertedTimeUnit, millisecond),
|
||||
convert_timestamp(ScaledEpoch).
|
||||
|
||||
maybe_isodate_format(ErlTimestamp) ->
|
||||
case emqx_rule_sqltester:is_test_runtime_env() of
|
||||
false ->
|
||||
ErlTimestamp;
|
||||
true ->
|
||||
%% if this is called from sqltest, we need to convert it to the ISODate() format,
|
||||
%% so that it can be correctly converted into a JSON string.
|
||||
isodate_format(ErlTimestamp)
|
||||
end.
|
||||
|
||||
isodate_format({MegaSecs, Secs, MicroSecs}) ->
|
||||
SystemTimeMs = (MegaSecs * 1000_000_000_000 + Secs * 1000_000 + MicroSecs) div 1000,
|
||||
Ts3339Str = calendar:system_time_to_rfc3339(SystemTimeMs, [{unit, millisecond}, {offset, "Z"}]),
|
||||
iolist_to_binary(["ISODate(", Ts3339Str, ")"]).
|
||||
|
||||
convert_timestamp(MillisecondsTimestamp) ->
|
||||
MicroTimestamp = MillisecondsTimestamp * 1000,
|
||||
MegaSecs = MicroTimestamp div 1000_000_000_000,
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
|
||||
-export([
|
||||
test/1,
|
||||
get_selected_data/3
|
||||
get_selected_data/3,
|
||||
%% Some SQL functions return different results in the test environment
|
||||
is_test_runtime_env/0
|
||||
]).
|
||||
|
||||
-spec test(#{sql := binary(), context := map()}) -> {ok, map() | list()} | {error, term()}.
|
||||
|
@ -63,12 +65,14 @@ test_rule(Sql, Select, Context, EventTopics) ->
|
|||
created_at => erlang:system_time(millisecond)
|
||||
},
|
||||
FullContext = fill_default_values(hd(EventTopics), emqx_rule_maps:atom_key_map(Context)),
|
||||
set_is_test_runtime_env(),
|
||||
try emqx_rule_runtime:apply_rule(Rule, FullContext, #{}) of
|
||||
{ok, Data} ->
|
||||
{ok, flatten(Data)};
|
||||
{error, Reason} ->
|
||||
{error, Reason}
|
||||
after
|
||||
unset_is_test_runtime_env(),
|
||||
ok = emqx_rule_engine:clear_metrics_for_rule(RuleId)
|
||||
end.
|
||||
|
||||
|
@ -97,3 +101,20 @@ envs_examp(EventTopic) ->
|
|||
emqx_rule_events:columns_with_exam(EventName)
|
||||
)
|
||||
).
|
||||
|
||||
is_test_runtime_env_atom() ->
|
||||
'emqx_rule_sqltester:is_test_runtime_env'.
|
||||
|
||||
set_is_test_runtime_env() ->
|
||||
erlang:put(is_test_runtime_env_atom(), true),
|
||||
ok.
|
||||
|
||||
unset_is_test_runtime_env() ->
|
||||
erlang:erase(is_test_runtime_env_atom()),
|
||||
ok.
|
||||
|
||||
is_test_runtime_env() ->
|
||||
case erlang:get(is_test_runtime_env_atom()) of
|
||||
true -> true;
|
||||
_ -> false
|
||||
end.
|
||||
|
|
|
@ -214,6 +214,27 @@ t_ctx_delivery_dropped(_) ->
|
|||
Expected = check_result([from_clientid, from_username, reason, qos, topic], [], Context),
|
||||
do_test(SQL, Context, Expected).
|
||||
|
||||
t_mongo_date_function_should_return_string_in_test_env(_) ->
|
||||
SQL =
|
||||
<<"SELECT mongo_date() as mongo_date FROM \"t/1\"">>,
|
||||
Context =
|
||||
#{
|
||||
action => <<"publish">>,
|
||||
clientid => <<"c_emqx">>,
|
||||
event_type => client_check_authz_complete,
|
||||
result => <<"allow">>,
|
||||
topic => <<"t/1">>,
|
||||
username => <<"u_emqx">>
|
||||
},
|
||||
CheckFunction = fun(Result) ->
|
||||
MongoDate = maps:get(mongo_date, Result),
|
||||
%% Use regex to match the expected string
|
||||
MatchResult = re:run(MongoDate, <<"ISODate\\([0-9]{4}-[0-9]{2}-[0-9]{2}T.*\\)">>),
|
||||
?assertMatch({match, _}, MatchResult),
|
||||
ok
|
||||
end,
|
||||
do_test(SQL, Context, CheckFunction).
|
||||
|
||||
do_test(SQL, Context, Expected0) ->
|
||||
Res = emqx_rule_engine_api:'/rule_test'(
|
||||
post,
|
||||
|
|
Loading…
Reference in New Issue