File 2331-Property-based-tests-for-the-sets-module.patch of Package erlang
From cc63f8cea5c3be92e6297abed3c29ac0cc73967e Mon Sep 17 00:00:00 2001
From: Maria Scott <maria-12648430@hnc-agency.org>
Date: Fri, 18 Aug 2023 11:51:00 +0200
Subject: [PATCH] Property-based tests for the sets module
Co-authored-by: Jan Uhlig <juhlig@hnc-agency.org>
---
lib/stdlib/test/Makefile | 1 +
lib/stdlib/test/property_test/sets_prop.erl | 653 +++++++++++++++++++
lib/stdlib/test/sets_property_test_SUITE.erl | 122 ++++
3 files changed, 776 insertions(+)
create mode 100644 lib/stdlib/test/property_test/sets_prop.erl
create mode 100644 lib/stdlib/test/sets_property_test_SUITE.erl
diff --git a/lib/stdlib/test/Makefile b/lib/stdlib/test/Makefile
index bdac775256..cb87124377 100644
--- a/lib/stdlib/test/Makefile
+++ b/lib/stdlib/test/Makefile
@@ -71,6 +71,7 @@ MODULES= \
re_testoutput1_split_test \
slave_SUITE \
sets_SUITE \
+ sets_property_test_SUITE \
sets_test_lib \
sofs_SUITE \
stdlib_SUITE \
diff --git a/lib/stdlib/test/property_test/sets_prop.erl b/lib/stdlib/test/property_test/sets_prop.erl
new file mode 100644
index 0000000000..2a87aa2614
--- /dev/null
+++ b/lib/stdlib/test/property_test/sets_prop.erl
@@ -0,0 +1,653 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2021-2022. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(sets_prop).
+
+-include_lib("common_test/include/ct_property_test.hrl").
+
+%%%%%%%%%%%%%%%%%%
+%%% Properties %%%
+%%%%%%%%%%%%%%%%%%
+
+%% --- add_element/2 --------------------------------------------------
+prop_add_element() ->
+ test_all(fun subprop_add_element/1).
+
+subprop_add_element(Mod) ->
+ ?FORALL(
+ {{S0, M0}, Es},
+ ?LET(
+ {L1, L2, B},
+ {ct_proper_ext:safe_list(),
+ ct_proper_ext:safe_list(),
+ ct_proper_ext:safe_list()},
+ {gen_set(Mod, L1 ++ B), L2 ++ B}
+ ),
+ begin
+ {S1, M1} = lists:foldl(fun(E, {SAcc, MAcc}) ->
+ {Mod:add_element(E, SAcc),
+ model_add_element(E, MAcc)}
+ end,
+ {S0, M0},
+ Es),
+ is_equal(S1, M1)
+ end
+ ).
+
+
+%% --- del_element/2 --------------------------------------------------
+prop_del_element() ->
+ test_all(fun subprop_del_element/1).
+
+subprop_del_element(Mod) ->
+ ?FORALL(
+ {{S0, M0}, Es},
+ ?LET(
+ {L1, L2, B},
+ {ct_proper_ext:safe_list(),
+ ct_proper_ext:safe_list(),
+ ct_proper_ext:safe_list()},
+ {gen_set(Mod, L1 ++ B), L2 ++ B}
+ ),
+ begin
+ {S1, M1} = lists:foldl(fun(E, {SAcc, MAcc}) ->
+ {Mod:del_element(E, SAcc),
+ model_del_element(E, MAcc)}
+ end,
+ {S0, M0},
+ Es),
+ is_equal(S1, M1)
+ end
+ ).
+
+
+%% --- filter/2 -------------------------------------------------------
+prop_filter() ->
+ test_all(fun subprop_filter/1).
+
+subprop_filter(Mod) ->
+ ?FORALL(
+ {{S0, M0}, Fun},
+ {gen_set(Mod), function1(boolean())},
+ is_equal(Mod:filter(Fun, S0),
+ model_filter(Fun, M0))
+ ).
+
+
+%% --- filtermap/2 ----------------------------------------------------
+prop_filtermap() ->
+ test_all(fun subprop_filtermap/1).
+
+subprop_filtermap(Mod) ->
+ ?FORALL(
+ {{S0, M0}, Fun},
+ {gen_set(Mod),
+ function1(oneof([true, false, {true, ct_proper_ext:safe_any()}]))},
+ is_equal(Mod:filtermap(Fun, S0),
+ model_filtermap(Fun, M0))
+ ).
+
+
+%% --- fold/3 ---------------------------------------------------------
+prop_fold() ->
+ test_all(fun subprop_fold/1).
+
+subprop_fold(Mod) ->
+ ?FORALL(
+ {S, M},
+ gen_set(Mod),
+ begin
+ Fun = fun(E, Acc) -> Acc + erlang:phash2(E) end,
+ Mod:fold(Fun, 0, S) =:= model_fold(Fun, 0, M)
+ end
+ ).
+
+
+%% --- from_list/1,2 --------------------------------------------------
+prop_from_list() ->
+ test_all(fun subprop_from_list/1).
+
+subprop_from_list(sets) ->
+ ?FORALL(
+ {L, V},
+ {ct_proper_ext:safe_list(), gen_version()},
+ is_equal(sets:from_list(L, [{version, V}]),
+ model_from_list(sets, L))
+ );
+subprop_from_list(Mod) ->
+ ?FORALL(
+ L,
+ ct_proper_ext:safe_list(),
+ is_equal(Mod:from_list(L),
+ model_from_list(Mod, L))
+ ).
+
+
+%% --- intersection/1 -------------------------------------------------
+prop_intersection_1() ->
+ test_all(fun subprop_intersection_1/1).
+
+subprop_intersection_1(Mod) ->
+ ?FORALL(
+ SMs,
+ ?LET(
+ {Ls, A},
+ {non_empty(list(ct_proper_ext:safe_list())),
+ ct_proper_ext:safe_list()},
+ [gen_set(Mod, L ++ A) || L <- Ls]
+ ),
+ begin
+ {Ss, Ms} = lists:unzip(SMs),
+ is_equal(Mod:intersection(Ss),
+ model_intersection(Ms))
+ end
+ ).
+
+
+%% --- intersection/2 -------------------------------------------------
+prop_intersection_2() ->
+ test_all(fun subprop_intersection_2/1).
+
+subprop_intersection_2(Mod) ->
+ ?FORALL(
+ {{S1, M1}, {S2, M2}},
+ ?LET(
+ {L1, L2, B},
+ {ct_proper_ext:safe_list(),
+ ct_proper_ext:safe_list(),
+ ct_proper_ext:safe_list()},
+ {gen_set(Mod, L1 ++ B), gen_set(Mod, L2 ++ B)}
+ ),
+ is_equal(Mod:intersection(S1, S2),
+ model_intersection(M1, M2))
+ ).
+
+
+%% --- is_disjoint/2 --------------------------------------------------
+prop_is_disjoint() ->
+ test_all(fun subprop_is_disjoint/1).
+
+subprop_is_disjoint(Mod) ->
+ ?FORALL(
+ {{S1, M1}, {S2, M2}},
+ ?LET(
+ {L1, L2, B},
+ {ct_proper_ext:safe_list(),
+ ct_proper_ext:safe_list(),
+ ct_proper_ext:safe_list()},
+ begin
+ {gen_set(Mod, L1 ++ B), gen_set(Mod, L2 ++ B)}
+ end
+ ),
+ Mod:is_disjoint(S1, S2) =:= model_is_disjoint(M1, M2)
+ ).
+
+
+%% --- is_element/2 ---------------------------------------------------
+prop_is_element() ->
+ test_all(fun subprop_is_element/1).
+
+subprop_is_element(Mod) ->
+ ?FORALL(
+ {{S, M}, Es},
+ ?LET(
+ {L, Extra},
+ {ct_proper_ext:safe_list(), ct_proper_ext:safe_list()},
+ {gen_set(Mod, L), L ++ Extra}
+ ),
+ lists:all(fun(E) ->
+ Mod:is_element(E, S) =:= model_is_element(E, M)
+ end,
+ Es)
+ ).
+
+
+%% --- is_empty/1 -----------------------------------------------------
+prop_is_empty() ->
+ test_all(fun subprop_is_empty/1).
+
+subprop_is_empty(Mod) ->
+ ?FORALL(
+ {S, M},
+ gen_set(Mod),
+ Mod:is_empty(S) =:= model_is_empty(M)
+ ).
+
+
+%% --- is_equal/1 -----------------------------------------------------
+prop_is_equal() ->
+ test_all(fun subprop_is_equal/1).
+
+subprop_is_equal(Mod) ->
+ ?FORALL(
+ {{S1, M1}, {S2, M2}},
+ {gen_set(Mod), gen_set(Mod)},
+ Mod:is_equal(S1, S2)=:=is_equal(S1, M2) andalso
+ Mod:is_equal(S2, S1)=:=is_equal(S2, M1)
+ ).
+
+
+%% --- is_set/1 -------------------------------------------------------
+prop_is_set() ->
+ test_all(fun subprop_is_set/1).
+
+subprop_is_set(sets) ->
+ ?FORALL(
+ {Exp, {S, _M}},
+ oneof([{true, gen_set(sets)},
+ {false, {?SUCHTHAT(T,
+ ct_proper_ext:safe_any(),
+ not (is_map(T) orelse
+ is_tuple(T) andalso
+ tuple_size(T)=:=9 andalso
+ element(1, T)=:=set)),
+ undefined}}]),
+ Exp =:= sets:is_set(S)
+ );
+subprop_is_set(ordsets) ->
+ ?FORALL(
+ {Exp, {S, _M}},
+ oneof([{true, gen_set(ordsets)},
+ {false, {?SUCHTHAT(T,
+ ct_proper_ext:safe_any(),
+ not is_list(T)),
+ undefined}}]),
+ Exp =:= ordsets:is_set(S)
+ );
+subprop_is_set(gb_sets) ->
+ ?FORALL(
+ {Exp, {S, _M}},
+ oneof([{true, gen_set(gb_sets)},
+ {false, {?SUCHTHAT(T,
+ ct_proper_ext:safe_any(),
+ not (is_tuple(T) andalso
+ tuple_size(T) =:= 2 andalso
+ is_integer(element(1, T)) andalso
+ element(1, T) >= 0 andalso
+ (element(2, T) =:= nil orelse
+ is_tuple(element(2, T)) andalso
+ tuple_size(element(2, T)) =:= 3))),
+ undefined}}]),
+ Exp =:= gb_sets:is_set(S)
+ ).
+
+
+%% --- subset/2 -------------------------------------------------------
+%%
+%% +-----------------------------+
+%% | S0 +----------------------+ |
+%% | | S1 +-------------+ | |
+%% | | | S2 | | |
+%% | | +----+-----------+ | | |
+%% | | | S3 | +-------+ | | | |
+%% | | | | | Empty | | | | |
+%% | | | | +-------+ | | | |
+%% | | | +-----------+-+ | |
+%% | | +----------------+ | |
+%% | +----------------------+ |
+%% +-----------------------------+
+%% * Empty is a subset of S2 and S3
+%%
+%% * S2 is a subset of S1 but not of S3
+%% * S3 is a subset of S1 but not of S2
+%% --> Empty is a subset of S1
+%%
+%% * S1 is a subset of S0
+%% --> S2, S3 and Empty are subsets of S0
+prop_is_subset() ->
+ test_all(fun subprop_is_subset/1).
+
+subprop_is_subset(Mod) ->
+ ?FORALL(
+ SMs,
+ ?LET(
+ {L1, L2},
+ {ct_proper_ext:safe_list(), ct_proper_ext:safe_list()},
+ begin
+ L3Extra = [make_ref()|L2],
+ L2Extra = [make_ref()|L1],
+ L1Extra = [make_ref()|L2Extra ++ L3Extra],
+ L0Extra = [make_ref()|L1Extra],
+ [gen_set(Mod, L0Extra),
+ gen_set(Mod, L1Extra),
+ gen_set(Mod, L2Extra),
+ gen_set(Mod, L3Extra),
+ gen_set(Mod, [])]
+ end
+ ),
+ lists:all(fun({{S1, M1}, {S2, M2}}) ->
+ Mod:is_subset(S1, S2) =:= model_is_subset(M1, M2)
+ end,
+ [{SM1, SM2} || SM1 <- SMs, SM2 <- SMs])
+ ).
+
+
+%% --- map/2 ----------------------------------------------------------
+prop_map() ->
+ test_all(fun subprop_map/1).
+
+subprop_map(Mod) ->
+ ?FORALL(
+ {{S0, M0}, Fun},
+ {gen_set(Mod), function1(ct_proper_ext:safe_any())},
+ is_equal(Mod:map(Fun, S0),
+ model_map(Fun, M0))
+ ).
+
+
+%% --- size/1 ---------------------------------------------------------
+prop_size() ->
+ test_all(fun subprop_size/1).
+
+subprop_size(Mod) ->
+ ?FORALL(
+ {S, M},
+ gen_set(Mod),
+ Mod:size(S) =:= model_size(M)
+ ).
+
+
+%% --- subtract/2 -----------------------------------------------------
+prop_subtract() ->
+ test_all(fun subprop_subtract/1).
+
+subprop_subtract(Mod) ->
+ ?FORALL(
+ {{S1, M1}, {S2, M2}},
+ ?LET(
+ {L1, L2, B},
+ {ct_proper_ext:safe_list(),
+ ct_proper_ext:safe_list(),
+ ct_proper_ext:safe_list()},
+ {gen_set(Mod, L1 ++ B), gen_set(Mod, L2 ++ B)}
+ ),
+ is_equal(Mod:subtract(S1, S2),
+ model_subtract(M1, M2)) andalso
+ is_equal(Mod:subtract(S2, S1),
+ model_subtract(M2, M1))
+ ).
+
+
+%% --- to_list/1 ------------------------------------------------------
+prop_to_list() ->
+ test_all(fun subprop_to_list/1).
+
+subprop_to_list(Mod) ->
+ ?FORALL(
+ {S, M},
+ gen_set(Mod),
+ list_matchsort(Mod:to_list(S)) =:= list_matchsort(model_to_list(M))
+ ).
+
+
+%% --- union/1 --------------------------------------------------------
+prop_union_1() ->
+ test_all(fun subprop_union_1/1).
+
+subprop_union_1(Mod) ->
+ ?FORALL(
+ SMs,
+ ?LET(
+ {Ls, A},
+ {list(ct_proper_ext:safe_list()), ct_proper_ext:safe_list()},
+ [gen_set(Mod, L ++ A) || L <- Ls]
+ ),
+ begin
+ {Ss, Ms} = lists:unzip(SMs),
+ is_equal(Mod:union(Ss),
+ model_union(Mod, Ms))
+ end
+ ).
+
+
+%% --- union/2 --------------------------------------------------------
+prop_union_2() ->
+ test_all(fun subprop_union_2/1).
+
+subprop_union_2(Mod) ->
+ ?FORALL(
+ {{S1, M1}, {S2, M2}},
+ ?LET(
+ {L1, L2, B},
+ {ct_proper_ext:safe_list(),
+ ct_proper_ext:safe_list(),
+ ct_proper_ext:safe_list()},
+ {gen_set(Mod, L1 ++ B), gen_set(Mod, L2 ++ B)}
+ ),
+ is_equal(Mod:union(S1, S2),
+ model_union(Mod, M1, M2))
+ ).
+
+%% --- sequence of modifying operations -------------------------------
+prop_operations() ->
+ test_all(fun subprop_operations/1).
+
+subprop_operations(Mod) ->
+ ?FORALL(
+ {SM0, Ops},
+ {gen_set(Mod),
+ list(oneof([{add_element, ct_proper_ext:safe_any()},
+ {del_element, ct_proper_ext:safe_any()},
+ {filter, function1(boolean())},
+ {filtermap, function1(oneof([true,
+ false,
+ {true, ct_proper_ext:safe_any()}]))},
+ {intersection, gen_set(Mod)},
+ {map, function1(ct_proper_ext:safe_any())},
+ {subtract, gen_set(Mod)},
+ {union, gen_set(Mod)}]))},
+ begin
+ {S1, M1} = lists:foldl(fun
+ ({add_element, E}, {SAcc, MAcc}) ->
+ {Mod:add_element(E, SAcc),
+ model_add_element(E, MAcc)};
+ ({del_element, E}, {SAcc, MAcc}) ->
+ {Mod:del_element(E, SAcc),
+ model_del_element(E, MAcc)};
+ ({filter, Fun}, {SAcc, MAcc}) ->
+ {Mod:filter(Fun, SAcc),
+ model_filter(Fun, MAcc)};
+ ({filtermap, Fun}, {SAcc, MAcc}) ->
+ {Mod:filtermap(Fun, SAcc),
+ model_filtermap(Fun, MAcc)};
+ ({intersection, {S, M}}, {SAcc, MAcc}) ->
+ {Mod:intersection(SAcc, S),
+ model_intersection(MAcc, M)};
+ ({map, Fun}, {SAcc, MAcc}) ->
+ {Mod:map(Fun, SAcc),
+ model_map(Fun, MAcc)};
+ ({subtract, {S, M}}, {SAcc, MAcc}) ->
+ {Mod:subtract(SAcc, S),
+ model_subtract(MAcc, M)};
+ ({union, {S, M}}, {SAcc, MAcc}) ->
+ {Mod:union(SAcc, S),
+ model_union(Mod, MAcc, M)}
+ end,
+ SM0,
+ Ops),
+ is_equal(S1, M1)
+ end
+ ).
+
+%%%%%%%%%%%%%%%%%%
+%%% Generators %%%
+%%%%%%%%%%%%%%%%%%
+
+gen_version() ->
+ oneof([1, 2]).
+
+gen_set(sets) ->
+ ?LET(
+ {L, V},
+ {ct_proper_ext:safe_list(), gen_version()},
+ gen_set(sets, L, V)
+ );
+gen_set(Mod) ->
+ ?LET(
+ L,
+ ct_proper_ext:safe_list(),
+ gen_set(Mod, L, 0)
+ ).
+
+gen_set(sets, List) when is_list(List) ->
+ ?LET(
+ V,
+ gen_version(),
+ gen_set(sets, List, V)
+ );
+gen_set(Mod, List) when is_list(List) ->
+ gen_set(Mod, List, 0);
+gen_set(Mod, Version) when is_integer(Version) ->
+ ?LET(
+ L,
+ ct_proper_ext:safe_list(),
+ gen_set(Mod, L, Version)
+ ).
+
+gen_set(sets, List, Version) ->
+ {sets:from_list(List, [{version, Version}]),
+ model_from_list(sets, List)};
+gen_set(Mod, List, _Version) ->
+ {Mod:from_list(List),
+ model_from_list(Mod, List)}.
+
+
+%%%%%%%%%%%%%
+%%% Model %%%
+%%%%%%%%%%%%%
+
+-record(model, {type, module, content=#{}}).
+
+model_new(sets) ->
+ #model{type=match, module=sets};
+model_new(ordsets) ->
+ #model{type=equal, module=ordsets};
+model_new(gb_sets) ->
+ #model{type=equal, module=gb_sets}.
+
+model_add_element(E, #model{type=equal, content=C}=M) when is_float(E), trunc(E) == E ->
+ M#model{content=C#{trunc(E) => E}};
+model_add_element(E, #model{content=C}=M) ->
+ M#model{content=C#{E => E}}.
+
+model_del_element(E, #model{type=equal, content=C}=M) when is_float(E), trunc(E) == E ->
+ M#model{content=maps:remove(trunc(E), C)};
+model_del_element(E, #model{content=C}=M) ->
+ M#model{content=maps:remove(E, C)}.
+
+model_from_list(Mod, L) ->
+ lists:foldl(fun model_add_element/2, model_new(Mod), L).
+
+model_to_list(#model{content=C}) ->
+ maps:values(C).
+
+model_is_element(E, #model{type=equal, content=C}) when is_float(E), trunc(E) == E ->
+ maps:is_key(trunc(E), C);
+model_is_element(E, #model{content=C}) ->
+ maps:is_key(E, C).
+
+model_size(#model{content=C}) ->
+ maps:size(C).
+
+model_filter(Fun, #model{content=C}=M) ->
+ M#model{content=maps:filter(fun(_K, V) -> Fun(V) end, C)}.
+
+model_map(Fun, #model{module=Mod, content=C}) ->
+ maps:fold(fun(_K, V, Acc) -> model_add_element(Fun(V), Acc) end, model_new(Mod), C).
+
+model_filtermap(Fun, #model{module=Mod, content=C}) ->
+ maps:fold(fun(_K, V0, Acc) ->
+ case Fun(V0) of
+ true ->
+ model_add_element(V0, Acc);
+ {true, V1} ->
+ model_add_element(V1, Acc);
+ false ->
+ Acc
+ end
+ end,
+ model_new(Mod),
+ C).
+
+model_fold(Fun, Acc0, #model{content=C}) ->
+ maps:fold(fun(_K, V, Acc1) -> Fun(V, Acc1) end, Acc0, C).
+
+model_subtract(#model{module=Mod, content=C1}=M1, #model{module=Mod, content=C2}) ->
+ M1#model{content=maps:without(maps:keys(C2), C1)}.
+
+model_intersection([M|Ms]) ->
+ model_intersection_1(Ms, M).
+
+model_intersection(M1, M2) ->
+ model_intersection_1([M1], M2).
+
+model_intersection_1([], Acc) ->
+ Acc;
+model_intersection_1([#model{module=Mod, content=C1}|Ms], #model{module=Mod, content=C2}=Acc) ->
+ model_intersection_1(Ms, Acc#model{content=maps:with(maps:keys(C2), maps:with(maps:keys(C1), C2))}).
+
+model_union(Mod, []) ->
+ model_new(Mod);
+model_union(_Mod, [M|Ms]) ->
+ model_union_1(Ms, M).
+
+model_union(_Mod, M1, M2) ->
+ model_union_1([M1], M2).
+
+model_union_1([], Acc) ->
+ Acc;
+model_union_1([#model{module=Mod, content=C1}|Ms], #model{module=Mod, content=C2}=Acc) ->
+ model_union_1(Ms, Acc#model{content=maps:merge(C2, C1)}).
+
+model_is_subset(#model{module=Mod, content=C1}, #model{module=Mod, content=C2}) ->
+ [] =:= maps:keys(C1) -- maps:keys(C2).
+
+model_is_empty(M) ->
+ 0 =:= model_size(M).
+
+model_is_disjoint(M1, M2) ->
+ 0 =:= model_size(model_intersection(M1, M2)).
+
+
+%%%%%%%%%%%%%%%
+%%% Helpers %%%
+%%%%%%%%%%%%%%%
+
+test_all(Fun) ->
+ conjunction([{T, Fun(T)} || T <- [sets, ordsets, gb_sets]]).
+
+list_matchsort(L) ->
+ lists:sort(fun
+ (A, B) when is_float(A), is_integer(B) ->
+ true;
+ (A, B) when is_integer(A), is_float(B) ->
+ false;
+ (A, B) ->
+ A =< B
+ end,
+ L).
+
+is_equal(S, #model{type=T, module=Mod, content=C}) ->
+ L1 = list_matchsort(Mod:to_list(S)),
+ L2 = list_matchsort(maps:keys(C)),
+ case T of
+ match -> L1 =:= L2;
+ equal -> L1 == L2
+ end.
+
diff --git a/lib/stdlib/test/sets_property_test_SUITE.erl b/lib/stdlib/test/sets_property_test_SUITE.erl
new file mode 100644
index 0000000000..20e6e0bcb3
--- /dev/null
+++ b/lib/stdlib/test/sets_property_test_SUITE.erl
@@ -0,0 +1,122 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2021-2023. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(sets_property_test_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+
+-compile(export_all).
+-compile(nowarn_export_all).
+
+all() ->
+ [
+ add_element_case,
+ del_element_case,
+ filter_case,
+ filtermap_case,
+ fold_case,
+ from_list_case,
+ intersection_1_case,
+ intersection_2_case,
+ is_disjoint_case,
+ is_element_case,
+ is_empty_case,
+ is_equal_case,
+ is_set_case,
+ is_subset_case,
+ map_case,
+ size_case,
+ subtract_case,
+ to_list_case,
+ union_1_case,
+ union_2_case,
+ operations_case
+ ].
+
+init_per_suite(Config) ->
+ ct_property_test:init_per_suite(Config).
+
+end_per_suite(Config) ->
+ Config.
+
+do_proptest(Prop, Config) ->
+ ct_property_test:quickcheck(sets_prop:Prop(), Config).
+
+add_element_case(Config) ->
+ do_proptest(prop_add_element, Config).
+
+del_element_case(Config) ->
+ do_proptest(prop_del_element, Config).
+
+filter_case(Config) ->
+ do_proptest(prop_filter, Config).
+
+filtermap_case(Config) ->
+ do_proptest(prop_filtermap, Config).
+
+fold_case(Config) ->
+ do_proptest(prop_fold, Config).
+
+from_list_case(Config) ->
+ do_proptest(prop_from_list, Config).
+
+intersection_1_case(Config) ->
+ do_proptest(prop_intersection_1, Config).
+
+intersection_2_case(Config) ->
+ do_proptest(prop_intersection_2, Config).
+
+is_disjoint_case(Config) ->
+ do_proptest(prop_is_disjoint, Config).
+
+is_element_case(Config) ->
+ do_proptest(prop_is_element, Config).
+
+is_empty_case(Config) ->
+ do_proptest(prop_is_empty, Config).
+
+is_equal_case(Config) ->
+ do_proptest(prop_is_equal, Config).
+
+is_set_case(Config) ->
+ do_proptest(prop_is_set, Config).
+
+is_subset_case(Config) ->
+ do_proptest(prop_is_subset, Config).
+
+map_case(Config) ->
+ do_proptest(prop_map, Config).
+
+size_case(Config) ->
+ do_proptest(prop_size, Config).
+
+subtract_case(Config) ->
+ do_proptest(prop_subtract, Config).
+
+to_list_case(Config) ->
+ do_proptest(prop_to_list, Config).
+
+union_1_case(Config) ->
+ do_proptest(prop_union_1, Config).
+
+union_2_case(Config) ->
+ do_proptest(prop_union_2, Config).
+
+operations_case(Config) ->
+ do_proptest(prop_operations, Config).
--
2.35.3