[[concuerror]]
== Concuerror

https://concuerror.com/[Concuerror] is a stateless model
checking tool for Erlang programs. It can be used to detect
and debug concurrency errors, such as deadlocks and errors
due to race conditions. The key property of such errors is
that they only occur on few, specific schedulings of the
program. Moreover, unlike tools based on randomisation,
Concuerror can verify the absence of such errors, because
it tests the program systematically.

Erlang.mk provides a wrapper around Concuerror.

=== Configuration

The `CONCUERROR_TESTS` variable must be defined in order to
use Concuerror. It lists the Concuerror test cases. There
is currently no way to detect test cases automatically. The
tests must be listed as `module:function` separated by
whitespace. For example:

[source,make]
CONCUERROR_TESTS = ranch_concuerror:start_stop ranch_concuerror:info

Concuerror will output some information directly on the
screen when run, but errors will only be written to a file.
This is because the error output can be very large. By
default Erlang.mk instructs Concuerror to save log files
in the 'logs/' directory (shared with Common Test). This
can be changed by setting `CONCUERROR_LOGS_DIR`:

[source,make]
CONCUERROR_LOGS_DIR = $(CURDIR)/path/to/logs

Concuerror options can be specified using the
`CONCUERROR_OPTS` variable:

[source,make]
CONCUERROR_OPTS = -k

Note that options may also be specified on a per-module
basis using the `-concuerror_options([]).` attribute.

=== Writing tests

Concuerror tests are a simple 0-arity function that must
be exported. For example:

[source,erlang]
----
-export([info/0]).

info() →
    %% Ensure we can call ranch:info/1 after starting a listener.
    SupPid = do_start(),
    {ok, _} = ranch:start_listener(?FUNCTION_NAME,
        ranch_erlang_transport, #{
            num_acceptors ⇒ 1
        },
        echo_protocol, []),
    #{} = ranch:info(?FUNCTION_NAME),
    do_stop(SupPid).
----

Do not forget to add the function to `CONCUERROR_TESTS`
as well.

=== Usage

To run Concuerror:

[source,bash]
$ make concuerror

Erlang.mk will create an index of all the test logs in
the '$(CONCUERROR_LOGS_DIR)/concuerror.html' file.
