How to mimic Erlang nodes in PropEr statem test

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

How to mimic Erlang nodes in PropEr statem test

Nyirő Gergő
Dear Erlangers,

I have a simple project [1] to learn distributed Erlang where I wrote
a proper_statem
test [2] to simulate the communication between Erlang nodes.
Everything fine and
nice until I have a single process to communicate with, but I want to
cut my program
into multiple processes, but I don't know how should I register the
processes to avoid
pid passing and run multiple process group on the same VM.

Which process registry is used in this situation?

Best regard,
Gergő

  [1]: https://github.com/nyirog/crdt
  [2]: https://github.com/nyirog/crdt/blob/master/test/prop_crdt_cluster.erl
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: How to mimic Erlang nodes in PropEr statem test

Fred Hebert-2
On 01/22, Nyirő Gergő wrote:
>nice until I have a single process to communicate with, but I want to
>cut my program
>into multiple processes, but I don't know how should I register the
>processes to avoid
>pid passing and run multiple process group on the same VM.

You already name all three processes according to if they were node
names. Can you be a bit more specific about what you intend to do?

Is giving names not good enough?
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: How to mimic Erlang nodes in PropEr statem test

Nyirő Gergő
On Wed, Jan 23, 2019 at 6:52 PM Fred Hebert <[hidden email]> wrote:

>
> On 01/22, Nyirő Gergő wrote:
> >nice until I have a single process to communicate with, but I want to
> >cut my program
> >into multiple processes, but I don't know how should I register the
> >processes to avoid
> >pid passing and run multiple process group on the same VM.
>
> You already name all three processes according to if they were node
> names. Can you be a bit more specific about what you intend to do?

Right now I have only one gen_server (crdt_server) per node, but I would
like to add an event handler (crdt_event) which could persist the content
of the crdt set or log the executed commands.

Since I just started to learn Erlang I have very limited ideas in
design choices,
that's why I'm looking for some advice. The following ideas came to my mind:

crdt_event could be registered with a fix name then all the
crdt_server processes
in the proper statem test will send the events to the same event handler, so
the event has to be extended with a reference to the sender (e.g: the name
or pid of the crdt_server). It seems too complicated for my situation.

Other solution would be to pass the NameOrPid of the crdt_event processes to
crdt_server processes, but a process registry could be a more elegant solution.

Should I use ct_property_test [1] instead?

p.s: Thanks for the fast feedback.

  [1]: http://erlang.org/doc/man/ct_property_test.html
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: How to mimic Erlang nodes in PropEr statem test

Fred Hebert-2
On 01/23, Nyirő Gergő wrote:
>
>Right now I have only one gen_server (crdt_server) per node, but I would
>like to add an event handler (crdt_event) which could persist the content
>of the crdt set or log the executed commands.
>

Okay, so that's essentially duplicating the messages: send them to the
server, but you want to asynchronously log with another process. Do I
understand this right?

>crdt_event could be registered with a fix name then all the
>crdt_server processes
>in the proper statem test will send the events to the same event handler, so
>the event has to be extended with a reference to the sender (e.g: the name
>or pid of the crdt_server). It seems too complicated for my situation.

Is the event handler only required for the tests? If so, that can make
sense. If you're working with the same design for your production
system, it would generally be a better idea to have one process that
handles the logging per CRDT server, assuming what you end up with is
one file per server, in order.

Using the same handler for multiple servers is a possibility, but you
have a lot more risk and complexity—as you noted, you'd need to start
identifying each message, rather than just giving the event manager a
destination where to output traffic—while coupling the runtime of
unrelated files.

>
>Other solution would be to pass the NameOrPid of the crdt_event processes to
>crdt_server processes, but a process registry could be a more elegant solution.
>

This is a possibility. There are other options such as:

- Each crdt_server is spawned under a crdt_sup. The crdt_sup works by
  booting two processes: crdt_log (first) and crdt_server (second). Each
  is passed a name that identifies the server ("crdt_1", `node_a`, or
  whatever)
