Getting closer to understanding why test coverage appears so poor, part 2

This commit is contained in:
Scott Lystig Fritchie 2014-10-27 00:43:44 +09:00
parent 342a972543
commit da2bad564f

View file

@ -24,6 +24,7 @@
-include("machi.hrl"). -include("machi.hrl").
-define(MGR, machi_chain_manager). -define(MGR, machi_chain_manager).
-define(D(X), io:format(user, "~s ~p\n", [??X, X])).
-export([]). -export([]).
@ -129,11 +130,20 @@ extract_upi_transitions([P1, P2|T]) ->
Trans = {P1#projection.upi, P2#projection.upi}, Trans = {P1#projection.upi, P2#projection.upi},
[Trans|extract_upi_transitions([P2|T])]. [Trans|extract_upi_transitions([P2|T])].
find_common_prefix([], _) ->
[];
find_common_prefix(_, []) ->
[];
find_common_prefix([H|L1], [H|L2]) ->
[H|find_common_prefix(L1, L2)];
find_common_prefix(_, _) ->
[].
calc_projection_test_() -> calc_projection_test_() ->
{timeout, 60, {timeout, 60,
fun() -> fun() ->
%% Nodes = [a,b,c,d], %% Nodes = [a,b,c,d],
Nodes = [a,b], Nodes = [a,b,c],
Cs = combinations(Nodes), Cs = combinations(Nodes),
Combos = lists:sort([{UPI1, UPI2} || UPI1 <- Cs, UPI2 <- Cs]), Combos = lists:sort([{UPI1, UPI2} || UPI1 <- Cs, UPI2 <- Cs]),
timer:sleep(500), timer:sleep(500),
@ -143,14 +153,14 @@ calc_projection_test_() ->
[], PsUPI1, Nodes -- PsUPI1, []), [], PsUPI1, Nodes -- PsUPI1, []),
P2 = ?MGR:make_projection(3, 2, <<>>, HdNd, Nodes, P2 = ?MGR:make_projection(3, 2, <<>>, HdNd, Nodes,
[], PsUPI2, Nodes -- PsUPI2, []), [], PsUPI2, Nodes -- PsUPI2, []),
Res = case (catch projection_transition_is_sane(P1, P2)) of Res = case projection_transition_is_sane(P1, P2) of
true -> true; true -> true;
_ -> false _ -> false
end, end,
{Res, UPI1, UPI2} {Res, PsUPI1, PsUPI2}
end || HdNd <- Nodes, end || HdNd <- Nodes,
{UPI1,UPI2} <- Combos, {UPI1,UPI2} <- Combos,
%% We assume that the author appears in any %% We assume that the author appears in any UPI list
UPI1 /= [], UPI1 /= [],
UPI2 /= [], UPI2 /= [],
%% HdNd is the author for all of these %% HdNd is the author for all of these
@ -159,30 +169,24 @@ calc_projection_test_() ->
lists:member(HdNd, UPI2), lists:member(HdNd, UPI2),
PsUPI1 <- perms(UPI1), PsUPI1 <- perms(UPI1),
PsUPI2 <- perms(UPI2)], PsUPI2 <- perms(UPI2)],
%% HeadNode = hd(Nodes),
OKs = [begin OKs = [begin
{UPI1,UPI2} {UPI1,UPI2}
end || {true, UPI1, UPI2} <- Rs], end || {true, UPI1, UPI2} <- Rs],
%% not sets:is_disjoint(sets:from_list(UPI1),
%% sets:from_list(UPI2))
%% orelse UPI1 == [] orelse UPI2 == []],
io:format(user, "OKs = ~p\n", [lists:usort(OKs)]), io:format(user, "OKs = ~p\n", [lists:usort(OKs)]),
%% OKs = [{UPI1,UPI2} || {true, UPI1, UPI2} <- Rs,
%% not sets:is_disjoint(sets:from_list(UPI1),
%% sets:from_list(UPI2))],
Tab = ets:new(count, [public, set, {keypos, 1}]), Tab = ets:new(count, [public, set, {keypos, 1}]),
[ets:insert(Tab, {Transition, 0}) || Transition <- OKs], [ets:insert(Tab, {Transition, 0}) || Transition <- OKs],
true = eqc:quickcheck( true = eqc:quickcheck(
eqc:numtests(500, ?QC_OUT(prop_calc_projection(Nodes, Tab)))), eqc:numtests(3500,
?QC_OUT(prop_calc_projection(Nodes, Tab)))),
NotCounted = [Transition || {Transition, 0} <- ets:tab2list(Tab)], NotCounted = [Transition || {Transition, 0} <- ets:tab2list(Tab)],
Counted = [X || {_, N}=X <- ets:tab2list(Tab), _Counted = [X || {_, N}=X <- ets:tab2list(Tab),
N > 0], N > 0],
timer:sleep(100), timer:sleep(100),
io:format(user, "OKs length = ~p\n", [length(OKs)]), io:format(user, "\tNotCounted = ~p\n", [NotCounted]),
io:format(user, "Transitions hit = ~p\n", [length(OKs) - length(NotCounted)]), io:format(user, "\tOKs length = ~p\n", [length(OKs)]),
io:format(user, "Transitions = ~p\n", [lists:sort(Counted)]), io:format(user, "\tTransitions hit = ~p\n", [length(OKs) - length(NotCounted)]),
io:format(user, "NotCounted length = ~p\n", [length(NotCounted)]), %% io:format(user, "\tTransitions = ~p\n", [lists:sort(_Counted)]),
io:format(user, "NotCounted = ~p\n", [NotCounted]), io:format(user, "\tNotCounted length = ~p\n", [length(NotCounted)]),
ok ok
end}. end}.
@ -265,16 +269,15 @@ projection_transition_is_sane(
true = lists:member(AuthorServer2, UPI_list2 ++ Repairing_list2), true = lists:member(AuthorServer2, UPI_list2 ++ Repairing_list2),
%% Additions to the UPI chain may only be at the tail %% Additions to the UPI chain may only be at the tail
UPI_common_prefix = UPI_common_prefix = find_common_prefix(UPI_list1, UPI_list2),
lists:takewhile(fun(X) -> sets:is_element(X, UPIS2) end, UPI_list1),
if UPI_common_prefix == [] -> if UPI_common_prefix == [] ->
if UPI_list1 == [] orelse UPI_list2 == [] -> if UPI_list1 == [] orelse UPI_list2 == [] ->
%% If the common prefix is empty, then one of the inputs %% If the common prefix is empty, then one of the
%% must be empty. %% inputs must be empty.
true; true;
true -> true ->
%% Otherwise, we have a case of UPI changing from one %% Otherwise, we have a case of UPI changing from
%% of these two situations: %% one of these two situations:
%% %%
%% UPI_list1 -> UPI_list2 %% UPI_list1 -> UPI_list2
%% [d,c,b,a] -> [c,a] %% [d,c,b,a] -> [c,a]
@ -380,6 +383,26 @@ fail2_smoke_test() ->
true. true.
fail3_smoke_test() ->
Nodes = [a,b],
UPI1 = [a,b],
UPI2 = [b,a],
[begin
PsUPI1 = UPI1,
PsUPI2 = UPI2,
P1 = ?MGR:make_projection(2, 1, <<>>, HdNd, Nodes,
[], PsUPI1, Nodes -- PsUPI1, []),
P2 = ?MGR:make_projection(3, 2, <<>>, HdNd, Nodes,
[], PsUPI2, Nodes -- PsUPI2, []),
Res = case projection_transition_is_sane(P1, P2) of
true -> true;
_ -> false
end,
{Res, HdNd, PsUPI1, PsUPI2} = {false, HdNd, PsUPI1, PsUPI2}
end || HdNd <- Nodes],
true.
%% aaa_smoke_test() -> %% aaa_smoke_test() ->
%% L = [a,b,c,d], %% L = [a,b,c,d],
%% Cs = combinations(L), %% Cs = combinations(L),
@ -391,7 +414,7 @@ fail2_smoke_test() ->
%% [], X, L -- X, []), %% [], X, L -- X, []),
%% P2 = ?MGR:make_projection(3, 2, <<>>, a, L, %% P2 = ?MGR:make_projection(3, 2, <<>>, a, L,
%% [], Y, L -- Y, []), %% [], Y, L -- Y, []),
%% Res = case (catch projection_transition_is_sane(P1, P2)) of %% Res = case projection_transition_is_sane(P1, P2) of
%% true -> true; %% true -> true;
%% _ -> false %% _ -> false
%% end, %% end,