|
|
@@ -31,6 +31,8 @@
|
|
|
|
|
|
-define(SHARD, shard(?FUNCTION_NAME)).
|
|
|
|
|
|
+-define(LTS_THRESHOLD, {simple, {20, 10}}).
|
|
|
+
|
|
|
-define(DB_CONFIG(CONFIG), #{
|
|
|
backend => builtin_local,
|
|
|
storage => ?config(layout, CONFIG),
|
|
|
@@ -47,9 +49,14 @@ init_per_group(Group, Config) ->
|
|
|
LayoutConf =
|
|
|
case Group of
|
|
|
reference ->
|
|
|
- {emqx_ds_storage_reference, #{}};
|
|
|
+ {emqx_ds_storage_reference, #{
|
|
|
+ lts_threshold_spec => ?LTS_THRESHOLD
|
|
|
+ }};
|
|
|
skipstream_lts ->
|
|
|
- {emqx_ds_storage_skipstream_lts, #{with_guid => true}};
|
|
|
+ {emqx_ds_storage_skipstream_lts, #{
|
|
|
+ with_guid => true,
|
|
|
+ lts_threshold_spec => ?LTS_THRESHOLD
|
|
|
+ }};
|
|
|
bitfield_lts ->
|
|
|
{emqx_ds_storage_bitfield_lts, #{}}
|
|
|
end,
|
|
|
@@ -292,6 +299,44 @@ t_replay(Config) ->
|
|
|
?assert(check(?SHARD, <<"#">>, 0, Messages)),
|
|
|
ok.
|
|
|
|
|
|
+t_replay_special_topics(_Config) ->
|
|
|
+ %% Verify that topic matching rules respect [MQTT-4.7.2-1]:
|
|
|
+ %% The Server MUST NOT match Topic Filters starting with a wildcard character (# or +)
|
|
|
+ %% with Topic Names beginning with a $ character.
|
|
|
+ {Values1, Values2} = lists:split(5, lists:seq(0, 1000, 100)),
|
|
|
+ STopic1 = <<"$SPECIAL/test/1/2">>,
|
|
|
+ ELTopic = <<"/test/">>,
|
|
|
+ Topics1 = [<<"g/test/1">>, <<"g/test/2">>, <<"/test/">>],
|
|
|
+ SBatch1 = [make_message(V, STopic1, bin(V)) || V <- Values1],
|
|
|
+ Batch1 = [make_message(V, Topic, bin(V)) || Topic <- Topics1, V <- Values1],
|
|
|
+ ok = emqx_ds:store_batch(?FUNCTION_NAME, SBatch1 ++ Batch1),
|
|
|
+ %% Expect special topic messages to show up only in `$SPECIAL/test/#` subscription:
|
|
|
+ ?assert(check(?SHARD, <<"$SPECIAL/test/#">>, 0, SBatch1)),
|
|
|
+ %% ...But not in an otherwise fitting wildcard subscriptions:
|
|
|
+ ?assert(check(?SHARD, <<"+/test/#">>, 0, Batch1)),
|
|
|
+ check(?SHARD, <<"+/test/+/+">>, 0, []),
|
|
|
+ %% ...And not in different special roots:
|
|
|
+ check(?SHARD, <<"$SYS/test/#">>, 0, []),
|
|
|
+ %% Publish through a lot of similarly structured topic to let LTS "learn":
|
|
|
+ STopic2 = <<"$SPECIAL/test/3/4">>,
|
|
|
+ Topics2 = [emqx_utils:format("~p/test/~p", [I, I]) || I <- lists:seq(1, 40)],
|
|
|
+ Batch2 = [make_message(V, Topic, bin(V)) || Topic <- Topics2 ++ [ELTopic], V <- Values2],
|
|
|
+ ok = emqx_ds:store_batch(?FUNCTION_NAME, Batch2),
|
|
|
+ SBatch2 = [make_message(V, STopic2, bin(V)) || V <- Values2],
|
|
|
+ ok = emqx_ds:store_batch(?FUNCTION_NAME, SBatch2),
|
|
|
+ %% ...Then verify the same things:
|
|
|
+ ?assert(check(?SHARD, <<"$SPECIAL/test/#">>, 0, SBatch1 ++ SBatch2)),
|
|
|
+ ?assert(check(?SHARD, <<"$SPECIAL/test/+/4">>, 0, SBatch2)),
|
|
|
+ ?assert(check(?SHARD, <<"+/test/#">>, 0, Batch1 ++ Batch2)),
|
|
|
+ check(?SHARD, <<"+/test/+/+">>, 0, SBatch2),
|
|
|
+ %% Also verify that having a lot of different $-roots does not break things:
|
|
|
+ STopics = [emqx_utils:format("$T~p/test/~p", [I, I]) || I <- lists:seq(1, 40)],
|
|
|
+ SBatch3 = [make_message(V, T, bin(V)) || T <- STopics, V <- Values2],
|
|
|
+ ok = emqx_ds:store_batch(?FUNCTION_NAME, SBatch3),
|
|
|
+ ?assert(check(?SHARD, <<"$T1/test/#">>, 0, SBatch3)),
|
|
|
+ ?assert(check(?SHARD, <<"+/test/#">>, 0, Batch1 ++ Batch2)),
|
|
|
+ check(?SHARD, <<"$SYS/test/#">>, 0, []).
|
|
|
+
|
|
|
%% This testcase verifies poll functionality that doesn't involve events:
|
|
|
t_poll(Config) ->
|
|
|
?check_trace(
|