- By using a dynamic process registry like gproc (see
  https://hex.pm/packages/gproc) and replacing the name registration
  from {local, Name} to {via, gproc, {n, l, {crdt_log, Name}}} and {via,
  gproc, {n, l, {crdt_server, Name}}} you can give them unique names
  that they can "know"
- On every call the crdt_server wants to log, it can call a function
  from the crdt_log module, such as crdt_log:do_log(Name, Contents)

If you implement the latter function as:

    -module(crdt_log).
   
    ...
   
    start_link(Name) ->
        %% {n, l, Name} stands for "{name, local, ActualName}" but gproc
        %% uses shorthand
        gen_server:start_link({via, gproc, {n, l, {crdt_log, Name}}},
                              ?MODULE, [], []).
   
    ...
   
    do_log(Name, Event) ->
        gen_server:cast({via, gproc, {n, l, {crdt_log, Name}}}, Event).
   
    ...

Then you'll be able to call the log process from within the other one
and send asynchronous events this way. You can then consider both
processes as one unit that fits under one supervisor. For your test, you
now want to boot 3 of these supervisors instead of only 3 servers, and
you should get a rather transparent layer added otherwise.


>Should I use ct_property_test [1] instead?
>

This is an experimental call or module to integrate the results of your
properties to the common test flow. You're free to use it if you want to
integrate everything into CT.

I personally maintain the rebar3 plugin for PropEr and I tend to prefer
it for some of the additional features it adds:

- meta functions
  https://github.com/ferd/rebar3_proper#per-properties-meta-functions 
  (which I might need to contribute upstream to PropEr instead)
- The ability to run a `rebar3 proper --retry` to get the last failing
  case run again
- The `rebar3 proper --store` call, which can be called after a failure
  to store the failing cases in a file that can be used to test
  regressions
- The `rebar3 proper --regressions` switch, which replays the previously
  stored couterexamples.

You can, of course, get all of this by doing more manual work in CT or
by transcribing counterexamples by hand into regression tests. I
personally just use the proper and CT commands distinctly, and instead
add a rebar3 alias for both:

    {alias, [{check, [ct, proper]}]}.

Which then lets me call 'rebar3 check' and runs both the CT and the
PropEr test suites.

Regards,
Fred.
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: How to mimic Erlang nodes in PropEr statem test

Stavros Aronis
Hi Gergő (and list),

before summer I was involved in writing a library for simulating
distributed Erlang systems on a single node:
https://github.com/klarna/vnet

Perhaps you may find some ideas from there useful. You can read a
paper about it (published in Erlang '18) by following the "Modelling
Distributed Erlang within a Single Node" link in
https://concuerror.com/publications (indirect link given to avoid ACMs
access restrictions).

An (admittedly poorly documented) example of its use (also discussed
in the paper) is available here:
https://github.com/klarna/vnet/tree/master/test/counter_server_example

Regards,
Stavros

On Fri, Jan 25, 2019 at 2:03 PM Fred Hebert <[hidden email]> wrote:

>
> On 01/23, Nyirő Gergő wrote:
> >
> >Right now I have only one gen_server (crdt_server) per node, but I would
> >like to add an event handler (crdt_event) which could persist the content
> >of the crdt set or log the executed commands.
> >
>
> Okay, so that's essentially duplicating the messages: send them to the
> server, but you want to asynchronously log with another process. Do I
> understand this right?
>
> >crdt_event could be registered with a fix name then all the
> >crdt_server processes
> >in the proper statem test will send the events to the same event handler, so
> >the event has to be extended with a reference to the sender (e.g: the name
> >or pid of the crdt_server). It seems too complicated for my situation.
>
> Is the event handler only required for the tests? If so, that can make
> sense. If you're working with the same design for your production
> system, it would generally be a better idea to have one process that
> handles the logging per CRDT server, assuming what you end up with is
> one file per server, in order.
>
> Using the same handler for multiple servers is a possibility, but you
> have a lot more risk and complexity—as you noted, you'd need to start
> identifying each message, rather than just giving the event manager a
> destination where to output traffic—while coupling the runtime of
> unrelated files.
>
> >
> >Other solution would be to pass the NameOrPid of the crdt_event processes to
> >crdt_server processes, but a process registry could be a more elegant solution.
> >
>
> This is a possibility. There are other options such as:
>
> - Each crdt_server is spawned under a crdt_sup. The crdt_sup works by
>   booting two processes: crdt_log (first) and crdt_server (second). Each
>   is passed a name that identifies the server ("crdt_1", `node_a`, or
>   whatever)
> - By using a dynamic process registry like gproc (see
>   https://hex.pm/packages/gproc) and replacing the name registration
>   from {local, Name} to {via, gproc, {n, l, {crdt_log, Name}}} and {via,
>   gproc, {n, l, {crdt_server, Name}}} you can give them unique names
>   that they can "know"
> - On every call the crdt_server wants to log, it can call a function
>   from the crdt_log module, such as crdt_log:do_log(Name, Contents)
>
> If you implement the latter function as:
>
>     -module(crdt_log).
>
>     ...
>
>     start_link(Name) ->
>         %% {n, l, Name} stands for "{name, local, ActualName}" but gproc
>         %% uses shorthand
>         gen_server:start_link({via, gproc, {n, l, {crdt_log, Name}}},
>                               ?MODULE, [], []).
>
>     ...
>
>     do_log(Name, Event) ->
>         gen_server:cast({via, gproc, {n, l, {crdt_log, Name}}}, Event).
>
>     ...
>
> Then you'll be able to call the log process from within the other one
> and send asynchronous events this way. You can then consider both
> processes as one unit that fits under one supervisor. For your test, you
> now want to boot 3 of these supervisors instead of only 3 servers, and
> you should get a rather transparent layer added otherwise.
>
>
> >Should I use ct_property_test [1] instead?
> >
>
> This is an experimental call or module to integrate the results of your
> properties to the common test flow. You're free to use it if you want to
> integrate everything into CT.
>
> I personally maintain the rebar3 plugin for PropEr and I tend to prefer
> it for some of the additional features it adds:
>
> - meta functions
>   https://github.com/ferd/rebar3_proper#per-properties-meta-functions
>   (which I might need to contribute upstream to PropEr instead)
> - The ability to run a `rebar3 proper --retry` to get the last failing
>   case run again
> - The `rebar3 proper --store` call, which can be called after a failure
>   to store the failing cases in a file that can be used to test
>   regressions
> - The `rebar3 proper --regressions` switch, which replays the previously
>   stored couterexamples.
>
> You can, of course, get all of this by doing more manual work in CT or
> by transcribing counterexamples by hand into regression tests. I
> personally just use the proper and CT commands distinctly, and instead
> add a rebar3 alias for both:
>
>     {alias, [{check, [ct, proper]}]}.
>
> Which then lets me call 'rebar3 check' and runs both the CT and the
> PropEr test suites.
>
> Regards,
> Fred.
> _______________________________________________
> erlang-questions mailing list
> [hidden email]
> http://erlang.org/mailman/listinfo/erlang-questions
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: How to mimic Erlang nodes in PropEr statem test

Nyirő Gergő
In reply to this post by Fred Hebert-2
On Fri, Jan 25, 2019 at 2:03 PM Fred Hebert <[hidden email]> wrote:

>
> On 01/23, Nyirő Gergő wrote:
> >
> >Right now I have only one gen_server (crdt_server) per node, but I would
> >like to add an event handler (crdt_event) which could persist the content
> >of the crdt set or log the executed commands.
> >
>
> Okay, so that's essentially duplicating the messages: send them to the
> server, but you want to asynchronously log with another process. Do I
> understand this right?

Yes, and I can also write the members of the CRDT set (which will be a
map in the final version) to disk with an extra event handler which
would be registered only in the production code.

> >Other solution would be to pass the NameOrPid of the crdt_event processes to
> >crdt_server processes, but a process registry could be a more elegant solution.
> >
>
> This is a possibility. There are other options such as:
>
> - Each crdt_server is spawned under a crdt_sup. The crdt_sup works by
>   booting two processes: crdt_log (first) and crdt_server (second). Each
>   is passed a name that identifies the server ("crdt_1", `node_a`, or
>   whatever)
> - By using a dynamic process registry like gproc (see
>   https://hex.pm/packages/gproc) and replacing the name registration
>   from {local, Name} to {via, gproc, {n, l, {crdt_log, Name}}} and {via,
>   gproc, {n, l, {crdt_server, Name}}} you can give them unique names
>   that they can "know"
> - On every call the crdt_server wants to log, it can call a function
>   from the crdt_log module, such as crdt_log:do_log(Name, Contents)

I think the dynamic process registry was that I was looking for.
(Good example, easy to understand).

> >Should I use ct_property_test [1] instead?
> >
>
> This is an experimental call or module to integrate the results of your
> properties to the common test flow. You're free to use it if you want to
> integrate everything into CT.

I misunderstood  the intention of the ct_property_test. I thought the test suite
parameterization and dynamic node creation of ct can be passed to PropEr tests.
But the warning is scary enough to avoid this solution:)

> I personally maintain the rebar3 plugin for PropEr and I tend to prefer
> it for some of the additional features it adds:

Nice plugin (I found it through hex), makes my work easier.

Thanks for the advice. Regards,
Gergő
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: How to mimic Erlang nodes in PropEr statem test

Nyirő Gergő
In reply to this post by Stavros Aronis
Hi Stavros,

thanks for the references looks interesting.
ConcuError was already on my learning plan, I will try with it.

Regards,
Gergő

On Fri, Jan 25, 2019 at 2:46 PM Stavros Aronis <[hidden email]> wrote:

> before summer I was involved in writing a library for simulating
> distributed Erlang systems on a single node:
> https://github.com/klarna/vnet
>
> Perhaps you may find some ideas from there useful. You can read a
> paper about it (published in Erlang '18) by following the "Modelling
> Distributed Erlang within a Single Node" link in
> https://concuerror.com/publications (indirect link given to avoid ACMs
> access restrictions).
>
> An (admittedly poorly documented) example of its use (also discussed
> in the paper) is available here:
> https://github.com/klarna/vnet/tree/master/test/counter_server_example
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions