diff options
author | Anders Svensson <anders@erlang.org> | 2022-02-19 13:52:47 +0100 |
---|---|---|
committer | Anders Svensson <anders@erlang.org> | 2022-03-17 11:01:18 +0100 |
commit | 6089f9e57b4dc3c0426b64e1412f33b2a71f19e9 (patch) | |
tree | c5a2f5af5b7bc682ddb0e298c6246135102f8b80 /lib/diameter/test | |
parent | 75ae8344f215acf2f4133aa2518aa0094bf760c6 (diff) | |
download | erlang-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.erl | 190 | ||||
-rw-r--r-- | lib/diameter/test/diameter_traffic_SUITE.erl | 423 | ||||
-rw-r--r-- | lib/diameter/test/diameter_transport_SUITE.erl | 123 |
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) -> |