anchor.diff:      unittest_helper:create_ct_all([join_lookup]) ++
           unittest_helper:create_ct_all([add_3_rm_3_data]) ++
           unittest_helper:create_ct_all([add_3_rm_3_data_inc]) ++
  +        [{group, graceful_leave_load}] ++
           test_cases().
   
   groups() ->
   %%     unittest_helper:create_ct_groups(test_cases(), [{add_9_rm_5, [sequence, {repeat_until_any_fail, forever}]}]).
       unittest_helper:create_ct_groups([join_lookup], [{join_lookup, [sequence, {repeat_until_any_fail, 20}]}]) ++
       unittest_helper:create_ct_groups([add_3_rm_3_data], [{add_3_rm_3_data, [sequence, {repeat_until_any_fail, 20}]}]) ++
  -    unittest_helper:create_ct_groups([add_3_rm_3_data_inc], [{add_3_rm_3_data_inc, [sequence, {repeat_until_any_fail, 20}]}]).
  +    unittest_helper:create_ct_groups([add_3_rm_3_data_inc], [{add_3_rm_3_data_inc, [sequence, {repeat_until_any_fail, 20}]}]) ++
  +    [{graceful_leave_load, [sequence, {repeat_until_any_fail, 5}], [make_4_add_1_rm_1_load, make_4_add_2_rm_2_load, make_4_add_3_rm_3_load]}].
   
   suite() -> [ {timetrap, {seconds, 30}} ].
   
  
positive.code:     ct:pal("######## waiting for bench finish ########"),
      util:wait_for_process_to_die(BenchPid).
  
  add_3_rm_1_load(Config) ->
      add_x_rm_y_load(Config, 3, 1).
  
  add_3_rm_2_load(Config) ->
      add_x_rm_y_load(Config, 3, 2).
  
  add_3_rm_3_load(Config) ->
      add_x_rm_y_load(Config, 3, 3).
  
  -spec add_x_rm_y_load(Config::[tuple()], X::non_neg_integer(), Y::pos_integer()) -> boolean().
  add_x_rm_y_load(Config, X, Y) ->
      {priv_dir, PrivDir} = lists:keyfind(priv_dir, 1, Config),
      unittest_helper:make_ring(1, [{config, [{log_path, PrivDir}, {monitor_perf_interval, 0} | join_parameters_list()]}]),
      stop_time(fun() -> add_x_rm_y_load_test(X, Y) end, lists:flatten(io_lib:format("add_~B_rm_~B_load", [X, Y]))),
      unittest_helper:check_ring_load(4),
      unittest_helper:check_ring_data().
  
  -spec add_x_rm_y_load_test(X::non_neg_integer(), Y::pos_integer()) -> ok.
  add_x_rm_y_load_test(X, Y) ->
      BenchPid = erlang:spawn(fun() -> bench:increment(1, 10000) end),
      _ = api_vm:add_nodes(X),
      check_size(X + 1),
      timer:sleep(500),
      % let Y nodes gracefully leave, one after another - not more than minority of tm_tms can die!
      [begin
           ct:pal("Killing #~p: ~p", [I, Pid]),
           comm:send_local(Pid, {leave, null}),
           check_size(X + 1 - I)
       end || {I, Pid} <- lists:zip(lists:seq(1, Y), util:random_subset(Y, pid_groups:find_all(dht_node)))],
      check_size(X + 1 - Y),
      ct:pal("######## waiting for bench finish ########"),
      util:wait_for_process_to_die(BenchPid).
  
  
negative.code:      tester_join_at,
       add_9, rm_5, add_9_rm_5,
       add_2x3_load,
       tester_join_at_timeouts
      ].
  
  