emqx_flapping_SUITE.erl 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. %%--------------------------------------------------------------------
  2. %% Copyright (c) 2019-2024 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. -include_lib("common_test/include/ct.hrl").
  21. all() -> emqx_common_test_helpers:all(?MODULE).
  22. init_per_suite(Config) ->
  23. Apps = emqx_cth_suite:start(
  24. [
  25. {emqx,
  26. "flapping_detect {"
  27. "\n enable = true"
  28. "\n max_count = 3"
  29. "\n window_time = 100ms"
  30. "\n ban_time = 2s"
  31. "\n }"}
  32. ],
  33. #{work_dir => emqx_cth_suite:work_dir(Config)}
  34. ),
  35. [{suite_apps, Apps} | Config].
  36. end_per_suite(Config) ->
  37. emqx_cth_suite:stop(?config(suite_apps, Config)).
  38. t_detect_check(_) ->
  39. ClientInfo = #{
  40. zone => default,
  41. listener => {tcp, default},
  42. clientid => <<"client007">>,
  43. peerhost => {127, 0, 0, 1}
  44. },
  45. false = emqx_flapping:detect(ClientInfo),
  46. false = emqx_banned:check(ClientInfo),
  47. false = emqx_flapping:detect(ClientInfo),
  48. false = emqx_banned:check(ClientInfo),
  49. true = emqx_flapping:detect(ClientInfo),
  50. timer:sleep(50),
  51. ct:pal("the table emqx_banned: ~p, nowsec: ~p", [
  52. ets:tab2list(emqx_banned),
  53. erlang:system_time(second)
  54. ]),
  55. true = emqx_banned:check(ClientInfo),
  56. timer:sleep(3000),
  57. false = emqx_banned:check(ClientInfo),
  58. Children = supervisor:which_children(emqx_cm_sup),
  59. {emqx_flapping, Pid, _, _} = lists:keyfind(emqx_flapping, 1, Children),
  60. gen_server:call(Pid, unexpected_msg),
  61. gen_server:cast(Pid, unexpected_msg),
  62. Pid ! test,
  63. ok = emqx_flapping:stop().
  64. t_expired_detecting(_) ->
  65. ClientInfo = #{
  66. zone => default,
  67. listener => {tcp, default},
  68. clientid => <<"client008">>,
  69. peerhost => {127, 0, 0, 1}
  70. },
  71. false = emqx_flapping:detect(ClientInfo),
  72. ?assertEqual(
  73. true,
  74. lists:any(
  75. fun
  76. ({flapping, <<"client008">>, _, _, _}) -> true;
  77. (_) -> false
  78. end,
  79. ets:tab2list(emqx_flapping)
  80. )
  81. ),
  82. timer:sleep(200),
  83. ?assertEqual(
  84. true,
  85. lists:all(
  86. fun
  87. ({flapping, <<"client008">>, _, _, _}) -> false;
  88. (_) -> true
  89. end,
  90. ets:tab2list(emqx_flapping)
  91. )
  92. ).
  93. t_conf_update(_) ->
  94. Global = emqx_config:get([flapping_detect]),
  95. #{
  96. ban_time := _BanTime,
  97. enable := _Enable,
  98. max_count := _MaxCount,
  99. window_time := _WindowTime
  100. } = Global,
  101. emqx_config:put_zone_conf(new_zone, [flapping_detect], #{}),
  102. ?assertEqual(Global, get_policy(new_zone)),
  103. emqx_config:put_zone_conf(zone_1, [flapping_detect], #{window_time => 100}),
  104. ?assertEqual(Global#{window_time := 100}, emqx_flapping:get_policy(zone_1)),
  105. Zones = #{
  106. <<"zone_1">> => #{<<"flapping_detect">> => #{<<"window_time">> => <<"123s">>}},
  107. <<"zone_2">> => #{<<"flapping_detect">> => #{<<"window_time">> => <<"456s">>}}
  108. },
  109. ?assertMatch({ok, _}, emqx:update_config([zones], Zones)),
  110. %% new_zone is already deleted
  111. ?assertError({config_not_found, _}, get_policy(new_zone)),
  112. %% update zone(zone_1) has default.
  113. ?assertEqual(Global#{window_time := 123000}, emqx_flapping:get_policy(zone_1)),
  114. %% create zone(zone_2) has default
  115. ?assertEqual(Global#{window_time := 456000}, emqx_flapping:get_policy(zone_2)),
  116. %% reset to default(empty) andalso get default from global
  117. ?assertMatch({ok, _}, emqx:update_config([zones], #{})),
  118. ?assertEqual(Global, emqx:get_config([zones, default, flapping_detect])),
  119. ?assertError({config_not_found, _}, get_policy(zone_1)),
  120. ?assertError({config_not_found, _}, get_policy(zone_2)),
  121. ok.
  122. t_conf_update_timer(_Config) ->
  123. %% delete all zones
  124. ?assertMatch({ok, _}, emqx:update_config([zones], #{})),
  125. emqx_cm_sup:restart_flapping(),
  126. validate_timer([{default, true}]),
  127. %% change zones
  128. {ok, _} =
  129. emqx:update_config([zones], #{
  130. <<"timer_1">> => #{<<"flapping_detect">> => #{<<"enable">> => true}},
  131. <<"timer_2">> => #{<<"flapping_detect">> => #{<<"enable">> => true}},
  132. <<"timer_3">> => #{<<"flapping_detect">> => #{<<"enable">> => false}}
  133. }),
  134. validate_timer([{timer_1, true}, {timer_2, true}, {timer_3, false}, {default, true}]),
  135. %% change global flapping_detect
  136. Global = emqx:get_raw_config([flapping_detect]),
  137. {ok, _} = emqx:update_config([flapping_detect], Global#{<<"enable">> => false}),
  138. validate_timer([{timer_1, true}, {timer_2, true}, {timer_3, false}, {default, false}]),
  139. %% reset
  140. {ok, _} = emqx:update_config([flapping_detect], Global#{<<"enable">> => true}),
  141. validate_timer([{timer_1, true}, {timer_2, true}, {timer_3, false}, {default, true}]),
  142. ok.
  143. validate_timer(Lists) ->
  144. {Names, _} = lists:unzip(Lists),
  145. Zones = emqx:get_config([zones]),
  146. ?assertEqual(lists:sort(Names), lists:sort(maps:keys(Zones))),
  147. Timers = sys:get_state(emqx_flapping),
  148. maps:foreach(
  149. fun(Name, #{flapping_detect := #{enable := Enable}}) ->
  150. ?assertEqual(lists:keyfind(Name, 1, Lists), {Name, Enable}),
  151. ?assertEqual(Enable, is_reference(maps:get(Name, Timers)), Timers)
  152. end,
  153. Zones
  154. ),
  155. ?assertEqual(maps:keys(Zones), maps:keys(Timers)),
  156. ok.
  157. t_window_compatibility_check(_Conf) ->
  158. Flapping = emqx:get_raw_config([flapping_detect]),
  159. ok = emqx_config:init_load(emqx_schema, <<"flapping_detect {window_time = disable}">>),
  160. ?assertMatch(#{window_time := 60000, enable := false}, emqx:get_config([flapping_detect])),
  161. %% reset
  162. FlappingBin = iolist_to_binary(["flapping_detect {", hocon_pp:do(Flapping, #{}), "}"]),
  163. ok = emqx_config:init_load(emqx_schema, FlappingBin),
  164. ?assertEqual(Flapping, emqx:get_raw_config([flapping_detect])),
  165. ok.
  166. get_policy(Zone) ->
  167. emqx_config:get_zone_conf(Zone, [flapping_detect]).