Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PropEr map() generators #238

Open
kostis opened this issue Apr 6, 2020 · 0 comments
Open

PropEr map() generators #238

kostis opened this issue Apr 6, 2020 · 0 comments

Comments

@kostis
Copy link
Collaborator

kostis commented Apr 6, 2020

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant