<div dir="ltr">I think you are missing the point. Let's demonstrate the problem in this way. There is natural but not working way how to do it<div><br></div><div><div>-define(WITH_G(L, Do),</div><div> begin</div><div> G = Module:from_edgelist(L),</div><div> try Do after delete(G)</div><div> end</div><div> end</div><div> ).</div><div><br></div><div>-define(WITH_G(L, DoEmpty, DoOther),</div><div> ?WITH_G(L,</div><div> case L of</div><div> [] -> DoEmpty;</div><div> _ -> DoOther</div><div> end</div><div> )</div><div> ).</div><div><br></div><div><div>prop_vertices(Module) -></div><div> ?FORALL(</div><div> L, digraph(),</div><div> ?WITH_G(</div><div> L, equals([], vertices(G)),</div><div> ?FORALL(</div><div> {V1, V2}, oneof(L),</div><div> conjunction(<br></div><div> [{source, lists:member(V1, vertices(G))},</div><div> {sink, lists:member(V2, vertices(G))},</div><div> {in_sources, lists:member(V1, sources(G))},</div><div> {in_sinks, lists:member(V2, sinks(G))}</div><div> ]</div><div> )</div><div> )<br></div><div> )</div><div> ).</div></div></div><div><br></div><div>And how to make it work:</div><div><br></div><div><div>prop_vertices(Module) -></div><div> ?FORALL(</div><div> L, digraph(),</div><div> case L of</div><div> [] -> ?WITH_G(L, equals([], vertices(G)));</div><div> _ -></div><div> ?FORALL(</div><div> {V1, V2}, oneof(L),</div><div> ?WITH_G(L,</div><div> begin</div><div> Vs = vertices(G),</div><div> Ses = sources(G),</div><div> Sks = sinks(G),</div><div> conjunction(</div><div> [{source, lists:member(V1, Vs)},</div><div> {sink, lists:member(V2, Vs)},</div><div> {in_sources, lists:member(V1, Ses)},</div><div> {in_sinks, lists:member(V2, Sks)}</div><div> ]</div><div> )</div><div> end</div><div> )</div><div> )</div><div> end</div><div> ).</div><div><br></div></div><div>There is the problem. There is no way you can write ?WITH_G macro working with any of PropEr macros as a parameter. And it would have a simple solution. Just spawn the process or add hooks for clean up.</div><div><br></div><div>I know it is possible to write it in a way it will work, but it prevents to write it reliably and in structured way.</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, May 26, 2015 at 1:44 AM, Kostis Sagonas <span dir="ltr"><<a href="mailto:kostis@cs.ntua.gr" target="_blank">kostis@cs.ntua.gr</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On 05/25/2015 05:11 PM, Hynek Vychodil wrote:<br>
</span><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
<br>
I bumped in the problem how clean up after property in PropEr. Let's<br>
have simple property where I make ets table:<br>
<br>
prop_ets() -><br>
?FORALL(V, integer(),<br>
begin<br>
E = ets:new(),<br>
true = ets:insert(T, {V, ok}),<br>
equals([{V, ok}], ets:lookup(T, V))<br>
end<br>
).<br>
<br>
How am I supposed to delete ets table? It is trickier than looks like.<br></span>
... <SNIP><br>
</blockquote>
<br>
I am not sure I understand what it is exactly that you are finding difficult to do in the simple example above. Here is how:<br>
<br>
=====================================================================<br>
-module(pets).<br>
-include_lib("proper/include/proper.hrl").<br>
<br>
-export_type([key/0, val/0]). % shut off compiler warning<br>
<br>
-type key() :: a | b | c.<br>
-type val() :: 0..42.<br>
<br>
prop_ets() -><br>
?FORALL({K,V}, {key(),val()},<br>
begin<br>
T = setup(),<br>
true = ets:insert(T, {K, V}),<br>
Res = ets:lookup(T, K),<br>
cleanup(T),<br>
[{K, V}] =:= Res<br>
end).<br>
<br>
setup() -><br>
ets:new(?MODULE, [public, named_table]).<br>
<br>
cleanup(T) -><br>
ets:delete(T).<br>
========================================================================<br>
<br>
The pattern of doing a setup, running some commands and getting some Result, doing the cleanup you want to do, and the check that the result is the one that you expect is a general pattern in property-based testing.<br>
<br>
As you can see, the above works:<br>
<br>
kostis@pc:~/proper$ erl -pa ~/proper<br>
Erlang/OTP 17 [erts-6.4.1] [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false]<br>
<br>
Eshell V6.4.1 (abort with ^G)<br>
1> c(pets, [debug_info]).<br>
{ok,pets}<br>
2> proper:quickcheck(pets:prop_ets()).<br>
....................................................................................................<br>
OK: Passed 100 test(s).<br>
true<br>
<br>
<br>
Change the property to one that does not hold (e.g. [{K, V}] =/= Res) and you will also see that shrinking works.<br>
<br>
<br>
I am not sure I follow what you mean by your nested ?FORALL properties but note that, as shown above, you can easily imitate multiple ?FORALLs by using complex terms (tuples, lists, etc.).<br>
<br>
Hope this helps,<br>
Kostis<br>
</blockquote></div><br></div>