summaryrefslogtreecommitdiff
path: root/lib/diameter/test
diff options
context:
space:
mode:
authorAnders Svensson <anders@erlang.org>2022-02-19 13:52:47 +0100
committerAnders Svensson <anders@erlang.org>2022-03-17 11:01:18 +0100
commit6089f9e57b4dc3c0426b64e1412f33b2a71f19e9 (patch)
treec5a2f5af5b7bc682ddb0e298c6246135102f8b80 /lib/diameter/test
parent75ae8344f215acf2f4133aa2518aa0094bf760c6 (diff)
downloaderlang-6089f9e57b4dc3c0426b64e1412f33b2a71f19e9.tar.gz
Rework diameter_{traffic,tls,transport}_SUITE
Make them runnable without common_test, by way of run/0, which is convenient for running suites easily from the shell; for example: $ env ERL_CRASH_DUMP_BYTES=0 erl -noinput -pa ebin -pa test -s diameter_traffic_SUITE run -s init stop Just crashing also provides better diagnostics than common_test often provides in the shell; for example: diameter_traffic_SUITE:init_per_group failed Reason: {badmatch,undefined} rand:uniform_s failed on line 334 Reason: {function_clause,[{rand,...},{...}|...]} Having to look in html pages to find details of failures like this isn't ideal. Testcases were also dependent on one another, so one failure could lead to several. Now run everthing that needs to be done in sequence, and different tests within a sequence in parallel. Multiple simultaneous connections in the transport suite are often refused on macOS, so be satisfied with one.
Diffstat (limited to 'lib/diameter/test')
-rw-r--r--lib/diameter/test/diameter_tls_SUITE.erl190
-rw-r--r--lib/diameter/test/diameter_traffic_SUITE.erl423
-rw-r--r--lib/diameter/test/diameter_transport_SUITE.erl123
3 files changed, 286 insertions, 450 deletions
diff --git a/lib/diameter/test/diameter_tls_SUITE.erl b/lib/diameter/test/diameter_tls_SUITE.erl
index 1ad897dcd2..4e8cde95d3 100644
--- a/lib/diameter/test/diameter_tls_SUITE.erl
+++ b/lib/diameter/test/diameter_tls_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -34,27 +34,15 @@
-module(diameter_tls_SUITE).
+%% testcases, no common_test dependency
+-export([run/0]).
+
+%% common_test wrapping
-export([suite/0,
all/0,
- groups/0,
init_per_suite/1,
- end_per_suite/1]).
-
-%% testcases
--export([start_ssl/1,
- start_diameter/1,
- make_certs/1, make_certs/0,
- start_services/1,
- add_transports/1,
- send1/1,
- send2/1,
- send3/1,
- send4/1,
- send5/1,
- remove_transports/1,
- stop_services/1,
- stop_diameter/1,
- stop_ssl/1]).
+ end_per_suite/1,
+ parallel/1]).
%% diameter callbacks
-export([prepare_request/3,
@@ -126,34 +114,22 @@
-define(LOGOUT, ?'DIAMETER_BASE_TERMINATION-CAUSE_LOGOUT').
%% ===========================================================================
+%% common_test wrapping
suite() ->
- [{timetrap, {seconds, 60}}].
+ [{timetrap, {seconds, 90}}].
all() ->
- [start_ssl,
- start_diameter,
- make_certs,
- start_services,
- add_transports,
- {group, all},
- {group, all, [parallel]},
- remove_transports,
- stop_services,
- stop_diameter,
- stop_ssl].
-
-groups() ->
- [{all, [], tc()}].
+ [parallel].
%% Shouldn't really have to know about crypto here but 'ok' from
%% ssl:start() isn't enough to guarantee that TLS is available.
init_per_suite(Config) ->
try
- false /= os:find_executable("openssl")
- orelse throw({?MODULE, no_openssl}),
- ok == (catch crypto:start())
- orelse throw({?MODULE, no_crypto}),
+ [] == (catch make_certs(dir(Config)))
+ orelse throw({?MODULE, no_certs}),
+ ok == crypto:start() orelse throw({?MODULE, no_crypto}),
+ ok == ssl:start() orelse throw({?MODULE, no_ssl}),
Config
catch
{?MODULE, E} ->
@@ -161,87 +137,81 @@ init_per_suite(Config) ->
end.
end_per_suite(_Config) ->
+ ssl:stop(),
crypto:stop().
-%% Testcases to run when services are started and connections
-%% established.
-tc() ->
- [send1,
- send2,
- send3,
- send4,
- send5].
-
-%% ===========================================================================
-%% testcases
-
-start_ssl(_Config) ->
- ok = ssl:start().
-
-start_diameter(_Config) ->
- ok = diameter:start().
+parallel(Config) ->
+ run(dir(Config), false).
-make_certs() ->
- [{timetrap, {minutes, 2}}].
+dir(Config) ->
+ proplists:get_value(priv_dir, Config).
-make_certs(Config) ->
- Dir = proplists:get_value(priv_dir, Config),
+%% ===========================================================================
- [] = ?util:run([[fun make_cert/2, Dir, B] || B <- ["server1",
- "server2",
- "server4",
- "server5",
- "client"]]).
+run() ->
+ Tmp = ?util:mktemp(filename:join(?util:tmpdir(), "diameter_tls")),
+ try
+ run(Tmp, true)
+ after
+ file:del_dir_r(Tmp)
+ end.
-start_services(Config) ->
- Dir = proplists:get_value(priv_dir, Config),
- Servers = [server(S, sopts(S, Dir)) || S <- ?SERVERS],
+run(Dir, B) ->
+ crypto:start(),
+ ssl:start(),
+ try
+ ?util:run([{[fun traffic/2, Dir, B], 60000}])
+ after
+ diameter:stop(),
+ ssl:stop(),
+ crypto:stop()
+ end.
+traffic(Dir, true) ->
+ [] = make_certs(Dir),
+ traffic(Dir, false);
+
+traffic(Dir, false) ->
+ ok = diameter:start(),
+ Servers = start_services(Dir),
+ Connections = add_transports(Dir, Servers),
+ [] = ?util:run([[fun call/1, S] || S <- ?util:scramble(?SERVERS)]),
+ [] = remove_transports(Connections),
+ [] = stop_services().
+
+make_certs(Dir) ->
+ ?util:run([[fun make_cert/2, Dir, B] || B <- ["server1",
+ "server2",
+ "server4",
+ "server5",
+ "client"]]).
+
+start_services(Dir) ->
+ Servers = [{S, {_,_} = server(S, sopts(S, Dir))} || S <- ?SERVERS],
ok = diameter:start_service(?CLIENT, ?SERVICE(?CLIENT, ?DICT_COMMON)),
+ Servers.
- {save_config, [Dir | Servers]}.
-
-add_transports(Config) ->
- {_, [Dir | Servers]} = proplists:get_value(saved_config, Config),
-
+add_transports(Dir, Servers) ->
true = diameter:subscribe(?CLIENT),
-
Opts = ssl_options(Dir, "client"),
- Connections = [connect(?CLIENT, S, copts(N, Opts))
- || {S,N} <- lists:zip(Servers, ?SERVERS)],
-
- ?util:write_priv(Config, "cfg", lists:zip(Servers, Connections)).
-
+ [{N, S, connect(?CLIENT, S, copts(N, Opts))} || {N,S} <- Servers].
%% Remove the client transports and expect the corresponding server
%% transport to go down.
-remove_transports(Config) ->
- Ts = ?util:read_priv(Config, "cfg"),
+remove_transports(Connections) ->
[] = [T || S <- ?SERVERS, T <- [diameter:subscribe(S)], T /= true],
- lists:map(fun disconnect/1, Ts).
+ [] = ?util:run([[fun disconnect/1, T] || T <- Connections]),
+ [S || S <- ?SERVERS,
+ I <- [receive #diameter_event{service = S, info = I} -> I end],
+ down /= catch element(1, I)].
-stop_services(_Config) ->
- [] = [{H,T} || H <- [?CLIENT | ?SERVERS],
- T <- [diameter:stop_service(H)],
- T /= ok].
+disconnect({_, {_LRef, _PortNr}, CRef}) ->
+ ok = diameter:remove_transport(?CLIENT, CRef).
-stop_diameter(_Config) ->
- ok = diameter:stop().
-
-stop_ssl(_Config) ->
- ok = ssl:stop().
-
-%% Send an STR intended for a specific server and expect success.
-send1(_Config) ->
- call(?SERVER1).
-send2(_Config) ->
- call(?SERVER2).
-send3(_Config) ->
- call(?SERVER3).
-send4(_Config) ->
- call(?SERVER4).
-send5(_Config) ->
- call(?SERVER5).
+stop_services() ->
+ [{H,T} || H <- [?CLIENT | ?SERVERS],
+ T <- [diameter:stop_service(H)],
+ T /= ok].
%% ===========================================================================
%% diameter callbacks
@@ -285,6 +255,7 @@ handle_request(#diameter_packet{msg = #diameter_base_STR{'Session-Id' = SId}},
%% ===========================================================================
%% support functions
+%% Send an STR intended for a specific server and expect success.
call(Server) ->
Realm = realm(Server),
Req = ['STR', {'Destination-Realm', Realm},
@@ -301,10 +272,6 @@ call(Req, Opts) ->
set([H|T], Vs) ->
[H | Vs ++ T].
-disconnect({{LRef, _PortNr}, CRef}) ->
- ok = diameter:remove_transport(?CLIENT, CRef),
- receive #diameter_event{info = {down, LRef, _, _}} -> ok end.
-
realm(Host) ->
tl(lists:dropwhile(fun(C) -> C /= $. end, Host)).
@@ -364,11 +331,12 @@ ssl([{ssl_options = T, Opts}]) ->
connect(Host, {_LRef, PortNr}, {Caps, Opts}) ->
{ok, Ref} = diameter:add_transport(Host, ?CONNECT(PortNr, Caps, Opts)),
- receive
- #diameter_event{service = Host,
- info = {up, Ref, _, _, #diameter_packet{}}} ->
- ok
- end,
+ {up, Ref, _, _, #diameter_packet{}}
+ = receive
+ #diameter_event{service = Host, info = Info}
+ when element(2, Info) == Ref ->
+ Info
+ end,
Ref.
copts(S, Opts)
diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl
index 81c10cc39f..95ea6be020 100644
--- a/lib/diameter/test/diameter_traffic_SUITE.erl
+++ b/lib/diameter/test/diameter_traffic_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2021. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,25 +25,17 @@
-module(diameter_traffic_SUITE).
+%% all tests, no common_test dependency
+-export([run/0,
+ run/1]).
+
+%% common_test wrapping
-export([suite/0,
all/0,
- groups/0,
- init_per_suite/0,
- init_per_suite/1,
- end_per_suite/1,
- init_per_group/1,
- init_per_group/2,
- end_per_group/2,
- init_per_testcase/2,
- end_per_testcase/2]).
+ parallel/1]).
%% testcases
--export([rfc4005/1,
- start/1,
- start_services/1,
- add_transports/1,
- result_codes/1,
- send_ok/1,
+-export([send_ok/1,
send_nok/1,
send_eval/1,
send_bad_answer/1,
@@ -97,11 +89,7 @@
send_multiple_filters_1/1,
send_multiple_filters_2/1,
send_multiple_filters_3/1,
- send_anything/1,
- remove_transports/1,
- empty/1,
- stop_services/1,
- stop/1]).
+ send_anything/1]).
%% diameter callbacks
-export([peer_up/4,
@@ -157,19 +145,18 @@
-define(RFCS, [rfc3588, rfc6733, rfc4005]).
%% Which transport protocol to use.
--define(TRANSPORTS, [tcp, sctp]).
-
--record(group,
- {transport,
- strings,
- encoding,
- client_service,
- client_dict,
- client_sender,
- server_service,
- server_decoding,
- server_sender,
- server_throttle}).
+-define(TRANSPORTS, [sctp || ?util:have_sctp()] ++ [tcp]).
+
+-record(group, {transport,
+ strings,
+ encoding,
+ client_service,
+ client_dict,
+ client_sender,
+ server_service,
+ server_decoding,
+ server_sender,
+ server_throttle}).
%% Not really what we should be setting unless the message is sent in
%% the common application but diameter doesn't care.
@@ -252,209 +239,156 @@
?'DIAMETER_BASE_TERMINATION-CAUSE_USER_MOVED').
%% ===========================================================================
+%% common_test wrapping
suite() ->
- [{timetrap, {seconds, 10}}].
+ [{timetrap, {seconds, 90}}].
all() ->
- [rfc4005, start, result_codes, {group, traffic}, empty, stop].
+ [parallel].
-%% Redefine this to run one or more groups for debugging purposes.
--define(GROUPS, []).
-%-define(GROUPS, [[sctp,rfc6733,record,map,false,false,true,false]]).
+parallel(_Config) ->
+ run().
-groups() ->
- [{traffic, [], tc()}].
+%% ===========================================================================
-%% --------------------
+%% run/0
+%%
+%% The test cases proper, do or (meaningfully) die.
+%%
+%% Randomly choose one of many configuration possibilities. Testing
+%% all of them takes too much time, and randomly skipping various
+%% cases (as used to be the case) just unnecessary complexity. There
+%% are run night after night in on various hosts, so just choosing a
+%% configuration results in sufficient coverage over time.
-init_per_suite() ->
- [{timetrap, {seconds, 60}}].
+run() ->
+ Svc = ?util:unique_string(),
+ run(#group{transport = ?util:choose(?TRANSPORTS),
+ strings = bool(),
+ encoding = ?util:choose(?ENCODINGS),
+ client_service = [$C | Svc],
+ client_dict = appdict(?util:choose(?RFCS)),
+ client_sender = bool(),
+ server_service = [$S | Svc],
+ server_decoding = ?util:choose(?DECODINGS),
+ server_sender = true, %% avoid deadlock
+ server_throttle = bool()}).
+
+%% run/1
+
+run(#group{} = Cfg) ->
+ _ = result_codes(Cfg),
+ io:format("config: ~p~n", [Cfg]),
+ try
+ ?util:run([{[fun traffic/1, Cfg], 60000}])
+ after
+ code:delete(nas4005),
+ code:purge(nas4005),
+ diameter:stop()
+ end.
+
+%% traffic/1
+
+traffic(#group{} = Cfg) ->
+ _ = compile_and_load(),
+ ok = diameter:start(),
+ LRef = server(Cfg),
+ ok = client(Cfg, LRef),
+ [] = send(Cfg),
+ ok = stop_services(Cfg),
+ [] = ets:tab2list(diameter_request).
-init_per_suite(Config) ->
- [{rfc4005, compile_and_load()}, {sctp, ?util:have_sctp()} | Config].
+%% start_service/2
-end_per_suite(_Config) ->
- code:delete(nas4005),
- code:purge(nas4005),
+start_service(Svc, Opts) ->
+ {ok, _} = {diameter:start_service(Svc, Opts), Opts},
ok.
-%% --------------------
+%% send/1
-init_per_group(_) ->
- [{timetrap, {seconds, 30}}].
+send(Cfg) ->
+ Ref = make_ref(),
+ Refs = [R || {F,1} <- module_info(exports),
+ "send_" ++ _ <- [atom_to_list(F)],
+ I <- [fun() -> exit({Ref, send(F, Cfg)}) end],
+ {_,R} <- [spawn_monitor(I)]],
+ lists:filter(fun({R,_}) -> R /= Ref; (_) -> true end, wait(Refs)).
-init_per_group(traffic, Config) ->
- Svc = ?util:unique_string(),
- Rec = #group{transport = choose([sctp || ?util:have_sctp()] ++ [tcp]),
- strings = bool(),
- encoding = choose(?ENCODINGS),
- client_service = [$C|Svc],
- client_dict = appdict(choose(?RFCS)),
- client_sender = bool(),
- server_service = [$S|Svc],
- server_decoding = choose(?DECODINGS),
- server_sender = true,
- server_throttle = bool()},
- io:format("config: ~p~n", [Rec]),
- init_per_group(config, [{group, Rec} | Config]);
-
-init_per_group(_, Config) ->
- start_services(Config),
- add_transports(Config),
- Config.
-
-end_per_group(traffic, Config) ->
- remove_transports(Config),
- stop_services(Config).
-
-%% --------------------
-
-%% Work around common_test accumulating Config improperly, causing
-%% testcases to get Config from groups and suites they're not in.
-init_per_testcase(N, Config)
- when N == rfc4005;
- N == start;
- N == result_codes;
- N == empty;
- N == stop ->
- Config;
-
-%% Skip testcases that can reasonably fail under SCTP.
-init_per_testcase(Name, Config) ->
- case [G || #group{transport = sctp} = G
- <- [proplists:get_value(group, Config)]]
- of
- [_] when Name == send_maxlen;
- Name == send_long ->
- {skip, sctp};
- _ ->
- [{testcase, Name} | Config]
- end.
+%% send/2
-end_per_testcase(_, _) ->
- ok.
+send(F, #group{transport = sctp})
+ when F == send_long;
+ F == send_maxlen ->
+ ok;
-%% --------------------
-
-%% Testcases to run when services are started and connections
-%% established.
-tc() ->
- [send_ok,
- send_nok,
- send_eval,
- send_bad_answer,
- send_protocol_error,
- send_experimental_result,
- send_arbitrary,
- send_proxy_info,
- send_unknown,
- send_unknown_short,
- send_unknown_mandatory,
- send_unknown_short_mandatory,
- send_noreply,
- send_grouped_error,
- send_unsupported,
- send_unsupported_app,
- send_error_bit,
- send_unsupported_version,
- send_long_avp_length,
- send_short_avp_length,
- send_zero_avp_length,
- send_invalid_avp_length,
- send_invalid_reject,
- send_unexpected_mandatory_decode,
- send_unexpected_mandatory,
- send_too_many,
- send_long,
- send_maxlen,
- send_nopeer,
- send_noapp,
- send_discard,
- send_any_1,
- send_any_2,
- send_all_1,
- send_all_2,
- send_timeout,
- send_error,
- send_detach,
- send_encode_error,
- send_destination_1,
- send_destination_2,
- send_destination_3,
- send_destination_4,
- send_destination_5,
- send_destination_6,
- send_bad_option_1,
- send_bad_option_2,
- send_bad_filter_1,
- send_bad_filter_2,
- send_bad_filter_3,
- send_bad_filter_4,
- send_multiple_filters_1,
- send_multiple_filters_2,
- send_multiple_filters_3,
- send_anything].
+send(F, Cfg) ->
+ timer:sleep(rand:uniform(2000)),
+ apply(?MODULE, F, [[{testcase, F}, {group, Cfg}]]).
-%% ===========================================================================
-%% start/stop testcases
+%% wait/1
-start(_Config) ->
- ok = diameter:start().
+wait(Refs)
+ when is_list(Refs) ->
+ lists:map(fun wait/1, Refs);
-start_services(Config) ->
- #group{client_service = CN,
- server_service = SN,
- server_decoding = SD}
- = Grp
- = group(Config),
- ok = diameter:start_service(SN, [{traffic_counters, bool()},
- {decode_format, SD}
- | ?SERVICE(SN, Grp)]),
- ok = diameter:start_service(CN, [{traffic_counters, bool()},
- {sequence, ?CLIENT_MASK},
- {decode_format, map},
- {strict_arities, decode}
- | ?SERVICE(CN, Grp)]).
+wait(MRef) ->
+ receive {'DOWN', MRef, process, _, T} -> T end.
-bool() ->
- 0.5 =< rand:uniform().
+%% ===========================================================================
-choose([_|_] = List) ->
- hd(lists:nthtail(rand:uniform(length(List)) - 1, List)).
+%% server/1
-add_transports(Config) ->
+server(Config) ->
#group{transport = T,
- encoding = E,
- client_service = CN,
client_sender = CS,
server_service = SN,
+ server_decoding = SD,
server_sender = SS,
server_throttle = ST}
+ = Grp
= group(Config),
- LRef = ?util:listen(SN,
- [T,
- {sender, SS},
- {message_cb, ST andalso {?MODULE, message, [0]}}]
- ++ [{packet, hd(?util:scramble([false, raw]))}
- || T == sctp andalso CS]
- ++ [{unordered, unordered()} || T == sctp],
- [{capabilities_cb, fun capx/2},
- {pool_size, 8}
- | server_apps()]),
- Cs = [?util:connect(CN,
- [T, {sender, CS} | client_opts(T)],
- LRef,
- [{id, Id}
- | client_apps(R, [{'Origin-State-Id', origin(Id)}])])
- || D <- ?DECODINGS, %% for multiple candidate peers
- R <- ?RFCS,
- R /= rfc4005 orelse have_nas(),
- Id <- [{D,E}]],
- ?util:write_priv(Config, "transport", [LRef | Cs]).
+ ok = start_service(SN, [{traffic_counters, bool()},
+ {decode_format, SD}
+ | ?SERVICE(SN, Grp)]),
+ Cfg = [{sender, SS},
+ {message_cb, ST andalso {?MODULE, message, [0]}}]
+ ++ [{packet, ?util:choose([false, raw])} || T == sctp andalso CS]
+ ++ [{unordered, unordered()} || T == sctp],
+ Opts = [{capabilities_cb, fun capx/2},
+ {pool_size, 8}
+ | server_apps()],
+ _LRef = ?util:listen(SN, [T | Cfg], Opts).
+
+%% client/1
+
+client(Config, LRef) ->
+ #group{transport = T,
+ encoding = E,
+ client_service = CN,
+ client_sender = CS}
+ = Grp
+ = group(Config),
+ ok = start_service(CN, [{traffic_counters, bool()},
+ {sequence, ?CLIENT_MASK},
+ {decode_format, map},
+ {strict_arities, decode}
+ | ?SERVICE(CN, Grp)]),
+ _ = [?util:connect(CN, [T | C], LRef, O)
+ || C <- [[{sender, CS} | client_opts(T)]],
+ D <- ?DECODINGS, %% for multiple candidate peers
+ R <- ?RFCS,
+ R /= rfc4005 orelse have_nas(),
+ I <- [{D,E}],
+ O <- [[{id, I}
+ | client_apps(R, [{'Origin-State-Id', origin(I)}])]]],
+ ok.
+
+bool() ->
+ 0.5 =< rand:uniform().
unordered() ->
- element(rand:uniform(4), {true, false, 1, 2}).
+ ?util:choose([true, false, 1, 2]).
client_opts(tcp) ->
[];
@@ -473,32 +407,19 @@ server_apps() ->
{capabilities, [{'Auth-Application-Id', [0] ++ [1 || B]}, %% common, NAS
{'Acct-Application-Id', [3]}]}]. %% accounting
+client_apps(rfc4005, Caps) ->
+ [{applications, [nas4005]},
+ {capabilities, [{'Auth-Application-Id', [1]}, %% NAS
+ {'Acct-Application-Id', []}
+ | Caps]}];
client_apps(D, Caps) ->
- if D == rfc4005 ->
- [{applications, [nas4005]},
- {capabilities, [{'Auth-Application-Id', [1]}, %% NAS
- {'Acct-Application-Id', []}
- | Caps]}];
- true ->
- D0 = dict0(D),
- [{applications, [acct(D0), D0]},
- {capabilities, Caps}]
- end.
+ D0 = dict0(D),
+ [{applications, [acct(D0), D0]},
+ {capabilities, Caps}].
have_nas() ->
false /= code:is_loaded(nas4005).
-remove_transports(Config) ->
- #group{client_service = CN,
- server_service = SN}
- = group(Config),
- [LRef | Cs] = ?util:read_priv(Config, "transport"),
- try
- [] = [T || C <- Cs, T <- [?util:disconnect(CN, C, SN, LRef)], T /= ok]
- after
- ok = diameter:remove_transport(SN, LRef)
- end.
-
stop_services(Config) ->
#group{client_service = CN,
server_service = SN}
@@ -506,24 +427,12 @@ stop_services(Config) ->
ok = diameter:stop_service(CN),
ok = diameter:stop_service(SN).
-%% Ensure even transports have been removed from request table.
-empty(_Config) ->
- [] = ets:tab2list(diameter_request).
-
-stop(_Config) ->
- ok = diameter:stop().
-
capx(_, #diameter_caps{origin_host = {OH,DH}}) ->
io:format("connection: ~p -> ~p~n", [DH,OH]),
ok.
%% ===========================================================================
-%% Fail only this testcase if the RFC 4005 dictionary hasn't been
-%% successfully compiled and loaded.
-rfc4005(Config) ->
- true = proplists:get_value(rfc4005, Config).
-
%% Ensure that result codes have the expected values.
result_codes(_Config) ->
{2001,
@@ -1041,6 +950,8 @@ send_anything(Config) ->
%% ===========================================================================
+group(#group{} = Rec) ->
+ Rec;
group(Config) ->
#group{} = proplists:get_value(group, Config).
@@ -1809,25 +1720,19 @@ message(ack, _, N) ->
%% ------------------------------------------------------------------------
compile_and_load() ->
- try
- Path = hd([P || H <- [[here(), ".."], [code:lib_dir(diameter)]],
- P <- [filename:join(H ++ ["examples",
- "dict",
- "rfc4005_nas.dia"])],
- {ok, _} <- [file:read_file_info(P)]]),
- {ok, [Forms]}
- = diameter_make:codec(Path, [return,
- forms,
- {name, "nas4005"},
- {prefix, "nas"},
- {inherits, "common/diameter_gen_base_rfc3588"}]),
- {ok, nas4005, Bin, []} = compile:forms(Forms, [debug_info, return]),
- {module, nas4005} = code:load_binary(nas4005, "nas4005", Bin),
- true
- catch
- E:R:Stack ->
- {E, R, Stack}
- end.
+ Path = hd([P || H <- [[here(), ".."], [code:lib_dir(diameter)]],
+ P <- [filename:join(H ++ ["examples",
+ "dict",
+ "rfc4005_nas.dia"])],
+ {ok, _} <- [file:read_file_info(P)]]),
+ Opts = [return,
+ forms,
+ {name, "nas4005"},
+ {prefix, "nas"},
+ {inherits, "common/diameter_gen_base_rfc3588"}],
+ {ok, [Forms]} = diameter_make:codec(Path, Opts),
+ {ok, nas4005, Bin, []} = compile:forms(Forms, [debug_info, return]),
+ {module, nas4005} = code:load_binary(nas4005, "nas4005", Bin).
here() ->
filename:dirname(code:which(?MODULE)).
diff --git a/lib/diameter/test/diameter_transport_SUITE.erl b/lib/diameter/test/diameter_transport_SUITE.erl
index 284d2b9566..9b763141ff 100644
--- a/lib/diameter/test/diameter_transport_SUITE.erl
+++ b/lib/diameter/test/diameter_transport_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2022. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -25,23 +25,17 @@
-module(diameter_transport_SUITE).
+%% all tests, no common_test dependency
+-export([run/0]).
+
+%% common_test wrapping
-export([suite/0,
all/0,
- groups/0,
- init_per_suite/1,
- end_per_suite/1]).
-
-%% testcases
--export([start/1,
- tcp_accept/1,
- tcp_connect/1,
- sctp_accept/1,
- sctp_connect/1,
- reconnect/1, reconnect/0,
- stop/1]).
+ parallel/1]).
-export([accept/1,
connect/1,
+ reconnect/1,
init/2]).
-include_lib("kernel/include/inet_sctp.hrl").
@@ -84,93 +78,63 @@
-define(SCTP(Sock, Data), {sctp, Sock, _, _, Data}).
%% ===========================================================================
+%% common_test wrapping
suite() ->
- [{timetrap, {seconds, 15}}].
+ [{timetrap, {seconds, 270}}].
all() ->
- [start,
- {group, all},
- {group, all, [parallel]},
- stop].
+ [parallel].
-groups() ->
- [{all, [], tc()}].
+parallel(_) ->
+ run().
-tc() ->
- [tcp_accept,
- tcp_connect,
- sctp_accept,
- sctp_connect,
- reconnect].
+%% ===========================================================================
-init_per_suite(Config) ->
- [{sctp, ?util:have_sctp()} | Config].
+%% run/0
-end_per_suite(_Config) ->
- ok.
+run() ->
+ ok = diameter:start(),
+ try
+ ?util:run([[fun run/1, {P,F}]
+ || P <- [sctp || ?util:have_sctp()] ++ [tcp],
+ F <- [connect, accept, reconnect]])
+ after
+ diameter:stop()
+ end.
-%% ===========================================================================
+%% run/1
-start(_Config) ->
- ok = diameter:start().
+run({Prot, reconnect}) ->
+ reconnect(Prot);
-stop(_Config) ->
- ok = diameter:stop().
+run({Prot, accept}) ->
+ accept(Prot);
+
+run({Prot, connect}) ->
+ connect(Prot).
%% ===========================================================================
-%% tcp_accept/1
-%% sctp_accept/1
+%% accept/1
%%
%% diameter transport accepting, test code connecting.
-tcp_accept(_) ->
- accept(tcp).
-
-sctp_accept(Config) ->
- case lists:member({sctp, true}, Config) of
- true -> accept(sctp);
- false -> {skip, no_sctp}
- end.
-
-%% Start multiple accepting transport processes that are connected to
-%% with an equal number of connecting processes using gen_tcp/sctp
-%% directly.
-
--define(PEER_COUNT, 8).
-
accept(Prot) ->
Ref = make_ref(),
true = diameter_reg:add_new({diameter_config, transport, Ref}), %% fake it
T = {Prot, Ref},
- [] = ?util:run(?util:scramble(acc(2*?PEER_COUNT, T, []))).
-
-acc(0, _, Acc) ->
- Acc;
-acc(N, T, Acc) ->
- acc(N-1, T, [{?MODULE, [init,
- element(1 + N rem 2, {accept, gen_connect}),
- T]}
- | Acc]).
+ ?util:run([{{?MODULE, [init, X, T]}, 15000}
+ || X <- [accept, gen_connect]]).
%% ===========================================================================
-%% tcp_connect/1
-%% sctp_connect/1
+%% connect/1
%%
%% Test code accepting, diameter transport connecting.
-tcp_connect(_) ->
- connect(tcp).
-
-sctp_connect(Config) ->
- case lists:member({sctp, true}, Config) of
- true -> connect(sctp);
- false -> {skip, no_sctp}
- end.
-
connect(Prot) ->
T = {Prot, make_ref()},
- [] = ?util:run([{?MODULE, [init, X, T]} || X <- [gen_accept, connect]]).
+ ?util:run([{{?MODULE, [init, X, T]}, 15000}
+ || X <- [gen_accept, connect]]).
%% ===========================================================================
%% reconnect/1
@@ -179,9 +143,6 @@ connect(Prot) ->
%% doesn't try to establish a new connection until the old one is
%% broken.
-reconnect() ->
- [{timetrap, {minutes, 4}}].
-
reconnect({listen, Ref}) ->
SvcName = make_ref(),
ok = start_service(SvcName),
@@ -222,10 +183,11 @@ reconnect({connect, Ref}) ->
MRef = erlang:monitor(process, Pid),
?RECV({'DOWN', MRef, process, _, _});
-reconnect(_) ->
+reconnect(Prot) ->
Ref = make_ref(),
- [] = ?util:run([{?MODULE, [reconnect, {T, Ref}]}
- || T <- [listen, connect]]).
+ ?util:run([{{?MODULE, [reconnect, {T, Ref}]}, 240000}
+ || Prot == tcp, %% ignore sctp
+ T <- [listen, connect]]).
start_service(SvcName) ->
OH = diameter_util:unique_string(),
@@ -430,8 +392,9 @@ gen_send(tcp, Sock, Bin) ->
gen_recv(sctp, Sock) ->
{_OS, _IS, Id} = getr(assoc),
receive
- ?SCTP(Sock, {[#sctp_sndrcvinfo{assoc_id = Id}], Bin})
+ ?SCTP(Sock, {[#sctp_sndrcvinfo{assoc_id = I}], Bin})
when is_binary(Bin) ->
+ {Id, _} = {I, Id}, %% assert
Bin
end;
gen_recv(tcp, Sock) ->