emqx_flapping_SUITE.erl 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. %%--------------------------------------------------------------------
  2. %% Copyright (c) 2019-2023 EMQ Technologies Co., Ltd. All Rights Reserved.
  3. %%
  4. %% Licensed under the Apache License, Version 2.0 (the "License");
  5. %% you may not use this file except in compliance with the License.
  6. %% You may obtain a copy of the License at
  7. %%
  8. %% http://www.apache.org/licenses/LICENSE-2.0
  9. %%
  10. %% Unless required by applicable law or agreed to in writing, software
  11. %% distributed under the License is distributed on an "AS IS" BASIS,
  12. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. %% See the License for the specific language governing permissions and
  14. %% limitations under the License.
  15. %%--------------------------------------------------------------------
  16. -module(emqx_flapping_SUITE).
  17. -compile(export_all).
  18. -compile(nowarn_export_all).
  19. -include_lib("eunit/include/eunit.hrl").
  20. all() -> emqx_common_test_helpers:all(?MODULE).
  21. init_per_suite(Config) ->
  22. emqx_common_test_helpers:boot_modules(all),
  23. emqx_common_test_helpers:start_apps([]),
  24. %% update global default config
  25. {ok, _} = emqx:update_config(
  26. [flapping_detect],
  27. #{
  28. <<"enable">> => true,
  29. <<"max_count">> => 3,
  30. % 0.1s
  31. <<"window_time">> => <<"100ms">>,
  32. %% 2s
  33. <<"ban_time">> => <<"2s">>
  34. }
  35. ),
  36. Config.
  37. end_per_suite(_Config) ->
  38. emqx_common_test_helpers:stop_apps([]),
  39. %% Clean emqx_banned table
  40. mria_mnesia:delete_schema(),
  41. ok.
  42. t_detect_check(_) ->
  43. ClientInfo = #{
  44. zone => default,
  45. listener => {tcp, default},
  46. clientid => <<"client007">>,
  47. peerhost => {127, 0, 0, 1}
  48. },
  49. false = emqx_flapping:detect(ClientInfo),
  50. false = emqx_banned:check(ClientInfo),
  51. false = emqx_flapping:detect(ClientInfo),
  52. false = emqx_banned:check(ClientInfo),
  53. true = emqx_flapping:detect(ClientInfo),
  54. timer:sleep(50),
  55. ct:pal("the table emqx_banned: ~p, nowsec: ~p", [
  56. ets:tab2list(emqx_banned),
  57. erlang:system_time(second)
  58. ]),
  59. true = emqx_banned:check(ClientInfo),
  60. timer:sleep(3000),
  61. false = emqx_banned:check(ClientInfo),
  62. Children = supervisor:which_children(emqx_cm_sup),
  63. {emqx_flapping, Pid, _, _} = lists:keyfind(emqx_flapping, 1, Children),
  64. gen_server:call(Pid, unexpected_msg),
  65. gen_server:cast(Pid, unexpected_msg),
  66. Pid ! test,
  67. ok = emqx_flapping:stop().
  68. t_expired_detecting(_) ->
  69. ClientInfo = #{
  70. zone => default,
  71. listener => {tcp, default},
  72. clientid => <<"client008">>,
  73. peerhost => {127, 0, 0, 1}
  74. },
  75. false = emqx_flapping:detect(ClientInfo),
  76. ?assertEqual(
  77. true,
  78. lists:any(
  79. fun
  80. ({flapping, <<"client008">>, _, _, _}) -> true;
  81. (_) -> false
  82. end,
  83. ets:tab2list(emqx_flapping)
  84. )
  85. ),
  86. timer:sleep(200),
  87. ?assertEqual(
  88. true,
  89. lists:all(
  90. fun
  91. ({flapping, <<"client008">>, _, _, _}) -> false;
  92. (_) -> true
  93. end,
  94. ets:tab2list(emqx_flapping)
  95. )
  96. ).
  97. t_conf_update(_) ->
  98. Global = emqx_config:get([flapping_detect]),
  99. #{
  100. ban_time := _BanTime,
  101. enable := _Enable,
  102. max_count := _MaxCount,
  103. window_time := _WindowTime
  104. } = Global,
  105. emqx_config:put_zone_conf(new_zone, [flapping_detect], #{}),
  106. ?assertEqual(Global, get_policy(new_zone)),
  107. emqx_config:put_zone_conf(zone_1, [flapping_detect], #{window_time => 100}),
  108. ?assertEqual(Global#{window_time := 100}, emqx_flapping:get_policy(zone_1)),
  109. Zones = #{
  110. <<"zone_1">> => #{<<"flapping_detect">> => #{<<"window_time">> => <<"123s">>}},
  111. <<"zone_2">> => #{<<"flapping_detect">> => #{<<"window_time">> => <<"456s">>}}
  112. },
  113. ?assertMatch({ok, _}, emqx:update_config([zones], Zones)),
  114. %% new_zone is already deleted
  115. ?assertError({config_not_found, _}, get_policy(new_zone)),
  116. %% update zone(zone_1) has default.
  117. ?assertEqual(Global#{window_time := 123000}, emqx_flapping:get_policy(zone_1)),
  118. %% create zone(zone_2) has default
  119. ?assertEqual(Global#{window_time := 456000}, emqx_flapping:get_policy(zone_2)),
  120. %% reset to default(empty) andalso get default from global
  121. ?assertMatch({ok, _}, emqx:update_config([zones], #{})),
  122. ?assertEqual(Global, emqx:get_config([zones, default, flapping_detect])),
  123. ?assertError({config_not_found, _}, get_policy(zone_1)),
  124. ?assertError({config_not_found, _}, get_policy(zone_2)),
  125. ok.
  126. t_conf_update_timer(_Config) ->
  127. _ = emqx_flapping:start_link(),
  128. validate_timer([{default, true}]),
  129. %% change zones
  130. {ok, _} =
  131. emqx:update_config([zones], #{
  132. <<"timer_1">> => #{<<"flapping_detect">> => #{<<"enable">> => true}},
  133. <<"timer_2">> => #{<<"flapping_detect">> => #{<<"enable">> => true}},
  134. <<"timer_3">> => #{<<"flapping_detect">> => #{<<"enable">> => false}}
  135. }),
  136. validate_timer([{timer_1, true}, {timer_2, true}, {timer_3, false}, {default, true}]),
  137. %% change global flapping_detect
  138. Global = emqx:get_raw_config([flapping_detect]),
  139. {ok, _} = emqx:update_config([flapping_detect], Global#{<<"enable">> => false}),
  140. validate_timer([{timer_1, true}, {timer_2, true}, {timer_3, false}, {default, false}]),
  141. %% reset
  142. {ok, _} = emqx:update_config([flapping_detect], Global#{<<"enable">> => true}),
  143. validate_timer([{timer_1, true}, {timer_2, true}, {timer_3, false}, {default, true}]),
  144. ok.
  145. validate_timer(Lists) ->
  146. {Names, _} = lists:unzip(Lists),
  147. Zones = emqx:get_config([zones]),
  148. ?assertEqual(lists:sort(Names), lists:sort(maps:keys(Zones))),
  149. Timers = sys:get_state(emqx_flapping),
  150. maps:foreach(
  151. fun(Name, #{flapping_detect := #{enable := Enable}}) ->
  152. ?assertEqual(lists:keyfind(Name, 1, Lists), {Name, Enable}),
  153. ?assertEqual(Enable, is_reference(maps:get(Name, Timers)), Timers)
  154. end,
  155. Zones
  156. ),
  157. ?assertEqual(maps:keys(Zones), maps:keys(Timers)),
  158. ok.
  159. t_window_compatibility_check(_Conf) ->
  160. Flapping = emqx:get_raw_config([flapping_detect]),
  161. ok = emqx_config:init_load(emqx_schema, <<"flapping_detect {window_time = disable}">>),
  162. ?assertMatch(#{window_time := 60000, enable := false}, emqx:get_config([flapping_detect])),
  163. %% reset
  164. FlappingBin = iolist_to_binary(["flapping_detect {", hocon_pp:do(Flapping, #{}), "}"]),
  165. ok = emqx_config:init_load(emqx_schema, FlappingBin),
  166. ?assertEqual(Flapping, emqx:get_raw_config([flapping_detect])),
  167. ok.
  168. get_policy(Zone) ->
  169. emqx_config:get_zone_conf(Zone, [flapping_detect]).