Skip to content

Commit

Permalink
Move one eqc to the test suite.
Browse files Browse the repository at this point in the history
This means you can run `rebar3 ct` to run the non EQC test cases, and if you
have access to EQC, you can run `rebar3 as eqc ct` to run with EQC tests
enabled as well.
  • Loading branch information
jlouis committed Jun 25, 2015
1 parent f371c1c commit a78258b
Show file tree
Hide file tree
Showing 6 changed files with 230 additions and 0 deletions.
1 change: 1 addition & 0 deletions rebar.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[].
1 change: 1 addition & 0 deletions test/Emakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{'*', [{d, 'EQC'}, debug_info]}.
2 changes: 2 additions & 0 deletions test/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
all:
erl -make
65 changes: 65 additions & 0 deletions test/fuse_eqc_SUITE.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
-module(fuse_eqc_SUITE).
-include_lib("common_test/include/ct.hrl").

-export([all/0]).
-export([groups/0]).
-export([suite/0]).
-export([init_per_suite/1]).
-export([end_per_suite/1]).
-export([init_per_group/2]).
-export([end_per_group/2]).

%% Tests.
-export([
fuse_time_seq/1,
fuse_time_par/1
]).

-ifdef(EQC).
-define(PRESENT, true).
-else.
-define(PRESENT, false).
-endif.

qc(Prop) ->
case eqc:counterexample(Prop) of
true ->
true;
false ->
exit(gave_up);
_quickcheck_CounterExample ->
exit(_quickcheck_CounterExample)
end.

%% ct.
all() -> [
fuse_time_seq,
fuse_time_par
].

groups() -> [].

suite() ->
[{timetrap, {minutes, 2}}].

init_per_suite(Config) ->
case ?PRESENT of
false -> {skip, no_quickcheck};
true -> Config
end.

end_per_suite(_Config) ->
ok.

init_per_group(_Group, Config) ->
Config.

end_per_group(_Group, _Config) ->
ok.

%% Tests.
fuse_time_seq(_Config) ->
qc(fuse_time_eqc:prop_seq()).

fuse_time_par(_Config) ->
qc(fuse_time_eqc:prop_par()).
63 changes: 63 additions & 0 deletions test/fuse_time_eqc.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
%%% @author Thomas Arts
%%% @copyright (C) 2014, Quviq AB
%%% @doc Showing that the fuse_time module behaves as expected
%%%
%%% @end
%%% Created : 26 Mar 2014 by Thomas Arts <[email protected]>

-module(fuse_time_eqc).
-compile(export_all).

-ifdef(EQC).
-include_lib("eqc/include/eqc.hrl").
-include_lib("eqc/include/eqc_statem.hrl").

initial_state() ->
{0,0,0}.

timestamp_command(_S) ->
{call, fuse_time_mock, timestamp, []}.

timestamp_next(_S, NewTime, []) ->
NewTime.

timestamp_post(S, [], NewTime) ->
S =< NewTime.

time_inc() ->
?LET(N, choose(0, 1000*1000),
N+1).

elapse_time_command(_S) ->
{call, fuse_time_mock, elapse_time, [time_inc()]}.

elapse_time_post(S, [_], NewTime) ->
less(S,NewTime).

less(X,Y) when X=<Y -> true;
less(X,Y) -> {X,'>=',Y}.


prop_seq() ->
?FORALL(Cmds, commands(?MODULE),
begin
fuse_time_mock:start({0,0,0}),
{H, S, Res} = run_commands(?MODULE,Cmds),
pretty_commands(?MODULE, Cmds, {H, S, Res},
Res == ok)
end).

prop_par() ->
?FORALL(Cmds, parallel_commands(?MODULE),
begin
fuse_time_mock:start({0,0,0}),
{H, S, Res} = run_parallel_commands(?MODULE,Cmds),
pretty_commands(?MODULE, Cmds, {H, S, Res},
Res == ok)
end).





-endif.
98 changes: 98 additions & 0 deletions test/fuse_time_mock.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
%%%-------------------------------------------------------------------
%%% @author Thomas Arts <>
%%% @copyright (C) 2014, Thomas Arts
%%% @doc
%%%
%%% @end
%%% Created : 26 Mar 2014 by Thomas Arts <>
%%%-------------------------------------------------------------------
-module(fuse_time_mock).

-include_lib("eqc/include/eqc.hrl").
-include_lib("pulse_otp/include/pulse_otp.hrl").

-export([start/1, init/2]).
-export([timestamp/0,elapse_time/1]).
-export([send_after/3, cancel_timer/1]).
-export([inc/2]).

-export([prop_inc/0]).

-define(UNIT,1000*1000).

send_after(_When, _Target, _Msg) -> make_ref().
cancel_timer(_Ref) -> 0.

timestamp() ->
?MODULE ! {timestamp, self()},
receive
{timestamp, Time} -> Time
after 1000 ->
exit(timeout)
end.

elapse_time(N) ->
?MODULE ! {elapse, self(), N},
receive
{timestamp, Time} -> Time
after 1000 ->
exit(timeout)
end.

start(Time) ->
case whereis(?MODULE) of
Pid when is_pid(Pid) ->
Pid ! {reset, self(), Time},
receive
ok -> ok
end;
undefined ->
spawn_link(?MODULE, init, [self(), Time]),
receive
ok -> ?MODULE
end
end.

init(From, Time) ->
register(?MODULE, self()),
From ! ok,
loop(Time).

loop(Time) ->
receive
{timestamp, From} ->
From ! {timestamp, Time},
loop(inc(Time,0));
{elapse, From, N} ->
NewTime = inc(Time,N),
From ! {timestamp, NewTime},
loop(NewTime);
{reset, From, RTime} ->
From ! ok,
loop(RTime);
stop ->
Time
end.

inc({Mega,One,Mili},N) ->
inc({Mega,One,Mili},N,?UNIT).

inc({Mega,One,Micro}, N, Unit) ->
NewTime = Mega*Unit*Unit + One*Unit + Micro + N,
NMega = NewTime div (Unit*Unit),
NOne = (NewTime rem (Unit*Unit)) div Unit,
NMicro = NewTime rem Unit,
{NMega, NOne, NMicro}.

prop_inc() ->
?FORALL(Base, choose(2,10),
?FORALL({Time,N}, {{choose(0,Base-1),choose(0,Base-1),choose(0,Base-1)},choose(0,Base*Base+1)},
begin
{Me,One,Mi} = inc(Time,N,Base),
?WHENFAIL(io:format("Computed: ~p\n",[{Me,One,Mi}]),
Me<Base*Base andalso One<Base andalso Mi<Base)
end)).




0 comments on commit a78258b

Please sign in to comment.