1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2015-2019. 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%% Test of the pool_size option in connecting nodes with multiple
23%% connections.
24%%
25
26-module(diameter_pool_SUITE).
27
28-export([suite/0,
29         all/0,
30         init_per_testcase/2,
31         end_per_testcase/2,
32         init_per_suite/1,
33         end_per_suite/1]).
34
35%% testcases
36-export([tcp_connect/1,
37         sctp_connect/1,
38         any_connect/1]).
39
40%% ===========================================================================
41
42-define(util, diameter_util).
43
44%% Config for diameter:start_service/2.
45-define(SERVICE(Host),
46        [{'Origin-Host', Host ++ ".ericsson.com"},
47         {'Origin-Realm', "ericsson.com"},
48         {'Host-IP-Address', [{127,0,0,1}]},
49         {'Vendor-Id', 12345},
50         {'Product-Name', "OTP/diameter"},
51         {'Auth-Application-Id', [0]},  %% common
52         {'Acct-Application-Id', [3]},  %% accounting
53         {restrict_connections, false},
54         {spawn_opt, {diameter_dist, route_session, []}},
55         {application, [{alias, common},
56                        {dictionary, diameter_gen_base_rfc6733},
57                        {module, diameter_callback}]},
58         {application, [{alias, accounting},
59                        {dictionary, diameter_gen_acct_rfc6733},
60                        {module, diameter_callback}]}]).
61
62%% ===========================================================================
63
64suite() ->
65    [{timetrap, {seconds, 30}}].
66
67all() ->
68    [tcp_connect,
69     sctp_connect,
70     any_connect].
71
72init_per_testcase(_Name, Config) ->
73    Config.
74
75end_per_testcase(_Name, _Config) ->
76    diameter:stop().
77
78init_per_suite(Config) ->
79    [{sctp, ?util:have_sctp()} | Config].
80
81end_per_suite(_Config) ->
82    ok.
83
84%% ===========================================================================
85
86tcp_connect(_Config) ->
87    connect(tcp, tcp).
88
89sctp_connect(Config) ->
90    case lists:member({sctp, true}, Config) of
91       true  -> connect(sctp, sctp);
92       false -> {skip, no_sctp}
93    end.
94
95any_connect(_Config) ->
96    connect(any, tcp).
97
98%% connect/2
99
100%% Establish multiple connections between a client and server.
101connect(ClientProt, ServerProt) ->
102    ok = diameter:start(),
103    [] = [{S,T} || S <- ["server", "client"],
104                   T <- [diameter:start_service(S, ?SERVICE(S))],
105                   T /= ok],
106    %% Listen with a single transport with pool_size = 4. Ensure the
107    %% expected number of transport processes are started.
108    LRef = ?util:listen("server", ServerProt, [{pool_size, 4}]),
109    {4,0} = count("server", LRef, accept), %% 4 transports, no connections
110    %% Establish 5 connections.
111    Ref = ?util:connect("client", ClientProt, LRef, [{pool_size, 5}]),
112    {5,5} = count("client", Ref, pool),    %% 5 connections
113    %% Ensure the server has started replacement transports within a
114    %% reasonable time. Sleepsince there's no guarantee the
115    %% replacements have been started before the client has received
116    %% 'up' events. (Although it's likely.)
117    sleep(),
118    {9,5} = count("server", LRef, accept), %% 5 connections + 4 accepting
119    %% Ensure there are still the expected number of accepting transports
120    %% after stopping the client service.
121    ok = diameter:stop_service("client"),
122    sleep(),
123    {4,0} = count("server", LRef, accept), %% 4 transports, no connections
124    %% Done.
125    ok = diameter:stop_service("server").
126
127count(Name, Ref, Key) ->
128    [{transport, [[{ref, Ref} | T]]},
129     {connections, Cs}]
130        = diameter:service_info(Name, [transport, connections]),
131    {Key, Ps} = lists:keyfind(Key, 1, T),
132    {length(Ps), length(Cs)}.  %% number of processes, connections
133
134sleep() ->
135    receive after 1000 -> ok end.
136