Pārlūkot izejas kodu

fix(topic): respect special topic rules when intersecting

Andrew Mayorov 1 gadu atpakaļ
vecāks
revīzija
24be189728
2 mainītis faili ar 24 papildinājumiem un 1 dzēšanām
  1. 8 1
      apps/emqx/src/emqx_topic.erl
  2. 16 0
      apps/emqx/test/emqx_topic_SUITE.erl

+ 8 - 1
apps/emqx/src/emqx_topic.erl

@@ -111,11 +111,18 @@ match(_, _) ->
 -spec intersection(TopicOrFilter, TopicOrFilter) -> TopicOrFilter | false when
     TopicOrFilter :: emqx_types:topic().
 intersection(Topic1, Topic2) when is_binary(Topic1), is_binary(Topic2) ->
-    case intersection(words(Topic1), words(Topic2), []) of
+    case intersect_start(words(Topic1), words(Topic2)) of
         [] -> false;
         Intersection -> join(lists:reverse(Intersection))
     end.
 
+intersect_start([<<"$", _/bytes>> | _], [W | _]) when ?IS_WILDCARD(W) ->
+    [];
+intersect_start([W | _], [<<"$", _/bytes>> | _]) when ?IS_WILDCARD(W) ->
+    [];
+intersect_start(Words1, Words2) ->
+    intersection(Words1, Words2, []).
+
 intersection(Words1, ['#'], Acc) ->
     lists:reverse(Words1, Acc);
 intersection(['#'], Words2, Acc) ->

+ 16 - 0
apps/emqx/test/emqx_topic_SUITE.erl

@@ -28,6 +28,7 @@
     [
         wildcard/1,
         match/2,
+        intersection/2,
         validate/1,
         prepend/2,
         join/1,
@@ -128,6 +129,21 @@ t_match_perf(_) ->
     true = match(Name, Filter),
     ok = bench('match/2', fun emqx_topic:match/2, [Name, Filter]).
 
+t_intersect(_) ->
+    <<"t/global/1/+">> = intersection(<<"t/global/#">>, <<"t/+/1/+">>),
+    <<"t/global/#">> = intersection(<<"t/global/#">>, <<"#">>),
+    <<"t/global/#">> = intersection(<<"t/global/#">>, <<"t/global/#">>),
+    <<"1/2/3/4/5">> = intersection(<<"1/+/3/+/5/#">>, <<"+/2/+/4/+">>),
+    <<"t/local/1">> = intersection(<<"t/local/1/#">>, <<"t/local/+">>),
+    false = intersection(<<"t/global/#">>, <<"t/local/+">>),
+    false = intersection(<<"t/local/1/+">>, <<"t/local/+">>).
+
+t_sys_intersect(_) ->
+    <<"$SYS/broker/+">> = intersection(<<"$SYS/broker/#">>, <<"$SYS/+/+">>),
+    <<"$SYS/broker">> = intersection(<<"$SYS/broker">>, <<"$SYS/+">>),
+    false = intersection(<<"$SYS/broker">>, <<"+/+">>),
+    false = intersection(<<"$SYS/broker">>, <<"#">>).
+
 t_validate(_) ->
     true = validate(<<"a/+/#">>),
     true = validate(<<"a/b/c/d">>),