Erlang/OTP Forums

Author Message

<  Erlang questions mailing list  ~  PropEr way to deal with recursive types

Guest
Posted: Sat Sep 10, 2011 12:10 am Reply with quote
Guest
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

I'm wondering how to handle testing with recursive types, especially
with regards to handling the depth at which those structures are created
in the generators.

Take, for instance, a decoded json object ({struct, [{K,V},...]} in this
case). V can obviously be a json object itself or even a list of json
objects.

I'd like to write a function is_json_object/1 that will deeply inspect a
passed json object and verify it is, in fact, a json object.

Assuming simplified types similar to:

- -type json_prop_key() :: binary().
- -type json_prop_value() :: binary() | json_object().
- -type json_object() :: {struct, [{json_prop_key(), json_prop_value()}]}.

and a function definition
- -spec is_json_object/1 :: (term()) -> boolean().
is_json_object(MaybeJObj) ->
% Implementation here
...
% return a boolean

Now, I'd like to create the PropEr tests for valid json objects. Here's
my first crack:

prop_is_json_object() ->
?FORALL(JObj, json_object_builder(),
?WHENFAIL(io:format("Failed prop_is_json_object ~p~n", [JObj]),
?MODULE:is_json_object(JObj)
)).

%% GENERATORS
%% create json objects
json_object_builder() ->
?LET(Prop, a_proplist(), {struct, Prop}).

a_proplist() ->
?SUCHTHAT(L, list( ?LET({K,V}, {binary(), proplist_value()}, {K, V})
), length(L) < 5).

proplist_value() ->
?LAZY(weighted_union([{15, binary()}, {1, json_object_builder()}])).

I tried limiting the proplist to 5 tuples, heavily weighting the
proplist_value union towards binary(), etc. When I run
"proper:module(json_tester).", I see a string of periods (varies how far
it gets), then the VM hangs and I have to get into the JCL to interrupt
the process. My assumption is that the generator is getting stuck
creating a big data structure, as CPU and memory increase rapidly.

I've looked at three examples[1][2][3] that Fred Herbert shared but
haven't found the mental bridge between his examples and my attempt. I
don't doubt that I'm misusing or ignorant of the right functions or
macros in PropEr to make this easier.

Any hints? Smile

James

[1]
https://bitbucket.org/ferd/zippers/src/9548780f0261/test/prop_zipper_lists.erl#cl-92
[2]
https://bitbucket.org/ferd/zippers/src/9548780f0261/test/prop_zipper_bintrees.erl#cl-88
[3]
https://bitbucket.org/ferd/zippers/src/9548780f0261/test/prop_zipper_forests.erl#cl-198

- --
James Aimonetti
Distributed Systems Engineer / DJ MC_

2600hz | http://2600hz.com
sip:james@2600hz.com
tel: 415.886.7905
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iQEcBAEBAgAGBQJOaqr2AAoJENc77s1OYoGgAYsH/jXoReq7uXkPxVrBvzseQULe
lOgFcJoWf1/Ese2pyIOC9VmNt5uj1XxMfhu5RinjSmXarep77nRUYTc6DMWDHYk+
YWSM9seNYMfR7tgcUmztpZkhpNdYvwKhPGHkvuuw3bEMzizT9qh+NmUOFvhUiwpU
kngonWOY00tFr+kpJ/JXQtcyCpl/WGTodXGOwflAwosFwTtJPLjOjS3fgqeF/X3s
NJv4rM1p55H6LmraX/t7mOvDPJFuMaDL/AfOqn1ndQM8BwXxjx6m8EcpN3B+noe8
LsAKEm3r+qXwGTImT6/H1PC+Y0NdGgSUbWDKQrTVNJlMyn8MstwBOPC7emJVhxI=
=4Srb
-----END PGP SIGNATURE-----
_______________________________________________
erlang-questions mailing list
erlang-questions@erlang.org
http://erlang.org/mailman/listinfo/erlang-questions
Post received from mailinglist
Guest
Posted: Sat Sep 10, 2011 2:17 am Reply with quote
Guest
James -

See the SIZED macro and resize command.

Here is an example that decrements the size for each recursive call:

type(Gen,Type) ->
?SIZED(Size,resize(if Size > 0 -> Size-1; true -> 0 end,type1(Gen,Type))).

https://github.com/norton/ubf/blob/master/test/qc/qc_ubf_types.erl

Depending on your needs, you may want to divide by 2, take the square root, etc.

thanks,

Joseph Norton


p.s. Take note - there is an open issue related to PropEr's resize implementation:

https://github.com/manopapad/proper/issues/10


On Sep 10, 2011, at 9:10 AM, James Aimonetti wrote:

> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> I'm wondering how to handle testing with recursive types, especially
> with regards to handling the depth at which those structures are created
> in the generators.
>
> Take, for instance, a decoded json object ({struct, [{K,V},...]} in this
> case). V can obviously be a json object itself or even a list of json
> objects.
>
> I'd like to write a function is_json_object/1 that will deeply inspect a
> passed json object and verify it is, in fact, a json object.
>
> Assuming simplified types similar to:
>
> - -type json_prop_key() :: binary().
> - -type json_prop_value() :: binary() | json_object().
> - -type json_object() :: {struct, [{json_prop_key(), json_prop_value()}]}.
>
> and a function definition
> - -spec is_json_object/1 :: (term()) -> boolean().
> is_json_object(MaybeJObj) ->
> % Implementation here
> ...
> % return a boolean
>
> Now, I'd like to create the PropEr tests for valid json objects. Here's
> my first crack:
>
> prop_is_json_object() ->
> ?FORALL(JObj, json_object_builder(),
> ?WHENFAIL(io:format("Failed prop_is_json_object ~p~n", [JObj]),
> ?MODULE:is_json_object(JObj)
> )).
>
> %% GENERATORS
> %% create json objects
> json_object_builder() ->
> ?LET(Prop, a_proplist(), {struct, Prop}).
>
> a_proplist() ->
> ?SUCHTHAT(L, list( ?LET({K,V}, {binary(), proplist_value()}, {K, V})
> ), length(L) < 5).
>
> proplist_value() ->
> ?LAZY(weighted_union([{15, binary()}, {1, json_object_builder()}])).
>
> I tried limiting the proplist to 5 tuples, heavily weighting the
> proplist_value union towards binary(), etc. When I run
> "proper:module(json_tester).", I see a string of periods (varies how far
> it gets), then the VM hangs and I have to get into the JCL to interrupt
> the process. My assumption is that the generator is getting stuck
> creating a big data structure, as CPU and memory increase rapidly.
>
> I've looked at three examples[1][2][3] that Fred Herbert shared but
> haven't found the mental bridge between his examples and my attempt. I
> don't doubt that I'm misusing or ignorant of the right functions or
> macros in PropEr to make this easier.
>
> Any hints? Smile
>
> James
>
> [1]
> https://bitbucket.org/ferd/zippers/src/9548780f0261/test/prop_zipper_lists.erl#cl-92
> [2]
> https://bitbucket.org/ferd/zippers/src/9548780f0261/test/prop_zipper_bintrees.erl#cl-88
> [3]
> https://bitbucket.org/ferd/zippers/src/9548780f0261/test/prop_zipper_forests.erl#cl-198
>
> - --
> James Aimonetti
> Distributed Systems Engineer / DJ MC_
>
> 2600hz | http://2600hz.com
> sip:james@2600hz.com
> tel: 415.886.7905
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.10 (GNU/Linux)
> Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
>
> iQEcBAEBAgAGBQJOaqr2AAoJENc77s1OYoGgAYsH/jXoReq7uXkPxVrBvzseQULe
> lOgFcJoWf1/Ese2pyIOC9VmNt5uj1XxMfhu5RinjSmXarep77nRUYTc6DMWDHYk+
> YWSM9seNYMfR7tgcUmztpZkhpNdYvwKhPGHkvuuw3bEMzizT9qh+NmUOFvhUiwpU
> kngonWOY00tFr+kpJ/JXQtcyCpl/WGTodXGOwflAwosFwTtJPLjOjS3fgqeF/X3s
> NJv4rM1p55H6LmraX/t7mOvDPJFuMaDL/AfOqn1ndQM8BwXxjx6m8EcpN3B+noe8
> LsAKEm3r+qXwGTImT6/H1PC+Y0NdGgSUbWDKQrTVNJlMyn8MstwBOPC7emJVhxI=
> =4Srb
> -----END PGP SIGNATURE-----
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@erlang.org
> http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
erlang-questions@erlang.org
http://erlang.org/mailman/listinfo/erlang-questions
Post received from mailinglist
motiejusj
Posted: Sat Sep 10, 2011 11:45 am Reply with quote
Joined: 02 Aug 2011 Posts: 5
On Fri, Sep 09, 2011 at 05:10:30PM -0700, James Aimonetti wrote:
> I tried limiting the proplist to 5 tuples, heavily weighting the
> proplist_value union towards binary(), etc. When I run
> "proper:module(json_tester).", I see a string of periods (varies how far
> it gets), then the VM hangs and I have to get into the JCL to interrupt
> the process. My assumption is that the generator is getting stuck
> creating a big data structure, as CPU and memory increase rapidly.
>
> I've looked at three examples[1][2][3] that Fred Herbert shared but
> haven't found the mental bridge between his examples and my attempt. I
> don't doubt that I'm misusing or ignorant of the right functions or
> macros in PropEr to make this easier.
>
> Any hints? Smile
>

You can limit recursion depth as well. Just pass max_size to the
proper:quickcheck() function. That helped me as I didn't have to write
my own recursive generator. Smile

As the topic is quite similar, I would like to remind about creating
custom types in PropEr.
http://erlang.org/pipermail/erlang-questions/2011-August/060619.html

Thanks

Motiejus
_______________________________________________
erlang-questions mailing list
erlang-questions@erlang.org
http://erlang.org/mailman/listinfo/erlang-questions
Post received from mailinglist
View user's profile Send private message
Guest
Posted: Sat Sep 10, 2011 1:06 pm Reply with quote
Guest
On 09/10/11 14:46, Motiejus Jak
Guest
Posted: Sat Sep 10, 2011 8:25 pm Reply with quote
Guest
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 09/10/2011 06:06 AM, Kostis Sagonas wrote:
> On 09/10/11 14:46, Motiejus Jak

Display posts from previous:  

All times are GMT
Page 1 of 1
This forum is locked: you cannot post, reply to, or edit topics.

Jump to:  

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You cannot download files in this forum