Skip to content

PropEr map() generators #238

Open
Open
@kostis

Description

@kostis

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions