sophia/quickcheck/aeso_utils_eqc.erl
Thomas Arts aa2e6aa218 machinery for running QuickCheck
No script needed if we make sure extra_src_dirs has different name than "eqc"

Obsolete QuickCheck property
2019-01-24 09:11:26 +01:00

60 lines
2.0 KiB
Erlang

%%% File : aeso_utils_eqc.erl
%%% Author : Ulf Norell
%%% Description :
%%% Created : 2 Jul 2018 by Ulf Norell
-module(aeso_utils_eqc).
-compile([export_all, nowarn_export_all]).
-include_lib("eqc/include/eqc.hrl").
%% QuickCheck property
graph() ->
?LET(M, map(choose(0, 10), list(choose(0, 10))),
return(complete(M))).
complete(G) ->
Is = lists:usort(lists:concat(maps:values(G))),
maps:merge(maps:from_list([ {I, []} || I <- Is ]), G).
prop_scc() ->
?FORALL(G, graph(),
begin
SCCs = aeso_utils:scc(G),
BadSCC = fun({acyclic, I}) -> reachable_from(G, I, I);
({cyclic, Is}) -> [] /= [ {I, J} || I <- Is, J <- Is, not reachable_from(G, I, J) ]
end,
ToList = fun({acyclic, I}) -> [I];
({cyclic, Is}) -> Is end,
?WHENFAIL(eqc:format("SCCs = ~p\n", [SCCs]),
conjunction(
[ {elems, equals(lists:sort(lists:flatmap(ToList, SCCs)), lists:sort(maps:keys(G)))}
, {sorted, equals([], [ {I, J} || {I, Js} <- maps:to_list(G),
J <- Js,
find_component(I, SCCs) < find_component(J, SCCs) ])}
, {precise, equals([], [ SCC || SCC <- SCCs, BadSCC(SCC) ])}
]))
end).
reachable_from(Graph, I, J) ->
reachable_from1(Graph, maps:get(I, Graph, []), J).
reachable_from1(_, [], _) -> false;
reachable_from1(_, [I | _], I) -> true;
reachable_from1(Graph, [I | Is], J) ->
case maps:get(I, Graph, undefined) of
undefined -> reachable_from1(Graph, Is, J);
Js -> reachable_from1(maps:remove(I, Graph), Js ++ Is, J)
end.
find_component(X, SCCs) ->
ISCCs = lists:zip(SCCs, lists:seq(1, length(SCCs))),
HasX = fun({acyclic, Y}) -> X == Y;
({cyclic, Ys}) -> lists:member(X, Ys) end,
case [ I || {SCC, I} <- ISCCs, HasX(SCC) ] of
[I | _] -> I;
[] -> false
end.