1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20
21%%
22%% Tests of the server implemented by diameter_sync.erl.
23%%
24
25-module(diameter_sync_SUITE).
26
27-export([suite/0,
28         all/0,
29         groups/0,
30         init_per_suite/1,
31         end_per_suite/1]).
32
33%% testcases
34-export([call/1,
35         cast/1,
36         timeout/1,
37         flush/1]).
38
39-define(sync, diameter_sync).
40-define(util, diameter_util).
41
42-define(TIMEOUT, infinity).
43
44%% ===========================================================================
45
46suite() ->
47    [{timetrap, {seconds, 60}}].
48
49all() ->
50    [{group, all},
51     {group, all, [parallel]}].
52
53groups() ->
54    [{all, [], tc()}].
55
56tc() ->
57    [call,
58     cast,
59     timeout,
60     flush].
61
62init_per_suite(Config) ->
63    ok = diameter:start(),
64    Config.
65
66end_per_suite(_Config) ->
67    ok = diameter:stop().
68
69%% ===========================================================================
70
71call(_) ->
72    Ref = make_ref(),
73    Q = {q, Ref},
74    F = fun() -> Ref end,
75    Ref = ?sync:call(Q, F, infinity, ?TIMEOUT),
76    Ref = ?sync:call(Q, F, 0, infinity),
77    Ref = call(Q, F),
78    Ref = call(Q, {fun(_) -> Ref end, x}),
79    timeout = call(Q, fun() -> exit(unexpected) end),
80    {_,_,_} = call(Q, {erlang, now, []}),
81    {_,_,_} = call(Q, [fun erlang:now/0]).
82
83cast(_) ->
84    Ref = make_ref(),
85    Q = {q, Ref},
86    false = ?sync:carp(Q),
87    [] = ?sync:pids(Q),
88    %% Queue a request that blocks until we send it Ref and another
89    %% that exits with Ref.
90    ok = cast(Q, fun() -> receive Ref -> ok end end),
91    ok = cast(Q, fun() -> exit(Ref) end),
92    [_,Pid] = ?sync:pids(Q),
93    %% Ensure some expected truths ...
94    2 = ?sync:pending(Q),
95    true = 2 =< ?sync:pending(),
96    true = lists:member(Q, ?sync:queues()),
97    %% ... and that the max number of requests is respected.
98    rejected = ?sync:call(Q, {erlang, now, []}, 1, ?TIMEOUT),
99    rejected = ?sync:cast(Q, {erlang, now, []}, 1, ?TIMEOUT),
100    %% Monitor on the identifiable request and see that exits when we
101    %% let the blocking request finish.
102    MRef = erlang:monitor(process, Pid),
103    {value, P} = ?sync:carp(Q),
104    P ! Ref,
105    Ref = receive
106              {'DOWN', MRef, process, _, Reason} ->
107                  Reason
108          after ?TIMEOUT ->
109                  false
110          end.
111
112timeout(_) ->
113    Q = make_ref(),
114    ok = ?sync:cast(Q, {timer, sleep, [2000]}, infinity, 2000),
115    timeout = ?sync:call(Q, fun() -> ok end, infinity, 1000).
116
117flush(_) ->
118    Q = make_ref(),
119    F = {timer, sleep, [2000]},
120    ok = cast(Q, F),
121    ok = cast(Q, F),
122    1 = ?sync:flush(Q).
123
124%% ===========================================================================
125
126call(Q, Req) ->
127    sync(call, Q, Req).
128
129cast(Q, Req) ->
130    sync(cast, Q, Req).
131
132sync(F, Q, Req) ->
133    ?sync:F(Q, Req, infinity, infinity).
134