Skip to content

Commit

Permalink
Add more tests to the number of users being removed
Browse files Browse the repository at this point in the history
  • Loading branch information
NelsonVides committed Feb 21, 2024
1 parent cf9a6e5 commit 11ffbba
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 24 deletions.
2 changes: 1 addition & 1 deletion elvis.config
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
{elvis_style, invalid_dynamic_call, #{ignore => [amoc_code_server_SUITE]}},
{elvis_style, dont_repeat_yourself, #{min_complexity => 50}},
{elvis_style, no_debug_call, disable},
{elvis_style, no_block_expressions, #{ignore => [amoc_code_server_SUITE]}},
{elvis_style, no_block_expressions, #{ignore => [amoc_code_server_SUITE, controller_SUITE]}},
{elvis_style, no_throw, disable},
{elvis_style, no_import, disable}
]},
Expand Down
4 changes: 2 additions & 2 deletions src/users/amoc_users_sup.erl
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@
-export([incr_no_of_users/1, decr_no_of_users/1, count_no_of_users/0,
start_child/3, stop_child/2, start_children/3, stop_children/2, terminate_all_children/0]).

-export([get_all_children/0]).
-export([distribute/2, get_all_children/0]).

-type count() :: non_neg_integer().
-type assignment() ::[{pid(), count()}].
-type assignment() :: [{pid(), count()}].

-record(storage, {
%% an array of atomics whose index works as follows:
Expand Down
100 changes: 79 additions & 21 deletions test/controller_SUITE.erl
Original file line number Diff line number Diff line change
@@ -1,18 +1,29 @@
-module(controller_SUITE).
-compile([export_all, nowarn_export_all]).

-include_lib("proper/include/proper.hrl").
-include_lib("stdlib/include/assert.hrl").

all() ->
[
{group, distribute},
{group, all_tests}
].

groups() ->
[
{distribute, [parallel], distribute()},
{all_tests, [], all_tests()}
].

distribute() ->
[
each_assignment_is_less_than_or_equal_in_the_input,
total_count_is_always_less_than_or_equal_the_requested_amount,
total_count_is_equal_to_the_requested_amount_or_the_sum_of_values_in_the_input,
total_count_is_the_exact_sum_of_the_values_in_the_input
].

all_tests() ->
[
no_scenario_running_status_is_idle,
Expand All @@ -28,6 +39,7 @@ all_tests() ->
remove_users_scenario_not_started_fails,
check_status_with_running_users_is_correct,
check_status_after_killing_one_user_is_correct,
check_status_after_killing_many_users_is_correct,
killing_more_users_than_available_is_correct,
killing_many_users_in_a_big_test_is_correct,
stop_non_running_scenario_fails,
Expand Down Expand Up @@ -57,6 +69,47 @@ end_per_testcase(_TestCase, Config) ->
Config.

%% test cases

each_assignment_is_less_than_or_equal_in_the_input(_) ->
Prop = ?FORALL({Total, Counts}, {pos_integer(), sups_with_counts()},
begin
SupervisorWithCounts = [ {dummy_pid(), Count} || Count <- Counts ],
{_, Assignments} = amoc_users_sup:distribute(Total, SupervisorWithCounts),
Data = maps:from_list(SupervisorWithCounts),
lists:all(fun({Pid, N}) -> N =< maps:get(Pid, Data) end, Assignments)
end),
run_prop(?FUNCTION_NAME, Prop, 100, 1).

total_count_is_always_less_than_or_equal_the_requested_amount(_) ->
Prop = ?FORALL({Total, Counts}, {pos_integer(), sups_with_counts()},
begin
SupervisorWithCounts = [ {dummy_pid(), Count} || Count <- Counts ],
{Count, _} = amoc_users_sup:distribute(Total, SupervisorWithCounts),
Count =< Total
end),
run_prop(?FUNCTION_NAME, Prop, 100, 1).

total_count_is_equal_to_the_requested_amount_or_the_sum_of_values_in_the_input(_) ->
Prop = ?FORALL({Total, Counts}, {pos_integer(), sups_with_counts()},
begin
SupervisorWithCounts = [ {dummy_pid(), Count} || Count <- Counts ],
{Count, Assignments} = amoc_users_sup:distribute(Total, SupervisorWithCounts),
Assinged = lists:sum([ N || {_, N} <- Assignments ]),
Count =:= Total orelse Count =:= Assinged
end),
run_prop(?FUNCTION_NAME, Prop, 100, 1).

% • The total count of the users is the exact sum of the values in the KV list
total_count_is_the_exact_sum_of_the_values_in_the_input(_) ->
Prop = ?FORALL({Total, Counts}, {pos_integer(), sups_with_counts()},
begin
SupervisorWithCounts = [ {dummy_pid(), Count} || Count <- Counts ],
{Count, Assignments} = amoc_users_sup:distribute(Total, SupervisorWithCounts),
Assinged = lists:sum([ N || {_, N} <- Assignments ]),
Count =:= Assinged
end),
run_prop(?FUNCTION_NAME, Prop, 100, 1).

no_scenario_running_status_is_idle(_) ->
Status = amoc_controller:get_status(),
?assertMatch(idle, Status).
Expand Down Expand Up @@ -119,31 +172,16 @@ check_status_with_running_users_is_correct(_) ->
test_helpers:wait_until_scenario_has_users(testing_scenario, EndId - StartId + 1, EndId).

check_status_after_killing_one_user_is_correct(_) ->
do_start_scenario(testing_scenario, test_helpers:regular_vars()),
NumOfUsers = 10,
amoc_controller:add_users(1, NumOfUsers),
test_helpers:wait_until_scenario_has_users(testing_scenario, NumOfUsers, NumOfUsers),
Ret = amoc_controller:remove_users(1, true),
?assertMatch({ok, 1}, Ret),
test_helpers:wait_until_scenario_has_users(testing_scenario, NumOfUsers - 1, NumOfUsers).
start_and_remove_some_users(10, 1, 1, 9).

check_status_after_killing_many_users_is_correct(_) ->
start_and_remove_some_users(10, 7, 7, 3).

killing_more_users_than_available_is_correct(_) ->
do_start_scenario(testing_scenario, test_helpers:regular_vars()),
NumOfUsers = 10,
amoc_controller:add_users(1, NumOfUsers),
test_helpers:wait_until_scenario_has_users(testing_scenario, NumOfUsers, NumOfUsers),
Ret = amoc_controller:remove_users(999, true),
?assertMatch({ok, 10}, Ret),
test_helpers:wait_until_scenario_has_users(testing_scenario, 0, NumOfUsers).
start_and_remove_some_users(10, 999, 10, 0).

killing_many_users_in_a_big_test_is_correct(_) ->
do_start_scenario(testing_scenario, test_helpers:regular_vars()),
NumOfUsers = 200,
amoc_controller:add_users(1, NumOfUsers),
test_helpers:wait_until_scenario_has_users(testing_scenario, NumOfUsers, NumOfUsers),
Ret = amoc_controller:remove_users(120, true),
?assertMatch({ok, 120}, Ret),
test_helpers:wait_until_scenario_has_users(testing_scenario, 80, NumOfUsers).
start_and_remove_some_users(200, 120, 120, 80).

stop_non_running_scenario_fails(_) ->
Ret = amoc_controller:stop_scenario(),
Expand Down Expand Up @@ -203,6 +241,26 @@ scenario_with_failing_init_fails(_) ->
?assertMatch({error, _}, Ret).

%% helpers
sups_with_counts() ->
non_empty(list(non_neg_integer())).

dummy_pid() ->
spawn_link(fun() -> ok end).

run_prop(PropName, Property, NumTests, WorkersPerScheduler) ->
Opts = [noshrink, {start_size, 1}, {numtests, NumTests},
{numworkers, WorkersPerScheduler * erlang:system_info(schedulers_online)}],
Res = proper:counterexample(proper:conjunction([{PropName, Property}]), Opts),
?assertEqual(true, Res).

start_and_remove_some_users(NumOfUsers, NumOfUsersToRemove, ExpectedRemoved, ExpectedFinal) ->
do_start_scenario(testing_scenario, test_helpers:regular_vars()),
amoc_controller:add_users(1, NumOfUsers),
test_helpers:wait_until_scenario_has_users(testing_scenario, NumOfUsers, NumOfUsers),
Ret = amoc_controller:remove_users(NumOfUsersToRemove, true),
?assertMatch({ok, ExpectedRemoved}, Ret),
test_helpers:wait_until_scenario_has_users(testing_scenario, ExpectedFinal, NumOfUsers).

do_start_scenario(Scenario) ->
do_start_scenario(Scenario, []).

Expand Down

0 comments on commit 11ffbba

Please sign in to comment.