proper icon indicating copy to clipboard operation
proper copied to clipboard

PropEr map() generators

Open kostis opened this issue 6 years ago • 0 comments

After a long wait for PropEr to support maps, PR #152 introduced a map() generator in a quick-and-dirty way. Unfortunately, that implementation violates all sorts of PropEr invariants and it only offers superficial support for maps. Many basic operations involving maps do not really work:

1> proper_types:is_instance(#{}, proper_types:map()).
false
2> proper_types:is_instance(#{a => 42}, proper_types:map()).
false
3> proper_types:is_instance([#{a => 42}], proper_types:list()).
false

Also, it is impossible to generate maps when using the any() generator of PropEr -- test case below. Of course, this also affects list(any()), tuple() and possibly other PropEr generators.

On a positive side, shrinking of maps seems to be working as it should.

-module(m).

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

prop_any_produces_maps() ->
  ?FORALL(T, term(), map_free(T)).

map_free(A) when is_atom(A) -> true;
map_free(B) when is_bitstring(B) -> true;
map_free(F) when is_function(F) -> throw(function_gen);
map_free(L) when is_list(L) -> lists:all(fun map_free/1, L);
map_free(M) when is_map(M) -> false; 
map_free(N) when is_number(N) -> true;
map_free(T) when is_tuple(T) -> lists:all(fun map_free/1, tuple_to_list(T)).

prop_map_shrink_size() ->
  ?FORALL(M, map(atom(), integer()), maps:size(M) < 7).

prop_map_shrink_values() ->
  ?FORALL(M, map(atom(), integer()), lists:sum(maps:values(M)) < 42).

Some test cases below:

Eshell V10.3.4  (abort with ^G)
1> c(m).
{ok,m}
2> proper:module(m).
Testing m:prop_any_produces_maps/0
....................................................................................................
OK: Passed 100 test(s).
 
Testing m:prop_map_shrink_size/0
........................!
Failed: After 25 test(s).
#{' ' => -1,'(Ñ\212ê\037Ù' => 4,'sµÕ\031' => 0,'\201.þCwf' => 3,'\211' => -9,'\211`³qÿ\020\024#' => -5,'ÇØð%\200å\034' => 50,'ó#GîÏ\225' => -6,'ù°\204a®µ¶' => -2}

Shrinking ...............................(31 time(s))
#{'' => 0,'\000' => 0,'\001' => 0,'\002' => 0,'\003' => 0,'\004' => 0,'\005' => 0}

Testing m:prop_map_shrink_values/0
....................!
Failed: After 21 test(s).
#{'\f¾Éµ' => 2,'/\t\202?Ì' => -1,'4' => 0,'W\204' => 0,ßí => 199}

Shrinking ......(6 time(s))
#{'' => 42}

[{m,prop_map_shrink_size,0},{m,prop_map_shrink_values,0}]
3> proper:quickcheck(m:prop_any_produces_maps(), 100000).
.... 100000 dots ...
OK: Passed 100000 test(s).
true

kostis avatar Apr 06 '20 16:04 kostis