diff options
31 files changed, 1894 insertions, 1940 deletions
diff --git a/lib/diameter/src/transport/diameter_tcp.erl b/lib/diameter/src/transport/diameter_tcp.erl index 9ac9f2d59c..f40f2b1fc4 100644 --- a/lib/diameter/src/transport/diameter_tcp.erl +++ b/lib/diameter/src/transport/diameter_tcp.erl @@ -43,6 +43,7 @@ -export([listener/1,%% diameter_sync callback info/1]). %% service_info callback +%% test -export([ports/0, ports/1]). @@ -450,16 +451,20 @@ sock(_, Sock) -> resolve(Type, S) -> Sock = sock(Type, S), try - ok(portnr(Sock)) + {ok, T} = portnr(Sock), + T catch _:_ -> Sock end. -portnr(Sock) - when is_port(Sock) -> - portnr(gen_tcp, Sock); +%% Assume either ssl or gen_tcp. In particular, this can't deal with a +%% transport module that called start/3 with an own module option. portnr(Sock) -> - portnr(ssl, Sock). + try + {ok, _} = portnr(ssl, Sock) + catch + _:_ -> portnr(gen_tcp, Sock) + end. %% --------------------------------------------------------------------------- %% # handle_call/3 diff --git a/lib/diameter/test/Makefile b/lib/diameter/test/Makefile index b537292834..3ae0f8eaf8 100644 --- a/lib/diameter/test/Makefile +++ b/lib/diameter/test/Makefile @@ -91,8 +91,6 @@ info: @echo ======================================== @$(call list,MODULES) @echo - @$(call list,HRL_FILES) - @echo @$(call list,SUITES) @echo @echo erl = $(shell which erl) @@ -116,6 +114,7 @@ help: @echo @echo " $(SUITES):" @echo " Compile and run a specific test suite." + @echo " Prefix with _ to run without common_test." @echo @echo " clean | realclean:" @echo " Remove generated files." @@ -142,6 +141,14 @@ $(SUITES): log opt | awk '{print} / FAILED /{rc=1} END{exit rc}' rc=0 # Shorter in sed but requires a GNU extension (ie. Q). +# Run suites without common_test. +$(SUITES:%=_%): opt + $(ERL) -noinput \ + -pa ../ebin \ + -sname diameter_test_$@ \ + -s diameter$@_SUITE run \ + -s init stop + cover: log opt coverspec $(ERL) -noinput \ -pa $(realpath ../ebin) \ @@ -173,7 +180,6 @@ release_tests_spec: $(INSTALL_DIR) "$(RELSYSDIR)" $(INSTALL_DATA) $(TEST_SPEC_FILE) \ $(COVER_SPEC_FILE) \ - $(HRL_FILES) \ "$(RELSYSDIR)" $(MAKE) $(DATA_DIRS:%/=release_data_%) $(MAKE) $(ERL_FILES:%=/%) diff --git a/lib/diameter/test/diameter.spec b/lib/diameter/test/diameter.spec index fae7863bec..be62bb7f2b 100644 --- a/lib/diameter/test/diameter.spec +++ b/lib/diameter/test/diameter.spec @@ -1 +1,2 @@ {suites, "../diameter_test", all}. +{skip_suites, "../diameter_test", [diameter_gen_sctp_SUITE], "Fails due to suspect gen_sctp behaviour."}. diff --git a/lib/diameter/test/diameter_3xxx_SUITE.erl b/lib/diameter/test/diameter_3xxx_SUITE.erl index 0f060c4ba7..63de2467a3 100644 --- a/lib/diameter/test/diameter_3xxx_SUITE.erl +++ b/lib/diameter/test/diameter_3xxx_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2013-2016. All Rights Reserved. +%% Copyright Ericsson AB 2013-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. @@ -26,19 +26,17 @@ -module(diameter_3xxx_SUITE). +%% testcases, no common_test dependency +-export([run/0, + run/1]). + +%% common_test wrapping -export([suite/0, all/0, - groups/0, - init_per_suite/1, - end_per_suite/1, - init_per_group/2, - end_per_group/2, - init_per_testcase/2, - end_per_testcase/2]). - -%% testcases --export([start/1, - send_unknown_application/1, + traffic/1]). + +%% internal +-export([send_unknown_application/1, send_unknown_command/1, send_ok/1, send_invalid_hdr_bits/1, @@ -47,9 +45,7 @@ send_5xxx_missing_avp/1, send_double_error/1, send_3xxx/1, - send_5xxx/1, - counters/1, - stop/1]). + send_5xxx/1]). %% diameter callbacks -export([peer_up/3, @@ -67,11 +63,7 @@ %% =========================================================================== -define(util, diameter_util). --define(testcase(), proplists:get_value(testcase, get(?MODULE))). --define(group(Config), begin - put(?MODULE, Config), - ?util:name(proplists:get_value(group, Config)) - end). +-define(testcase(), get(?MODULE)). -define(L, atom_to_list). -define(A, list_to_atom). @@ -106,34 +98,15 @@ %% =========================================================================== suite() -> - [{timetrap, {seconds, 60}}]. + [{timetrap, {seconds, 90}}]. all() -> - [{group, ?util:name([E,D])} || E <- ?ERRORS, D <- ?RFCS]. - -groups() -> - Tc = tc(), - [{?util:name([E,D]), [], [start] ++ Tc ++ [counters, stop]} - || E <- ?ERRORS, D <- ?RFCS]. - -init_per_suite(Config) -> - ok = diameter:start(), - Config. + [traffic]. -end_per_suite(_Config) -> - ok = diameter:stop(). +traffic(_Config) -> + run(). -init_per_group(Group, Config) -> - [{group, Group} | Config]. - -end_per_group(_, _) -> - ok. - -init_per_testcase(Name, Config) -> - [{testcase, Name} | Config]. - -end_per_testcase(_, _) -> - ok. +%% =========================================================================== tc() -> [send_unknown_application, @@ -147,25 +120,36 @@ tc() -> send_3xxx, send_5xxx]. -%% =========================================================================== +%% run/0 + +run() -> + ?util:run([[{{?MODULE, run, [{E,D}]}, 60000} || E <- ?ERRORS, + D <- ?RFCS]]). + +%% run/1 -%% start/1 +run({F, [_,_] = G}) -> + put(?MODULE, F), + apply(?MODULE, F, [G]); -start(Config) -> - Group = proplists:get_value(group, Config), - [Errors, RFC] = ?util:name(Group), - ok = diameter:start_service(?SERVER, ?SERVICE(?L(Group), - Errors, - RFC)), +run({E,D}) -> + try + run([E,D]) + after + ok = diameter:stop() + end; + +run([Errors, RFC] = G) -> + Name = ?L(Errors) ++ "," ++ ?L(RFC), + ok = diameter:start(), + ok = diameter:start_service(?SERVER, ?SERVICE(Name, Errors, RFC)), ok = diameter:start_service(?CLIENT, ?SERVICE(?CLIENT, callback, rfc6733)), LRef = ?util:listen(?SERVER, tcp), - ?util:connect(?CLIENT, tcp, LRef). - -%% stop/1 - -stop(_Config) -> + ?util:connect(?CLIENT, tcp, LRef), + ?util:run([{?MODULE, run, [{F,G}]} || F <- tc()]), + _ = counters(G), ok = diameter:remove_transport(?CLIENT, true), ok = diameter:remove_transport(?SERVER, true), ok = diameter:stop_service(?SERVER), @@ -175,9 +159,7 @@ stop(_Config) -> %% %% Check that counters are as expected. -counters(Config) -> - Group = proplists:get_value(group, Config), - [_Errors, _Rfc] = G = ?util:name(Group), +counters([_Errors, _RFC] = G) -> [] = ?util:run([[fun counters/3, K, S, G] || K <- [statistics, transport, connections], S <- [?CLIENT, ?SERVER]]). @@ -379,10 +361,7 @@ send_unknown_application([_,_]) -> %% UNSUPPORTED_APPLICATION 'Failed-AVP' = [], 'AVP' = []} - = call(); - -send_unknown_application(Config) -> - send_unknown_application(?group(Config)). + = call(). %% send_unknown_command/1 %% @@ -398,10 +377,7 @@ send_unknown_command([_,_]) -> %% UNSUPPORTED_COMMAND 'Failed-AVP' = [], 'AVP' = []} - = call(); - -send_unknown_command(Config) -> - send_unknown_command(?group(Config)). + = call(). %% send_ok/1 %% @@ -412,10 +388,7 @@ send_ok([_,_]) -> #diameter_base_STA{'Result-Code' = 5002, %% UNKNOWN_SESSION_ID 'Failed-AVP' = [], 'AVP' = []} - = call(); - -send_ok(Config) -> - send_ok(?group(Config)). + = call(). %% send_invalid_hdr_bits/1 %% @@ -433,10 +406,7 @@ send_invalid_hdr_bits([_,_]) -> #'diameter_base_answer-message'{'Result-Code' = 3008, %% INVALID_HDR_BITS 'Failed-AVP' = [], 'AVP' = []} - = call(); - -send_invalid_hdr_bits(Config) -> - send_invalid_hdr_bits(?group(Config)). + = call(). %% send_missing_avp/1 %% @@ -454,10 +424,7 @@ send_missing_avp([_,_]) -> #diameter_base_STA{'Result-Code' = 5005, %% MISSING_AVP 'Failed-AVP' = [_], 'AVP' = []} - = call(); - -send_missing_avp(Config) -> - send_missing_avp(?group(Config)). + = call(). %% send_ignore_missing_avp/1 %% @@ -475,10 +442,7 @@ send_ignore_missing_avp([_,_]) -> #diameter_base_STA{'Result-Code' = 2001, %% SUCCESS 'Failed-AVP' = [], 'AVP' = []} - = call(); - -send_ignore_missing_avp(Config) -> - send_ignore_missing_avp(?group(Config)). + = call(). %% send_5xxx_missing_avp/1 %% @@ -501,10 +465,7 @@ send_5xxx_missing_avp([_,_]) -> #diameter_base_STA{'Result-Code' = 2001, %% SUCCESS 'Failed-AVP' = [], 'AVP' = []} - = call(); - -send_5xxx_missing_avp(Config) -> - send_5xxx_missing_avp(?group(Config)). + = call(). %% send_double_error/1 %% @@ -522,10 +483,7 @@ send_double_error([_,_]) -> #'diameter_base_answer-message'{'Result-Code' = 3008, %% INVALID_HDR_BITS 'Failed-AVP' = [], 'AVP' = []} - = call(); - -send_double_error(Config) -> - send_double_error(?group(Config)). + = call(). %% send_3xxx/1 %% @@ -536,10 +494,7 @@ send_3xxx([_,_]) -> #'diameter_base_answer-message'{'Result-Code' = 3999, 'Failed-AVP' = [], 'AVP' = []} - = call(); - -send_3xxx(Config) -> - send_3xxx(?group(Config)). + = call(). %% send_5xxx/1 %% @@ -555,10 +510,7 @@ send_5xxx([_,_]) -> #'diameter_base_answer-message'{'Result-Code' = 5999, 'Failed-AVP' = [], 'AVP' = []} - = call(); - -send_5xxx(Config) -> - send_5xxx(?group(Config)). + = call(). %% =========================================================================== diff --git a/lib/diameter/test/diameter_app_SUITE.erl b/lib/diameter/test/diameter_app_SUITE.erl index ef4a28d3f4..0211ab1982 100644 --- a/lib/diameter/test/diameter_app_SUITE.erl +++ b/lib/diameter/test/diameter_app_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2018. 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. @@ -24,22 +24,24 @@ -module(diameter_app_SUITE). +%% testcases, no common_test dependency +-export([run/0, + run/1]). + +%% common_test wrapping -export([suite/0, - all/0, - init_per_suite/1, - end_per_suite/1]). + all/0]). %% testcases -export([keys/1, vsn/1, - modules/1, - exports/1, + modules/1, + exports/1, release/1, - xref/1, + xref/1, relup/1]). --include("diameter_ct.hrl"). - +-define(util, diameter_util). -define(A, list_to_atom). %% Modules not in the app and that should not have dependencies on it @@ -57,7 +59,7 @@ %% =========================================================================== suite() -> - [{timetrap, {seconds, 60}}]. + [{timetrap, {seconds, 20}}]. all() -> [keys, @@ -68,12 +70,22 @@ all() -> xref, relup]. -init_per_suite(Config) -> - [{application, ?APP, App}] = diameter_util:consult(?APP, app), - [{app, App} | Config]. +%% =========================================================================== + +run() -> + run(all()). + +run(List) -> + Tmp = ?util:mktemp(filename:join(?util:tmpdir(), "diameter_app")), + try + run([{priv_dir, Tmp}], List) + after + file:del_dir_r(Tmp) + end. -end_per_suite(_Config) -> - ok. +run(Config, List) -> + [{application, diameter, App}] = ?util:consult(diameter, app), + ?util:run([{{?MODULE, F, [{App, Config}]}, 10000} || F <- List]). %% =========================================================================== %% # keys/1 @@ -82,10 +94,12 @@ end_per_suite(_Config) -> %% also be caught by other testcases. %% =========================================================================== -keys(Config) -> - App = fetch(app, Config), +keys({App, _Config}) -> [] = lists:filter(fun(K) -> not lists:keymember(K, 1, App) end, - [vsn, description, modules, registered, applications]). + [vsn, description, modules, registered, applications]); + +keys(Config) -> + run(Config, [keys]). %% =========================================================================== %% # vsn/1 @@ -93,8 +107,11 @@ keys(Config) -> %% Ensure that our app version sticks to convention. %% =========================================================================== +vsn({App, _Config}) -> + true = is_vsn(fetch(vsn, App)); + vsn(Config) -> - true = is_vsn(fetch(vsn, fetch(app, Config))). + run(Config, [vsn]). %% =========================================================================== %% # modules/1 @@ -103,15 +120,17 @@ vsn(Config) -> %% compiler/info modules. %% =========================================================================== -modules(Config) -> - Mods = fetch(modules, fetch(app, Config)), +modules({App, _Config}) -> + Mods = fetch(modules, App), Installed = code_mods(), Help = lists:sort(?INFO_MODULES ++ ?COMPILER_MODULES), + {[], Help} = {Mods -- Installed, lists:sort(Installed -- Mods)}; - {[], Help} = {Mods -- Installed, lists:sort(Installed -- Mods)}. +modules(Config) -> + run(Config, [modules]). code_mods() -> - Dir = code:lib_dir(?APP, ebin), + Dir = code:lib_dir(diameter, ebin), {ok, Files} = file:list_dir(Dir), [?A(lists:reverse(R)) || N <- Files, "maeb." ++ R <- [lists:reverse(N)]]. @@ -121,9 +140,12 @@ code_mods() -> %% Ensure that no module does export_all. %% =========================================================================== +exports({App, _Config}) -> + Mods = fetch(modules, App), + [] = [M || M <- Mods, exports_all(M)]; + exports(Config) -> - Mods = fetch(modules, fetch(app, Config)), - [] = [M || M <- Mods, exports_all(M)]. + run(Config, [exports]). exports_all(Mod) -> Opts = fetch(options, Mod:module_info(compile)), @@ -136,8 +158,7 @@ exports_all(Mod) -> %% Ensure that it's possible to build a minimal release with our app file. %% =========================================================================== -release(Config) -> - App = fetch(app, Config), +release({App, Config}) -> Rel = {release, {"diameter test release", fetch(vsn, App)}, {erts, erlang:system_info(version)}, @@ -146,13 +167,16 @@ release(Config) -> ok = write_file(filename:join([Dir, "diameter_test.rel"]), Rel), {ok, _, []} = systools:make_script("diameter_test", [{path, [Dir]}, {outdir, Dir}, - silent]). + silent]); + +release(Config) -> + run(Config, [release]). %% sasl need to be included to avoid a missing_sasl warning, error %% in the case of relup/1. appvsn(Name) -> - [{application, Name, App}] = diameter_util:consult(Name, app), + [{application, Name, App}] = ?util:consult(Name, app), fetch(vsn, App). %% =========================================================================== @@ -162,8 +186,7 @@ appvsn(Name) -> %% or one in an application we haven't declared as a dependency. (Almost.) %% =========================================================================== -xref(Config) -> - App = fetch(app, Config), +xref({App, _Config}) -> Mods = fetch(modules, App), %% modules listed in the app file %% List of application names extracted from runtime_dependencies. @@ -179,7 +202,7 @@ xref(Config) -> %% the sense that there's no .app file, and isn't listed in %% applications. ok = lists:foreach(fun(A) -> add_application(XRef, A) end, - [?APP, erts | fetch(applications, App)]), + [diameter, erts | fetch(applications, App)]), {ok, Undefs} = xref:analyze(XRef, undefined_function_calls), {ok, RTmods} = xref:analyze(XRef, {module_use, Mods}), @@ -212,7 +235,10 @@ xref(Config) -> %% The declared application versions are ignored since we only %% know what we see now. [] = lists:filter(fun(M) -> not lists:member(app(M), Deps) end, - RTdeps -- Mods). + RTdeps -- Mods); + +xref(Config) -> + run(Config, [xref]). ignored({FromMod,_,_}, {ToMod,_,_} = To, Rel)-> %% diameter_tcp does call ssl despite the latter not being listed @@ -281,7 +307,7 @@ add_application(XRef, App, Dir) {ok, App} = xref:add_application(XRef, Dir, []). make_name(Suf) -> - list_to_atom(atom_to_list(?APP) ++ "_" ++ atom_to_list(Suf)). + list_to_atom("diameter_" ++ atom_to_list(Suf)). %% =========================================================================== %% # relup/1 @@ -289,11 +315,10 @@ make_name(Suf) -> %% Ensure that we can generate release upgrade files using our appup file. %% =========================================================================== -relup(Config) -> - [{Vsn, Up, Down}] = diameter_util:consult(?APP, appup), +relup({App, Config}) -> + [{Vsn, Up, Down}] = ?util:consult(diameter, appup), true = is_vsn(Vsn), - App = fetch(app, Config), Rel = [{erts, erlang:system_info(version)} | [{A, appvsn(A)} || A <- [sasl | fetch(applications, App)]]], @@ -314,7 +339,10 @@ relup(Config) -> {ok, _, _, []} = systools:make_relup(Name, UpFrom, DownTo, [{path, [Dir]}, {outdir, Dir}, - silent]). + silent]); + +relup(Config) -> + run(Config, [relup]). acc_rel(Dir, Rel, List) -> lists:foldl(fun(T,A) -> acc_rel(Dir, Rel, T, A) end, diff --git a/lib/diameter/test/diameter_capx_SUITE.erl b/lib/diameter/test/diameter_capx_SUITE.erl index 51b6c1d7f2..852450bc9f 100644 --- a/lib/diameter/test/diameter_capx_SUITE.erl +++ b/lib/diameter/test/diameter_capx_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,39 +25,30 @@ -module(diameter_capx_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, - init_per_group/2, - end_per_group/2, - init_per_testcase/2, - end_per_testcase/2]). - -%% testcases --export([start/1, - vendor_id/1, - start_services/1, - add_listeners/1, - s_no_common_application/1, - c_no_common_application/1, - s_no_common_security/1, - c_no_common_security/1, - s_unknown_peer/1, - c_unknown_peer/1, - s_unable/1, - c_unable/1, - s_client_reject/1, - c_client_reject/1, - remove_listeners/1, - stop_services/1, - stop/1]). + traffic/1]). %% diameter callbacks -export([peer_up/4, peer_down/4]). +%% internal +-export([s_no_common_application/1, + s_no_common_security/1, + s_unknown_peer/1, + s_unable/1, + s_client_reject/1, + c_no_common_application/1, + c_no_common_security/1, + c_unknown_peer/1, + c_unable/1, + c_client_reject/1]). + -include("diameter.hrl"). -include("diameter_gen_base_rfc3588.hrl"). %% Use only the Vendor-Specific-Application-Id record from the base @@ -108,7 +99,7 @@ -define(caps, #diameter_caps). -define(packet, #diameter_packet). --define(fail(T), erlang:error({T, process_info(self(), messages)})). +-define(fail(T), error({T, process_info(self(), messages)})). -define(TIMEOUT, 10000). @@ -117,56 +108,15 @@ %% =========================================================================== suite() -> - [{timetrap, {seconds, 60}}]. - -all() -> [start, - vendor_id, - start_services, - add_listeners] - ++ [{group, D, P} || D <- ?DICTS, P <- [[], [parallel]]] - ++ [remove_listeners, - stop_services, - stop]. - -groups() -> - Tc = lists:flatmap(fun tc/1, tc()), - [{D, [], Tc} || D <- ?DICTS]. - -init_per_suite(Config) -> - lists:foreach(fun load_dict/1, ?NOAPPS), - Config. + [{timetrap, {seconds, 20}}]. -end_per_suite(_Config) -> - [] = [Mod || N <- ?NOAPPS, - Mod <- [dict(N)], - false <- [code:delete(Mod)]], - ok. - -%% Generate a unique hostname for each testcase so that watchdogs -%% don't prevent a connection from being brought up immediately. -init_per_testcase(Name, Config) -> - [{host, ?L(Name) ++ "." ++ diameter_util:unique_string()} - | Config]. - -init_per_group(Name, Config) -> - [{rfc, Name} | Config]. +all() -> + [traffic]. -end_per_group(_, _) -> - ok. +traffic(_Config) -> + run(). -end_per_testcase(N, _) - when N == start; - N == vendor_id; - N == start_services; - N == add_listeners; - N == remove_listeners; - N == stop_services; - N == stop -> - ok; - -end_per_testcase(Name, Config) -> - CRef = ?util:read_priv(Config, Name), - ok = diameter:remove_transport(?CLIENT, CRef). +%% =========================================================================== %% Testcases all come in two flavours, client and server. tc(Name) -> @@ -179,17 +129,46 @@ tc() -> unable, client_reject]. -%% =========================================================================== -%% start/stop testcases +run() -> + try + ?util:run([{fun traffic/0, 15000}]) + after + ok = diameter:stop(), + [] = [M || N <- ?NOAPPS, + M <- [dict(N)], + B <- [code:delete(M)], + _ <- [code:purge(M)], + not B] + end. + +traffic() -> + lists:foreach(fun load_dict/1, ?NOAPPS), + ok = diameter:start(), + _ = vendor_id(), + ok = diameter:start_service(?SERVER, ?SERVICE), + ok = diameter:start_service(?CLIENT, ?SERVICE), + LRefs = add_listeners(), + ?util:run([[fun traffic/3, F, D, LRefs] || D <- ?DICTS, + N <- tc(), + F <- tc(N)]), + ok = diameter:remove_transport(?SERVER, true), + ok = diameter:stop_service(?CLIENT), + ok = diameter:stop_service(?SERVER). -start(_Config) -> - ok = diameter:start(). +%% Generate a unique hostname for each testcase so that watchdogs +%% don't prevent a connection from being brought up immediately. +traffic(F, Dict, {_Base, _Acct} = LRefs) -> + apply(?MODULE, + F, + [[{lref, LRefs}, + {rfc, Dict}, + {host, ?L(F) ++ "." ++ ?util:unique_string()}]]). %% Ensure that both integer and list-valued vendor id's can be %% configured in a Vendor-Specific-Application-Id, the arity having %% changed between RFC 3588 and RFC 6733. -vendor_id(_Config) -> - [] = ?util:run([[fun vid/1, V] || V <- [1, [1], [1,2], x]]). +vendor_id() -> + ?util:run([[fun vid/1, V] || V <- [1, [1], [1,2], x]]). vid(V) -> RC = diameter:start_service(make_ref(), @@ -203,14 +182,10 @@ vid(x, {error, _}) -> vid(_, ok) -> ok. -start_services(_Config) -> - ok = diameter:start_service(?SERVER, ?SERVICE), - ok = diameter:start_service(?CLIENT, ?SERVICE). - %% One server that responds only to base accounting, one that responds %% to both this and the common application. Share a common service just %% to simplify config, and because we can. -add_listeners(Config) -> +add_listeners() -> Acct = [listen(?SERVER, [{capabilities, [{'Origin-Host', ?HOST(H)}, {'Auth-Application-Id', []}]}, @@ -224,17 +199,7 @@ add_listeners(Config) -> {capabilities_cb, [fun server_capx/3, base]}]) || {A,H} <- [{[base3588, acct3588], "base3588-srv"}, {[base6733, acct6733], "base6733-srv"}]], - ?util:write_priv(Config, ?MODULE, {Base, Acct}). %% lref/2 reads - -remove_listeners(_Config) -> - ok = diameter:remove_transport(?SERVER, true). - -stop_services(_Config) -> - ok = diameter:stop_service(?CLIENT), - ok = diameter:stop_service(?SERVER). - -stop(_Config) -> - ok = diameter:stop(). + {Base, Acct}. %% =========================================================================== %% All the testcases come in pairs, one for receiving an event on the @@ -338,13 +303,10 @@ s_client_reject(Config) -> receive ?event{service = ?SERVER, info = {up, LRef, - {_, ?caps{origin_host = {_, OH}}}, - {listen, _}, - ?packet{}}} - = Info -> - Info - after ?TIMEOUT -> - ?fail({LRef, OH}) + {_, ?caps{origin_host = {_, OH}}}, + {listen, _}, + ?packet{}}} -> + ok end. c_client_reject(Config) -> @@ -404,12 +366,9 @@ server_closed(Config, F, RC) -> info = {closed, LRef, {'CER', RC, ?caps{origin_host = {_, OH}}, - ?packet{}} - = Reason, + ?packet{}}, {listen, _}}} -> - Reason - after ?TIMEOUT -> - ?fail({LRef, OH}) + ok end. %% server_reject/3 @@ -425,12 +384,9 @@ server_reject(Config, F, RC) -> info = {closed, LRef, {'CER', {capabilities_cb, _, RC}, ?caps{origin_host = {_, OH}}, - ?packet{}} - = Reason, + ?packet{}}, {listen, _}}} -> - Reason - after ?TIMEOUT -> - ?fail({LRef, OH}) + ok end. %% client_closed/4 @@ -459,8 +415,6 @@ client_recv(CRef) -> ?event{service = ?CLIENT, info = {closed, CRef, Reason, {connect, _}}} -> Reason - after ?TIMEOUT -> - ?fail(CRef) end. %% server_capx/3 @@ -504,20 +458,14 @@ listen(Name, Opts) -> connect(Config, T, Opts) -> {_, H} = lists:keyfind(host, 1, Config), LRef = lref(Config, T), - CRef = connect(LRef, [{capabilities, [{'Origin-Host', ?HOST(H)}]} - | Opts]), - Name = lists:takewhile(fun(C) -> C /= $. end, H), - ?util:write_priv(Config, Name, CRef), %% end_per_testcase reads - {CRef, LRef}. - -connect(LRef, Opts) -> [PortNr] = ?util:lport(tcp, LRef), - {ok, CRef} = diameter:add_transport(?CLIENT, - {connect, opts(PortNr, Opts)}), - CRef. + {ok, CRef} + = diameter:add_transport(?CLIENT, {connect, opts(H, PortNr, Opts)}), + {CRef, LRef}. -opts(PortNr, Opts) -> - [{transport_module, diameter_tcp}, +opts(Host, PortNr, Opts) -> + [{capabilities, [{'Origin-Host', ?HOST(Host)}]}, + {transport_module, diameter_tcp}, {transport_config, [{raddr, ?ADDR}, {rport, PortNr}, {ip, ?ADDR}, @@ -531,7 +479,7 @@ lref(rfc6733, [_, LRef]) -> lref(Config, T) -> lref(proplists:get_value(rfc, Config), - case ?util:read_priv(Config, ?MODULE) of + case proplists:get_value(lref, Config) of {R, _} when T == base -> R; {_, R} when T == acct -> diff --git a/lib/diameter/test/diameter_codec_SUITE.erl b/lib/diameter/test/diameter_codec_SUITE.erl index 17112794e4..ff8a031460 100644 --- a/lib/diameter/test/diameter_codec_SUITE.erl +++ b/lib/diameter/test/diameter_codec_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. @@ -28,86 +28,110 @@ -module(diameter_codec_SUITE). +%% testcases, no common_test dependency +-export([run/0, + run/1]). + +%% common_test wrapping -export([suite/0, all/0, - groups/0, - init_per_suite/1, - end_per_suite/1, - init_per_group/2, - end_per_group/2, - init_per_testcase/2, - end_per_testcase/2]). - -%% testcases --export([base/1, + base/1, gen/1, lib/1, unknown/1, - success/1, - grouped_error/1, - failed_error/1]). + recode/1]). --include("diameter_ct.hrl"). -include("diameter.hrl"). +-define(util, diameter_util). -define(L, atom_to_list). %% =========================================================================== suite() -> - [{timetrap, {seconds, 10}}]. + [{timetrap, {seconds, 15}}]. all() -> - [base, gen, lib, unknown, {group, recode}]. + [base, gen, lib, unknown, recode]. -groups() -> - [{recode, [], [success, - grouped_error, - failed_error]}]. +base(_Config) -> + run(base). -init_per_suite(Config) -> - Config. +gen(_Config) -> + run(gen). -end_per_suite(_Config) -> - ok. +lib(_Config) -> + run(lib). -init_per_group(recode, Config) -> - ok = diameter:start(), - Config. +unknown(Config) -> + Priv = proplists:get_value(priv_dir, Config), + Data = proplists:get_value(data_dir, Config), + unknown(Priv, Data). + +recode(_Config) -> + run(recode). + +%% =========================================================================== + +%% run/0 + +run() -> + run(all()). + +%% run/1 -end_per_group(_, _) -> - ok = diameter:stop(). +run(base) -> + diameter_codec_test:base(); -init_per_testcase(gen, Config) -> - [{application, ?APP, App}] = diameter_util:consult(?APP, app), +run(gen) -> + [{application, diameter, App}] = diameter_util:consult(diameter, app), {modules, Ms} = lists:keyfind(modules, 1, App), [_|_] = Gs = lists:filter(fun(M) -> lists:prefix("diameter_gen_", ?L(M)) end, Ms), - [{dicts, Gs} | Config]; + lists:foreach(fun diameter_codec_test:gen/1, Gs); -init_per_testcase(_Name, Config) -> - Config. +run(lib) -> + diameter_codec_test:lib(); -end_per_testcase(_, _) -> - ok. - -%% =========================================================================== - -base(_Config) -> - diameter_codec_test:base(). +%% Have a separate AVP dictionary just to exercise more code. +run(unknown) -> + PD = ?util:mktemp(filename:join(?util:tmpdir(), "diameter_codec")), + DD = filename:join([code:lib_dir(diameter), + "test", + "diameter_codec_SUITE_data"]), + try + unknown(PD, DD) + after + file:del_dir_r(PD) + end; + +run(success) -> + success(); + +run(grouped_error) -> + grouped_error(); + +run(failed_error) -> + failed_error(); + +run(recode) -> + ok = diameter:start(), + try + ?util:run([{?MODULE, run, [F]} || F <- [success, + grouped_error, + failed_error]]) + after + ok = diameter:stop() + end; -gen([{dicts, Ms} | _]) -> - lists:foreach(fun diameter_codec_test:gen/1, Ms). +run(List) -> + ?util:run([{{?MODULE, run, [F]}, 10000} || F <- List]). -lib(_Config) -> - diameter_codec_test:lib(). +%% =========================================================================== -%% Have a separate AVP dictionary just to exercise more code. -unknown(Config) -> - Priv = proplists:get_value(priv_dir, Config), - Data = proplists:get_value(data_dir, Config), +unknown(Priv, Data) -> ok = make(Data, "recv.dia"), ok = make(Data, "avps.dia"), {ok, _, _} = compile("diameter_test_avps.erl"), @@ -130,7 +154,7 @@ compile(File, Opts) -> %% =========================================================================== %% Ensure a Grouped AVP is represented by a list in the avps field. -success(_) -> +success() -> Avps = [{295, <<1:32>>}, %% Termination-Cause {284, [{280, "Proxy-Host"}, %% Proxy-Info {33, "Proxy-State"}, %% @@ -145,13 +169,13 @@ success(_) -> value = 2, data = <<2:32>>}]], errors = []} - = str(recode(str(Avps))). + = str(repkg(str(Avps))). %% =========================================================================== %% Ensure a Grouped AVP is represented by a list in the avps field %% even in the case of a decode error on a component AVP. -grouped_error(_) -> +grouped_error() -> Avps = [{295, <<1:32>>}, %% Termination-Cause {284, [{295, <<0:32>>}, %% Proxy-Info, Termination-Cause {280, "Proxy-Host"}, @@ -166,13 +190,13 @@ grouped_error(_) -> #diameter_avp{code = 280}, #diameter_avp{code = 33}]], errors = [{5004, #diameter_avp{code = 284}}]} - = str(recode(str(Avps))). + = str(repkg(str(Avps))). %% =========================================================================== %% Ensure that a failed decode in Failed-AVP is acceptable, and that %% the component AVPs are decoded if possible. -failed_error(_) -> +failed_error() -> Avps = [{279, [{295, <<0:32>>}, %% Failed-AVP, Termination-Cause {258, <<1:32>>}, %% Auth-Application-Id {284, [{280, "Proxy-Host"}, %% Proxy-Info @@ -195,7 +219,7 @@ failed_error(_) -> value = 2, data = <<2:32>>}]]], errors = []} - = sta(recode(sta(Avps))). + = sta(repkg(sta(Avps))). %% =========================================================================== @@ -279,9 +303,9 @@ avp([{_,_} | _] = Avps) -> avp(V) -> V. -%% recode/1 +%% repkg/1 -recode(Msg) -> +repkg(Msg) -> recode(Msg, diameter_gen_base_rfc6733). recode(#diameter_packet{} = Pkt, Dict) -> diff --git a/lib/diameter/test/diameter_compiler_SUITE.erl b/lib/diameter/test/diameter_compiler_SUITE.erl index 73fe1ef6e0..a33da0f64e 100644 --- a/lib/diameter/test/diameter_compiler_SUITE.erl +++ b/lib/diameter/test/diameter_compiler_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. @@ -24,16 +24,17 @@ -module(diameter_compiler_SUITE). +%% testcases, no common_test dependency +-export([run/0, + run/1]). + +%% common_test wrapping -export([suite/0, all/0, - init_per_suite/1, - end_per_suite/1]). - -%% testcases --export([format/1, format/2, - replace/1, replace/2, - generate/1, generate/4, - flatten1/1, flatten1/3, + format/1, + replace/1, + generate/1, + flatten1/1, flatten2/1]). -export([dict/0]). %% fake dictionary module @@ -364,7 +365,7 @@ %% =========================================================================== suite() -> - [{timetrap, {minutes, 10}}]. + [{timetrap, {seconds, 45}}]. all() -> [format, @@ -373,33 +374,37 @@ all() -> flatten1, flatten2]. -%% Error handling testcases will make an erroneous dictionary out of -%% the base dictionary and check that the expected error results. -%% ?REPLACE encodes the modifications and expected error. -init_per_suite(Config) -> +%% =========================================================================== + +%% run/0 + +run() -> + run(all()). + +%% run/1 + +run(List) -> Path = filename:join([code:lib_dir(diameter, src), "dict", ?base]), {ok, Bin} = file:read_file(Path), - [{base, Bin} | Config]. - -end_per_suite(_Config) -> - ok. + ?util:run([{{?MODULE, F, [Bin]}, 30000} || F <- List]). %% =========================================================================== %% format/1 %% %% Ensure that parse o format is the identity map. -format(Config) -> - Bin = proplists:get_value(base, Config), - [] = ?util:run([{?MODULE, [format, M, Bin]} - || E <- ?REPLACE, - {ok, M} <- [norm(E)]]). +format(<<_/binary>> = Bin) -> + ?util:run([{?MODULE, format, [{M, Bin}]} || E <- ?REPLACE, + {ok, M} <- [norm(E)]]); -format(Mods, Bin) -> +format({Mods, Bin}) -> B = modify(Bin, Mods), {ok, Dict} = parse(B, []), {ok, D} = parse(diameter_make:format(Dict), []), - {Dict, Dict} = {Dict, D}. + {Dict, Dict} = {Dict, D}; + +format(_Config) -> + run([format]). parse(File, Opts) -> case diameter_make:codec(File, [parse, hrl, return | Opts]) of @@ -415,20 +420,21 @@ parse(File, Opts) -> %% Ensure the expected success/error when parsing a morphed common %% dictionary. -replace(Config) -> - Bin = proplists:get_value(base, Config), - [] = ?util:run([{?MODULE, [replace, N, Bin]} - || E <- ?REPLACE, - N <- [norm(E)]]). +replace(<<_/binary>> = Bin) -> + ?util:run([{?MODULE, replace, [{N, Bin}]} || E <- ?REPLACE, + N <- [norm(E)]]); -replace({E, Mods}, Bin) -> +replace({{E, Mods}, Bin}) -> B = modify(Bin, Mods), case {E, parse(B, [{include, here()}]), Mods} of {ok, {ok, Dict}, _} -> Dict; {_, {error, {E,_} = T}, _} when E /= ok -> diameter_make:format_error(T) - end. + end; + +replace(_Config) -> + run([replace]). re({RE, Repl}, Bin) -> re:replace(Bin, RE, Repl, [multiline]). @@ -438,15 +444,14 @@ re({RE, Repl}, Bin) -> %% %% Ensure success when generating code and compiling. -generate(Config) -> - Bin = proplists:get_value(base, Config), +generate(<<_/binary>> = Bin) -> Rs = lists:zip(?REPLACE, lists:seq(1, length(?REPLACE))), - [] = ?util:run([{?MODULE, [generate, M, Bin, N, T]} - || {E,N} <- Rs, - {ok, M} <- [norm(E)], - T <- [erl, hrl, parse, forms]]). + ?util:run([{?MODULE, generate, [{M, Bin, N, T}]} + || {E,N} <- Rs, + {ok, M} <- [norm(E)], + T <- [erl, hrl, parse, forms]]); -generate(Mods, Bin, N, Mode) -> +generate({Mods, Bin, N, Mode}) -> B = modify(Bin, Mods ++ [{"@name .*", "@name dict" ++ ?L(N)}]), {ok, Dict} = parse(B, []), File = "dict" ++ integer_to_list(N), @@ -454,7 +459,10 @@ generate(Mods, Bin, N, Mode) -> [{name, File}, {prefix, "base"}, Mode])}, - generate(Mode, File, Dict). + generate(Mode, File, Dict); + +generate(_Config) -> + run([generate]). generate(erl, File, _) -> {ok, _} = compile:file(File ++ ".erl", [return_errors]); @@ -473,21 +481,21 @@ generate(hrl, _, _) -> %% =========================================================================== %% flatten1/1 -flatten1(_Config) -> +flatten1({Key, BaseD, FlatD}) -> + Vs = orddict:fetch(Key, BaseD), + Vs = orddict:fetch(Key, FlatD); + +flatten1(_) -> [Vsn | BaseD] = diameter_gen_base_rfc6733:dict(), {ok, I} = parse("@inherits diameter_gen_base_rfc6733\n", []), [Vsn | FlatD] = diameter_make:flatten(I), - [] = ?util:run([{?MODULE, [flatten1, K, BaseD, FlatD]} - || K <- [avp_types, grouped, enum]]). - -flatten1(Key, BaseD, FlatD) -> - Vs = orddict:fetch(Key, BaseD), - Vs = orddict:fetch(Key, FlatD). + ?util:run([{?MODULE, flatten1, [{K, BaseD, FlatD}]} + || K <- [avp_types, grouped, enum]]). %% =========================================================================== %% flatten2/1 -flatten2(_Config) -> +flatten2(_) -> Dict1 = "@name diameter_test1\n" "@prefix diameter_test1\n" diff --git a/lib/diameter/test/diameter_config_SUITE.erl b/lib/diameter/test/diameter_config_SUITE.erl index 31a6b49041..90773e8f6d 100644 --- a/lib/diameter/test/diameter_config_SUITE.erl +++ b/lib/diameter/test/diameter_config_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2013-2015. All Rights Reserved. +%% Copyright Ericsson AB 2013-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,14 +25,15 @@ -module(diameter_config_SUITE). --export([suite/0, - all/0]). +%% testscases, no common_test dependency +-export([run/0, + run/1]). -%% testcases --export([start/1, +%% common_test wrapping +-export([suite/0, + all/0, start_service/1, - add_transport/1, - stop/1]). + add_transport/1]). -define(util, diameter_util). @@ -204,38 +205,53 @@ %% =========================================================================== suite() -> - [{timetrap, {seconds, 60}}]. + [{timetrap, {seconds, 15}}]. all() -> - [start, - start_service, - add_transport, - stop]. + [start_service, + add_transport]. + +start_service(_Config) -> + run([start_service]). + +add_transport(_Config) -> + run([add_transport]). %% =========================================================================== -start(_) -> - ok = diameter:start(). +run() -> + run(all()). -start_service(T) - when is_tuple(T) -> - do(fun start/3, T); +run(List) + when is_list(List) -> + try + ?util:run([[[fun run/1, {F, 5000}] || F <- List]]) + after + dbg:stop_clear(), + diameter:stop() + end; + +run({F, Tmo}) -> + ok = diameter:start(), + try + ?util:run([{[fun run/1, F], Tmo}]) + after + ok = diameter:stop() + end; -start_service(_) -> - [] = ?util:run([{?MODULE, start_service, [T]} - || T <- [lists:keyfind(capabilities, 1, ?TRANSPORT_CONFIG) - | ?SERVICE_CONFIG]]). +run(start_service) -> + ?util:run([[fun start/1, T] + || T <- [lists:keyfind(capabilities, 1, ?TRANSPORT_CONFIG) + | ?SERVICE_CONFIG]]); -add_transport(T) - when is_tuple(T) -> - do(fun add/3, T); +run(add_transport) -> + ?util:run([[fun add/1, T] || T <- ?TRANSPORT_CONFIG]). -add_transport(_) -> - [] = ?util:run([{?MODULE, add_transport, [T]} - || T <- ?TRANSPORT_CONFIG]). +start(T) -> + do(fun start/3, T). -stop(_) -> - ok = diameter:stop(). +add(T) -> + do(fun add/3, T). %% =========================================================================== diff --git a/lib/diameter/test/diameter_ct.hrl b/lib/diameter/test/diameter_ct.hrl deleted file mode 100644 index fdf8782456..0000000000 --- a/lib/diameter/test/diameter_ct.hrl +++ /dev/null @@ -1,22 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2010-2016. 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. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% - --define(APP, diameter). --define(ERROR(T), erlang:error({?MODULE, ?LINE, T})). diff --git a/lib/diameter/test/diameter_dist_SUITE.erl b/lib/diameter/test/diameter_dist_SUITE.erl index aa2141d744..7c66a711c8 100644 --- a/lib/diameter/test/diameter_dist_SUITE.erl +++ b/lib/diameter/test/diameter_dist_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2019-2021. All Rights Reserved. +%% Copyright Ericsson AB 2019-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,15 +25,13 @@ -module(diameter_dist_SUITE). --export([ - suite/0, - all/0, - init_per_suite/1, - end_per_suite/1 -]). +%% all tests, no common_test dependency +-export([run/0]). -%% testcases --export([send/1]). +%% common_test wrapping +-export([suite/0, + all/0, + traffic/1]). %% diameter callbacks -export([peer_up/3, @@ -45,61 +43,210 @@ handle_error/4, handle_request/3]). -%% Internal export for RPC --export([start_server/5, start_client/6]). +%% rpc calls +-export([start/1, + call/1, + connect/1, + ping/1]). -include("diameter.hrl"). -include("diameter_gen_base_rfc6733.hrl"). --include_lib("common_test/include/ct.hrl"). - %% =========================================================================== +-define(util, diameter_util). + -define(CLIENT, 'CLIENT'). -define(SERVER, 'SERVER'). -define(REALM, "erlang.org"). -define(DICT, diameter_gen_base_rfc6733). -define(ADDR, {127,0,0,1}). + +%% Config for diameter:start_service/2. +-define(SERVICE(Host), + [{'Origin-Host', Host ++ [$.|?REALM]}, + {'Origin-Realm', ?REALM}, + {'Host-IP-Address', [?ADDR]}, + {'Vendor-Id', 12345}, + {'Product-Name', "OTP/diameter"}, + {'Auth-Application-Id', [?DICT:id()]}, + {'Origin-State-Id', origin()}, + {spawn_opt, {diameter_dist, route_session, [#{id => []}]}}, + {sequence, fun sequence/0}, + {string_decode, false}, + {application, [{dictionary, ?DICT}, + {module, ?MODULE}, + {request_errors, callback}, + {answer_errors, callback}]}]). + -define(SUCCESS, 2001). -define(BUSY, 3004). -define(LOGOUT, ?'DIAMETER_BASE_TERMINATION-CAUSE_LOGOUT'). -define(MOVED, ?'DIAMETER_BASE_TERMINATION-CAUSE_USER_MOVED'). -define(TIMEOUT, ?'DIAMETER_BASE_TERMINATION-CAUSE_SESSION_TIMEOUT'). +-define(L, atom_to_list). +-define(A, list_to_atom). + +%% The order here is significant and causes the server to listen +%% before the clients connect. The server listens on the first node, +%% and distributes requests to the other two. +-define(NODES, [{server0, ?SERVER}, + {server1, ?SERVER}, + {server2, ?SERVER}, + {client, ?CLIENT}]). + %% =========================================================================== +%% common_test wrapping suite() -> - [{timetrap, {seconds, 30}}]. + [{timetrap, {seconds, 90}}]. all() -> - [send]. - -init_per_suite(Config) -> - {ok, ServerPeer, ServerNode} = ?CT_PEER(), - ListenPort = erpc:call(ServerNode, ?MODULE, start_server, [?SERVER, "server0", 0, 0, 30]), - %% Distributed workers - Peer1 = start_worker(?SERVER), - Peer2 = start_worker(?SERVER), - %% Diameter client - {ok, ClientPeer, ClientNode} = ?CT_PEER(), - ok = erpc:call(ClientNode, ?MODULE, start_client, [?CLIENT, ListenPort, "client", 99, 0, 32]), - %% unlink peers, assuming end_per_suite is executed reliably - Peers = [ServerPeer, Peer1, Peer2, ClientPeer], - [unlink(P) || P <- Peers], - [{server, ServerNode}, {client, ClientNode}, {peers, Peers} | Config]. - -end_per_suite(Config) -> - [peer:stop(P) || P <- proplists:get_value(peers, Config)]. - -%% Basic test -send(Config) when is_list(Config) -> - ServerNode = proplists:get_value(server, Config), - ClientNode = proplists:get_value(client, Config), - %% Send 100 requests and ensure the node name sent as User-Name isn't - %% the node terminating transport. - send(ServerNode, ClientNode, 100, dict:new()). - -send(Server0, _Client, 0, Dict) -> + [traffic]. + +traffic(_Config) -> + run(). + +%% =========================================================================== + +%% run/0 + +run() -> + [] = ?util:run([{fun traffic/0, 60000}]). + %% process for linked peers to die with + +%% traffic/0 + +traffic() -> + true = is_alive(), %% need distribution for peer nodes + Nodes = enslave(), + [] = ping(lists:droplast(Nodes)), %% drop client node + [] = start(Nodes), + ok = connect(Nodes), + ok = send(Nodes). + +%% enslave/1 +%% +%% Start four slave nodes, three to implement a Diameter server, +%% one to implement a client. + +enslave() -> + Here = filename:dirname(code:which(?MODULE)), + Ebin = filename:join([Here, "..", "ebin"]), + Dirs = [Here, Ebin], + Args = [["-pa" | [lists:flatten(io_lib:format("~s", [D])) || D <- Dirs]], + ["-setcookie", ?L(erlang:get_cookie())]], + [{N,S} || A <- [lists:append(Args)], + {M,S} <- ?NODES, + N <- [start(M, A)]]. + +start(Name, Args) -> + {ok, _, Node} = peer:start_link(#{name => Name, args => Args}), + Node. + +%% ping/1 +%% +%% Ensure the server nodes are connected so that diameter_dist can attach. + +ping({S, Nodes}) -> + ?SERVER = S, %% assert + [N || {N,_} <- Nodes, + node() /= N, + pang <- [net_adm:ping(N)]]; + +ping(Nodes) -> + [{N,RC} || {N,S} <- Nodes, + RC <- [rpc:call(N, ?MODULE, ping, [{S,Nodes}])], + RC /= []]. + +%% start/1 +%% +%% Start diameter services. + +%% There's no need to start diameter on a node that only services +%% diameter_dist as a handler of incoming requests, but the +%% diameter_dist server must be started since the servers communicate +%% to determine who services what. The typical case is probably that +%% handler nodes also want to be able to send Diameter requests, in +%% which case the application needs to be started and diameter_dist is +%% started as a part of this, but only start the server here to ensure +%% everything still works as expected. +start({_SvcName, [_, {S1, _}, {S2, _}, _]}) + when node() == S1; %% server1 + node() == S2 -> %% server2 + Mod = diameter_dist, + {ok, _} = gen_server:start({local, Mod}, Mod, _Args = [], _Opts = []), + ok; + +start({SvcName, [{S0, _}, _, _, {C, _}]}) + when node() == S0; %% server0 + node() == C -> %% client + ok = diameter:start(), + ok = diameter:start_service(SvcName, ?SERVICE((?L(SvcName)))); + +start(Nodes) -> + [{N,RC} || {N,S} <- Nodes, + RC <- [rpc:call(N, ?MODULE, start, [{S, Nodes}])], + RC /= ok]. + +sequence() -> + sequence(sname()). + +sequence(client) -> + {0,32}; +sequence(Server) -> + "server" ++ N = ?L(Server), + {list_to_integer(N), 30}. + +origin() -> + origin(sname()). + +origin(client) -> + 99; +origin(Server) -> + "server" ++ N = ?L(Server), + list_to_integer(N). + +%% connect/1 +%% +%% Establish one connection from the client, terminated on the first +%% server node, the others handling requests. + +connect({?SERVER, [{Node, _} | _], []}) + when Node == node() -> %% server0 + [_LRef = ?util:listen(?SERVER, tcp)]; + +connect({?SERVER, _, [_] = Acc}) -> %% server[12]: register to receive requests + ok = diameter_dist:attach([?SERVER]), + Acc; + +connect({?CLIENT, [{Node, _} | _], [LRef]}) -> + ?util:connect(?CLIENT, tcp, {Node, LRef}), + ok; + +connect(Nodes) -> + lists:foldl(fun({N,S}, A) -> + rpc:call(N, ?MODULE, connect, [{S, Nodes, A}]) + end, + [], + Nodes). + +%% =========================================================================== +%% traffic testcases + +%% send/1 +%% +%% Send 100 requests and ensure the node name sent as User-Name isn't +%% the node terminating transport. + +send(Nodes) -> + send(Nodes, 100, dict:new()). + +%% send/2 + +send(Nodes, 0, Dict) -> + [{Server0, _} | _] = Nodes, Node = atom_to_binary(Server0, utf8), {false, _} = {dict:is_key(Node, Dict), dict:to_list(Dict)}, %% Check that counters have been incremented as expected on server0. @@ -112,71 +259,38 @@ send(Server0, _Client, 0, Dict) -> Stats}, {[{send, 0, 100, 2001}], _} = {[{D,R,N,C} || {{{0,275,R}, D, {'Result-Code', C}}, N} <- Stats], - Stats}; + Stats}, + ok; -send(Server0, Client, N, Dict) -> - Req = #diameter_base_STR{'Destination-Realm' = ?REALM, - 'Auth-Application-Id' = ?DICT:id(), - 'Termination-Cause' = ?LOGOUT}, +send(Nodes, N, Dict) -> #diameter_base_STA{'Result-Code' = ?SUCCESS, 'User-Name' = [ServerNode]} - = rpc:call(Client, diameter, call, [?CLIENT, ?DICT, Req, []]), + = send(Nodes, str(?LOGOUT)), true = is_binary(ServerNode), - send(Server0, Client, N-1, dict:update_counter(ServerNode, 1, Dict)). + send(Nodes, N-1, dict:update_counter(ServerNode, 1, Dict)). %% =========================================================================== -%% Utilities -%% Starts a peer node with Diameter server running -start_server(Server, Host, Origin, SeqFrom, SeqTo) -> - ok = diameter:start(), - ok = diameter:start_service(Server, service_opt(Host, Origin, SeqFrom, SeqTo)), - %% Listener config - ListenConfig = [{transport_module, diameter_tcp}, {transport_config, [{ip, ?ADDR}, - {port, 0}, {accept, {256, 0, 0, 1}}, {accept, ["256.0.0.1", ["^.+$"]]}]}], - %% start listener on Server0, get the listener port number - {ok, ListenRef} = diameter:add_transport(Server, {listen, ListenConfig}), - %% wait for listener to be up - [_] = diameter_reg:wait({diameter_tcp, listener, {ListenRef, '_'}}), - [{listen, ListenPort, _}] = diameter_tcp:ports(), - ListenPort. - -%% Starts Diameter client node connected to Server -start_client(Client, ServerPort, Host, Origin, SeqFrom, SeqTo) -> - ok = diameter:start(), - ok = diameter:start_service(Client, service_opt(Host, Origin, SeqFrom, SeqTo)), - %% Establish connection to the server - ConnectConfig = [{transport_module, diameter_tcp}, - {transport_config, [{raddr, ?ADDR}, {rport, ServerPort}]}], - true = diameter:subscribe(Client), - {ok, Ref} = diameter:add_transport(Client, {connect, ConnectConfig}), - receive - {diameter_event, Client, {up, Ref, _, _, _}} -> ok - end. - -%% Returns config for diameter:start_service/2. -service_opt(Host, Origin, SeqFrom, SeqTo) -> - [{'Origin-Host', Host ++ [$.|?REALM]}, - {'Origin-Realm', ?REALM}, - {'Host-IP-Address', [?ADDR]}, - {'Vendor-Id', 12345}, - {'Product-Name', "OTP/diameter"}, - {'Auth-Application-Id', [?DICT:id()]}, - {'Origin-State-Id', Origin}, - {spawn_opt, {diameter_dist, route_session, [#{id => []}]}}, - {sequence, fun () -> {SeqFrom, SeqTo} end}, %% use 'fun' for fun and piggy-back testing - {string_decode, false}, - {application, [{dictionary, ?DICT}, - {module, ?MODULE}, - {request_errors, callback}, - {answer_errors, callback}]}]. - -%% Starts a distributed worker node -start_worker(AttachTo) -> - {ok, Peer, Node} = ?CT_PEER(), - {ok, _} = erpc:call(Node, gen_server, start, [{local, diameter_dist}, diameter_dist, [], []]), - ok = erpc:call(Node, diameter_dist, attach, [[AttachTo]]), - Peer. +str(Cause) -> + #diameter_base_STR{'Destination-Realm' = ?REALM, + 'Auth-Application-Id' = ?DICT:id(), + 'Termination-Cause' = Cause}. + +%% send/2 + +send(Nodes, Req) -> + {Node, _} = lists:last(Nodes), + rpc:call(Node, ?MODULE, call, [Req]). + +%% call/1 + +call(Req) -> + diameter:call(?CLIENT, ?DICT, Req, []). + +%% sname/0 + +sname() -> + ?A(hd(string:tokens(?L(node()), "@"))). %% =========================================================================== %% diameter callbacks diff --git a/lib/diameter/test/diameter_distribution_SUITE.erl b/lib/diameter/test/diameter_distribution_SUITE.erl index 7cb977f5d4..592ec24e64 100644 --- a/lib/diameter/test/diameter_distribution_SUITE.erl +++ b/lib/diameter/test/diameter_distribution_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2013-2021. All Rights Reserved. +%% Copyright Ericsson AB 2013-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,18 +25,19 @@ -module(diameter_distribution_SUITE). --export([ - suite/0, - all/0, - init_per_suite/1, - end_per_suite/1 -]). +%% testcases, no common_test dependency +-export([run/0]). -%% testcases --export([send_local/1, - send_remote/1, - send_timeout/1, - send_failover/1]). +%% common_test wrapping +-export([suite/0, + all/0, + traffic/1]). + +%% rpc calls +-export([ping/1, + start/1, + connect/1, + call/1]). %% diameter callbacks -export([peer_up/3, @@ -48,95 +49,212 @@ handle_error/5, handle_request/3]). -%% Internal export for RPC --export([start_server/5, start_client/6, call/1]). - -include("diameter.hrl"). -include("diameter_gen_base_rfc6733.hrl"). --include_lib("common_test/include/ct.hrl"). - %% =========================================================================== +-define(util, diameter_util). + -define(CLIENT, 'CLIENT'). -define(SERVER, 'SERVER'). -define(REALM, "erlang.org"). -define(DICT, diameter_gen_base_rfc6733). -define(ADDR, {127,0,0,1}). + +%% Config for diameter:start_service/2. +-define(SERVICE(Host), + [{'Origin-Host', Host ++ [$.|?REALM]}, + {'Origin-Realm', ?REALM}, + {'Host-IP-Address', [?ADDR]}, + {'Vendor-Id', 12345}, + {'Product-Name', "OTP/diameter"}, + {'Auth-Application-Id', [?DICT:id()]}, + {'Origin-State-Id', origin()}, + {share_peers, peers()}, + {use_shared_peers, peers()}, + {restrict_connections, false}, + {spawn_opt, {diameter_dist, spawn_local, []}}, + {sequence, fun sequence/0}, + {application, [{dictionary, ?DICT}, + {module, ?MODULE}, + {request_errors, callback}, + {answer_errors, callback}]}]). + -define(SUCCESS, 2001). -define(BUSY, 3004). -define(LOGOUT, ?'DIAMETER_BASE_TERMINATION-CAUSE_LOGOUT'). -define(MOVED, ?'DIAMETER_BASE_TERMINATION-CAUSE_USER_MOVED'). -define(TIMEOUT, ?'DIAMETER_BASE_TERMINATION-CAUSE_SESSION_TIMEOUT'). +-define(L, atom_to_list). +-define(A, list_to_atom). + +%% The order here is significant and causes the server to listen +%% before the clients connect. +-define(NODES, [{server, ?SERVER}, + {client0, ?CLIENT}, + {client1, ?CLIENT}, + {client2, ?CLIENT}]). + +%% Options to ct_slave:start/2. +-define(TIMEOUTS, [{T, 15000} || T <- [boot_timeout, + init_timeout, + start_timeout]]). + %% =========================================================================== suite() -> - [{timetrap, {seconds, 30}}]. + [{timetrap, {seconds, 90}}]. all() -> - [send_local, - send_remote, - send_timeout, - send_failover]. - -init_per_suite(Config) -> - {ok, ServerPeer, ServerNode} = ?CT_PEER(), - ListenPort = erpc:call(ServerNode, ?MODULE, start_server, [?SERVER, "server0", 99, 0, 32]), - %% client nodes - Indices = lists:seq(0, 2), - {_Ok, ClientPeers, Nodes} = lists:unzip3([{ok, _P, _N} = ?CT_PEER() || _ <- Indices]), - %% Ensure the client nodes are connected since the sharing of - %% transports is only between connected nodes. - [pong = erpc:call(N, net_adm, ping, [M]) || N <- Nodes, M <- Nodes, N < M], - %% Start diameter clients - %% not exactly multi-call, call args are different - [ok = erpc:call(N, ?MODULE, start_client, - [?CLIENT, ListenPort, "client" ++ integer_to_list(Seq), Seq, Seq, 30]) - || {N, Seq} <- lists:zip(Nodes, Indices)], - %% unlink peers, assuming end_per_suite is executed reliably - Peers = [ServerPeer | ClientPeers], - [unlink(P) || P <- Peers], - [{server, ServerNode}, {clients, Nodes}, {peers, Peers} | Config]. - -end_per_suite(Config) -> - [peer:stop(P) || P <- proplists:get_value(peers, Config)]. + [traffic]. + +traffic(_Config) -> + traffic(). %% =========================================================================== -%% traffic testcases -%% send_local/1 +run() -> + [] = ?util:run([{fun traffic/0, 60000}]). + %% process for linked peers to die with + +%% traffic/0 + +traffic() -> + true = is_alive(), %% need distribution for peer nodes + Nodes = enslave(), + [] = ping(Nodes), %% drop client node + [] = start(Nodes), + [_] = connect(Nodes), + [] = send(Nodes). + +%% enslave/0 %% +%% Start four slave nodes, one to implement a Diameter server, +%% three to implement a client. + +enslave() -> + Here = filename:dirname(code:which(?MODULE)), + Ebin = filename:join([Here, "..", "ebin"]), + Dirs = [Here, Ebin], + Args = [["-pa" | [lists:flatten(io_lib:format("~s", [D])) || D <- Dirs]], + ["-setcookie", ?L(erlang:get_cookie())]], + [{N,S} || A <- [lists:append(Args)], + {M,S} <- ?NODES, + N <- [start(M, A)]]. + +start(Name, Args) -> + {ok, _, Node} = peer:start_link(#{name => Name, args => Args}), + Node. + +%% ping/1 +%% +%% Ensure the client nodes are connected since the sharing of +%% transports is only between connected nodes. + +ping({?SERVER, _Nodes}) -> + []; + +ping({?CLIENT, Nodes}) -> + [N || {N,_} <- Nodes, + node() /= N, + pang <- [net_adm:ping(N)]]; + +ping(Nodes) -> + [{N,RC} || {N,S} <- Nodes, + RC <- [rpc:call(N, ?MODULE, ping, [{S, Nodes}])], + RC /= []]. + +%% start/1 +%% +%% Start diameter services. + +start(SvcName) + when is_atom(SvcName) -> + ok = diameter:start(), + ok = diameter:start_service(SvcName, ?SERVICE((?L(SvcName)))); + +start(Nodes) -> + [{N,RC} || {N,S} <- Nodes, + RC <- [rpc:call(N, ?MODULE, start, [S])], + RC /= ok]. + +sequence() -> + sequence(sname()). + +sequence(server) -> + {0,32}; +sequence(Client) -> + "client" ++ N = ?L(Client), + {list_to_integer(N), 30}. + +origin() -> + origin(sname()). + +origin(server) -> + 99; +origin(Client) -> + "client" ++ N = ?L(Client), + list_to_integer(N). + +peers() -> + peers(sname()). + +peers(server) -> true; +peers(client0) -> [node() | nodes()]; +peers(client1) -> fun erlang:nodes/0; +peers(client2) -> nodes(). + +%% connect/1 +%% +%% Establish one connection to the server from each of the client +%% nodes. + +connect({?SERVER, _, []}) -> + [_LRef = ?util:listen(?SERVER, tcp)]; + +connect({?CLIENT, [{Node, _} | _], [LRef] = Acc}) -> + ?util:connect(?CLIENT, tcp, {Node, LRef}), + Acc; + +connect(Nodes) -> + lists:foldl(fun({N,S}, A) -> + rpc:call(N, ?MODULE, connect, [{S, Nodes, A}]) + end, + [], + Nodes). + +%% =========================================================================== + +%% send/1 + +send(Nodes) -> + ?util:run([[fun send/2, Nodes, T] + || T <- [local, remote, timeout, failover]]). + +%% send/2 + %% Send a request from the first client node, using a the local %% transport. - -send_local(Config) -> +send(Nodes, local) -> #diameter_base_STA{'Result-Code' = ?SUCCESS} - = send(Config, local, str(?LOGOUT)). + = send(Nodes, 0, str(?LOGOUT)); -%% send_remote/1 -%% %% Send a request from the first client node, using a transport on the %% another node. - -send_remote(Config) -> +send(Nodes, remote) -> #diameter_base_STA{'Result-Code' = ?SUCCESS} - = send(Config, remote, str(?LOGOUT)). + = send(Nodes, 1, str(?LOGOUT)); -%% send_timeout/1 -%% %% Send a request that the server discards. +send(Nodes, timeout) -> + {error, timeout} = send(Nodes, 1, str(?TIMEOUT)); -send_timeout(Config) -> - {error, timeout} = send(Config, remote, str(?TIMEOUT)). - -%% send_failover/1 -%% -%% Send a request that causes the server to remote transports down. - -send_failover(Config) -> +%% Send a request that causes the server to take the transport down. +send(Nodes, failover) -> #'diameter_base_answer-message'{'Result-Code' = ?BUSY} - = send(Config, remote, str(?MOVED)). + = send(Nodes, 2, str(?MOVED)). %% =========================================================================== @@ -145,68 +263,20 @@ str(Cause) -> 'Auth-Application-Id' = ?DICT:id(), 'Termination-Cause' = Cause}. -%% send/2 +%% send/3 -send(Config, Where, Req) -> - [Node | _] = proplists:get_value(clients, Config) , +send([_, {Node, _} | _], Where, Req) -> rpc:call(Node, ?MODULE, call, [{Where, Req}]). %% call/1 call({Where, Req}) -> - diameter:call(?CLIENT, ?DICT, Req, [{extra, [{Where, node()}]}]). - + diameter:call(?CLIENT, ?DICT, Req, [{extra, [{Where, sname()}]}]). -%% Starts a peer node with Diameter server running -start_server(Server, Host, Origin, SeqFrom, SeqTo) -> - ok = diameter:start(), - ok = diameter:start_service(Server, service_opt(Host, Origin, SeqFrom, SeqTo)), - %% Listener config - ListenConfig = [{transport_module, diameter_tcp}, {transport_config, [{ip, ?ADDR}, - {port, 0}, {accept, {256, 0, 0, 1}}, {accept, ["256.0.0.1", ["^.+$"]]}]}], - %% start listener on Server0, get the listener port number - {ok, ListenRef} = diameter:add_transport(Server, {listen, ListenConfig}), - %% wait for listener to be up - [_] = diameter_reg:wait({diameter_tcp, listener, {ListenRef, '_'}}), - [{listen, ListenPort, _}] = diameter_tcp:ports(), - ListenPort. - -%% Starts Diameter client node connected to Server -start_client(Client, ServerPort, Host, Origin, SeqFrom, SeqTo) -> - ok = diameter:start(), - ok = diameter:start_service(Client, service_opt(Host, Origin, SeqFrom, SeqTo)), - %% Establish connection to the server - ConnectConfig = [{transport_module, diameter_tcp}, - {transport_config, [{ip, ?ADDR}, {port, 0}, {raddr, ?ADDR}, {rport, ServerPort}]}], - true = diameter:subscribe(Client), - {ok, Ref} = diameter:add_transport(Client, {connect, ConnectConfig}), - receive - {diameter_event, Client, {up, Ref, _, _, _}} -> ok - end. +%% sname/0 -%% Config for diameter:start_service/2. -service_opt(Host, Origin, SeqFrom, SeqTo) -> - [{'Origin-Host', Host ++ [$.|?REALM]}, - {'Origin-Realm', ?REALM}, - {'Host-IP-Address', [?ADDR]}, - {'Vendor-Id', 12345}, - {'Product-Name', "OTP/diameter"}, - {'Auth-Application-Id', [?DICT:id()]}, - {'Origin-State-Id', Origin}, - {share_peers, peers(Host)}, - {use_shared_peers, peers(Host)}, - {restrict_connections, false}, - {spawn_opt, {diameter_dist, spawn_local, []}}, - {sequence, fun () -> {SeqFrom, SeqTo} end}, - {application, [{dictionary, ?DICT}, - {module, ?MODULE}, - {request_errors, callback}, - {answer_errors, callback}]}]. - -peers("server0") -> true; -peers("client0") -> [node() | nodes()]; -peers("client1") -> fun erlang:nodes/0; -peers("client2") -> nodes(). +sname() -> + ?A(hd(string:tokens(?L(node()), "@"))). %% =========================================================================== %% diameter callbacks @@ -223,18 +293,26 @@ peer_down(_SvcName, _Peer, State) -> %% pick_peer/4 -pick_peer([LP], [_, _], ?CLIENT, _State, {local, _Client0Node}) -> +pick_peer([LP], _, ?CLIENT, _State, {0, client0}) -> {ok, LP}; -pick_peer([_], [RP | _], ?CLIENT, _State, {remote, _Client0Node}) -> +pick_peer(_, Peers, ?CLIENT, _State, {1, client0}) -> + [RP] = [T || {_, #diameter_caps{origin_state_id = {[1],_}}} = T <- Peers], {ok, RP}; -pick_peer([LP], [], ?CLIENT, _State, {remote, _Client0Node}) -> - {ok, LP}. +%% Sending on the remote transport causes the server to take the +%% transport down. Retransmission on the local. +pick_peer(LP, RP, ?CLIENT, _State, {2, client0}) -> + {ok, case [T || {_, #diameter_caps{origin_state_id = {[2],_}}} = T <- RP] of + [T] -> + T; + _ -> + hd([_] = LP) + end}. %% prepare_request/4 -prepare_request(Pkt, ?CLIENT, {_Ref, Caps}, {_, _Client0Node}) -> +prepare_request(Pkt, ?CLIENT, {_Ref, Caps}, {_, client0}) -> #diameter_packet{msg = Req} = Pkt, #diameter_caps{origin_host = {OH, _}, @@ -246,25 +324,26 @@ prepare_request(Pkt, ?CLIENT, {_Ref, Caps}, {_, _Client0Node}) -> %% prepare_retransmit/4 -prepare_retransmit(Pkt, ?CLIENT, _, {_, _Client0Node}) -> +prepare_retransmit(Pkt, ?CLIENT, _, {_, client0}) -> #diameter_packet{msg = #diameter_base_STR{'Termination-Cause' = ?MOVED}} = Pkt, %% assert {send, Pkt}. %% handle_answer/5 -handle_answer(Pkt, _Req, ?CLIENT, _Peer, {_, _Client0Node}) -> +handle_answer(Pkt, _Req, ?CLIENT, _Peer, {_, client0}) -> #diameter_packet{msg = Rec, errors = []} = Pkt, Rec. %% handle_error/5 -handle_error(Reason, _Req, ?CLIENT, _Peer, {_, _Client0Node}) -> +handle_error(Reason, _Req, ?CLIENT, _Peer, {_, client0}) -> {error, Reason}. %% handle_request/3 handle_request(Pkt, ?SERVER, Peer) -> + server = sname(), %% assert #diameter_packet{msg = Req} = Pkt, request(Req, Peer). diff --git a/lib/diameter/test/diameter_dpr_SUITE.erl b/lib/diameter/test/diameter_dpr_SUITE.erl index 779b919d3c..45f4ec9b5a 100644 --- a/lib/diameter/test/diameter_dpr_SUITE.erl +++ b/lib/diameter/test/diameter_dpr_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2012-2017. All Rights Reserved. +%% Copyright Ericsson AB 2012-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. @@ -24,22 +24,26 @@ -module(diameter_dpr_SUITE). +%% testcases, no common_test dependency +-export([run/0, + run/1]). + +%% common_test wrapping -export([suite/0, all/0, - groups/0, - init_per_suite/1, - end_per_suite/1, - init_per_group/2, - end_per_group/2]). - -%% testcases --export([start/1, - connect/1, + client/1, + server/1, + uncommon/1, + transport/1, + service/1, + application/1]). + +%% internal +-export([connect/1, send_dpr/1, remove_transport/1, stop_service/1, - check/1, - stop/1]). + check/1]). %% disconnect_cb -export([disconnect/5]). @@ -84,42 +88,54 @@ %% =========================================================================== suite() -> - [{timetrap, {seconds, 60}}]. + [{timetrap, {seconds, 30}}]. all() -> - [{group, R} || R <- [client, server, uncommon | ?REASONS]]. + [client, server, uncommon, transport, service, application]. -%% The group determines how transports are terminated: by remove_transport, -%% stop_service or application stop. -groups() -> - [{R, [], [start, send_dpr, stop]} || R <- [client, server, uncommon]] - ++ [{R, [], Ts} || Ts <- [tc()], R <- ?REASONS]. +-define(tc(Name), Name(_) -> run([Name])). -init_per_suite(Config) -> %% not need, but a useful place to enable trace - Config. +?tc(client). +?tc(server). +?tc(uncommon). +?tc(transport). +?tc(service). +?tc(application). -end_per_suite(_Config) -> - ok. +%% =========================================================================== -init_per_group(Name, Config) -> - [{group, Name} | Config]. +%% run/0 -end_per_group(_, _) -> - ok. +run() -> + run(all()). -tc() -> - [start, connect, remove_transport, stop_service, check, stop]. +%% run/1 -%% =========================================================================== +run(List) + when is_list(List) -> + try + ?util:run([[{[fun run/1, T], 15000} || T <- List]]) + after + diameter:stop() + end; -%% start/1 - -start(Config) - when is_list(Config) -> - Grp = group(Config), +run(Grp) -> ok = diameter:start(), ok = diameter:start_service(?SERVER, service(?SERVER, Grp)), - ok = diameter:start_service(?CLIENT, service(?CLIENT, Grp)). + ok = diameter:start_service(?CLIENT, service(?CLIENT, Grp)), + _ = lists:foldl(fun(F,A) -> apply(?MODULE, F, [A]) end, + [{group, Grp}], + tc(Grp)), + ok = diameter:stop(). + +tc(T) + when T == client; + T == server; + T == uncommon -> + [send_dpr]; + +tc(_) -> + [connect, remove_transport, stop_service, check]. service(?SERVER = Svc, _) -> ?SERVICE(Svc) @@ -192,26 +208,30 @@ sender(_) -> %% connect/1 connect(Config) -> - Pid = spawn(fun init/0), %% process for disconnect_cb to bang + Self = self(), Grp = group(Config), + Pid = spawn(fun() -> init(Self) end), %% process for disconnect_cb to bang LRef = ?util:listen(?SERVER, tcp), Refs = [?util:connect(?CLIENT, tcp, LRef, opts(RCs, {Grp, Pid})) || RCs <- ?RETURNS], - ?util:write_priv(Config, config, [Pid | Refs]). + Pid ! (Grp == application orelse length(Refs)), + [{config, [Pid | Refs]} | Config]. %% remove_transport/1 %% Remove all the client transports only in the transport group. remove_transport(Config) -> transport == group(Config) - andalso (ok = diameter:remove_transport(?CLIENT, true)). + andalso (ok = diameter:remove_transport(?CLIENT, true)), + Config. %% stop_service/1 %% Stop the service only in the service group. stop_service(Config) -> service == group(Config) - andalso (ok = diameter:stop_service(?CLIENT)). + andalso (ok = diameter:stop_service(?CLIENT)), + Config. %% check/1 @@ -219,16 +239,11 @@ stop_service(Config) -> %% for the timing reason explained below. check(Config) -> Grp = group(Config), - [Pid | Refs] = ?util:read_priv(Config, config), + [Pid | Refs] = proplists:get_value(config, Config), Pid ! self(), %% ask for dictionary Dict = receive {Pid, D} -> D end, %% get it check(Refs, ?RETURNS, Grp, Dict). %% check for callbacks -%% stop/1 - -stop(_Config) -> - ok = diameter:stop(). - %% =========================================================================== %% Whether or not there are callbacks after diameter:stop() depends on @@ -258,8 +273,7 @@ check1(Ref, [], _, Dict) -> %% ---------------------------------------- group(Config) -> - {group, Grp} = lists:keyfind(group, 1, Config), - Grp. + proplists:get_value(group, Config). %% Configure the callback with the group name (= disconnect reason) as %% extra argument. @@ -274,13 +288,18 @@ disconnect(Reason, Ref, Peer, {Reason, Pid}, RC) -> Pid ! {Reason, Ref}, RC. -init() -> - exit(recv(dict:new())). +init(Pid) -> + monitor(process, Pid), + exit(recv(receive T -> T end, dict:new())). -recv(Dict) -> +recv(true, Dict) -> + recv(0, Dict); +recv(N, Dict) -> receive - Pid when is_pid(Pid) -> + Pid when N == 0, is_pid(Pid) -> Pid ! {self(), Dict}; {Reason, Ref} -> - recv(dict:store(Ref, Reason, Dict)) + recv(N - 1, dict:store(Ref, Reason, Dict)); + {'DOWN', _, process, _, _} -> + ok end. diff --git a/lib/diameter/test/diameter_event_SUITE.erl b/lib/diameter/test/diameter_event_SUITE.erl index 6d1d1dfd8f..f4cb5e6d79 100644 --- a/lib/diameter/test/diameter_event_SUITE.erl +++ b/lib/diameter/test/diameter_event_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2013-2020. All Rights Reserved. +%% Copyright Ericsson AB 2013-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. @@ -26,20 +26,18 @@ -module(diameter_event_SUITE). +%% testcase, no common_test dependency +-export([run/0]). + +%% common_test wrapping -export([suite/0, all/0, - init_per_suite/1, - end_per_suite/1, - init_per_testcase/2, - end_per_testcase/2]). - -%% testcases --export([start/1, - start_server/1, - up/1, + traffic/1]). + +%% internal +-export([up/1, down/1, - cea_timeout/1, - stop/1]). + cea_timeout/1]). -include("diameter.hrl"). @@ -77,43 +75,44 @@ %% =========================================================================== suite() -> - [{timetrap, {seconds, 60}}]. + [{timetrap, {seconds, 90}}]. all() -> - [start, - start_server, - up, - down, - cea_timeout, - stop]. - -%% Not used, but a convenient place to enable trace. -init_per_suite(Config) -> - Config. - -end_per_suite(_Config) -> - ok. + [traffic]. -init_per_testcase(Name, Config) -> - [{name, Name} | Config]. - -end_per_testcase(_, _) -> - ok. +traffic(_Config) -> + run(). %% =========================================================================== -%% start/stop testcases -start(_Config) -> - ok = diameter:start(). +%% run/0 -start_server(Config) -> +run() -> + ok = diameter:start(), + try + ?util:run([{fun traffic/0, 60000}]) + after + ok = diameter:stop() + end. + +%% traffic/0 + +traffic() -> + PortNr = start_server(), + Config = [{portnr, PortNr}], + Funs = [up, down, cea_timeout], + ?util:run([[{?MODULE, F, [[{name, F} | Config]]} || F <- Funs]]). + +%% start_server/0 + +start_server() -> diameter:subscribe(?SERVER), ok = diameter:start_service(?SERVER, ?SERVICE(?SERVER, [?DICT_COMMON])), LRef = ?util:listen(?SERVER, tcp, [{capabilities_cb, fun capx_cb/2}, {capx_timeout, ?SERVER_CAPX_TMO}]), [PortNr] = ?util:lport(tcp, LRef), - ?util:write_priv(Config, portnr, PortNr), - start = event(?SERVER). + start = event(?SERVER), + PortNr. %% Connect with matching capabilities and expect the connection to %% come up. @@ -158,9 +157,6 @@ cea_timeout(Config) -> start = event(Svc), {{closed, Ref, {'CEA', timeout}, T}, _} = {event(Svc), T}. -stop(_Config) -> - ok = diameter:stop(). - %% ---------------------------------------- %% Keep the server from sending CEA until the client has timed out. @@ -201,7 +197,7 @@ start_service(Name, Opts) -> diameter:start_service(Name, [{monitor, self()} | Opts]). opts(Config, Opts) -> - PortNr = ?util:read_priv(Config, portnr), + PortNr = proplists:get_value(portnr, Config), {connect, [{transport_module, diameter_tcp}, {transport_config, [{ip, ?ADDR}, {port, 0}, diff --git a/lib/diameter/test/diameter_examples_SUITE.erl b/lib/diameter/test/diameter_examples_SUITE.erl index b718899353..f02e74aef6 100644 --- a/lib/diameter/test/diameter_examples_SUITE.erl +++ b/lib/diameter/test/diameter_examples_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2013-2021. All Rights Reserved. +%% Copyright Ericsson AB 2013-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. @@ -24,29 +24,31 @@ -module(diameter_examples_SUITE). +%% testcase, no common_test dependency +-export([run/0, + run/1]). + +%% common_test wrapping -export([suite/0, all/0, - groups/0, - init_per_suite/1, - end_per_suite/1, - init_per_group/2, - end_per_group/2]). - -%% testcases --export([dict/1, - code/1, - start/1, - traffic/1]). + dict/1, + code/1]). +%% rpc calls -export([install/1, - call/1]). + start/1, + traffic/1]). -include("diameter.hrl"). --include_lib("common_test/include/ct.hrl"). - %% =========================================================================== +-define(util, diameter_util). + +%% The order here is significant and causes the server to listen +%% before the clients connect. +-define(NODES, [server, client]). + %% @inherits dependencies between example dictionaries. This is needed %% in order compile them in the right order. Can't compile to erl to %% find out since @inherits is a beam dependency. @@ -58,56 +60,55 @@ -define(DICT0, [rfc3588_base, rfc6733_base]). %% Transport protocols over which the example Diameter nodes are run. --define(PROTS, [tcp, sctp]). +-define(PROTS, [sctp || ?util:have_sctp()] ++ [tcp]). + +-define(L, atom_to_list). +-define(A, list_to_atom). %% =========================================================================== +%% common_test wrapping suite() -> - [{timetrap, {minutes, 2}}]. + [{timetrap, {seconds, 45}}]. all() -> - [dict, - code, - {group, all}]. - -groups() -> - Tc = tc(), - [{all, [parallel], [{group, P} || P <- ?PROTS]} - | [{P, [], Tc} || P <- ?PROTS]]. - -%% Not used, but a convenient place to enable trace. -init_per_suite(Config) -> - Config. - -end_per_suite(_Config) -> - ok. - -init_per_group(all, Config) -> - Config; - -init_per_group(tcp = N, Config) -> - [{group, N} | Config]; - -init_per_group(sctp = N, Config) -> - case diameter_util:have_sctp() of - true -> - [{group, N} | Config]; - false-> - {skip, no_sctp} - end. + [dict, code]. + +dict(_Config) -> + run([dict]). + +code(Config) -> + run([{code, proplists:get_value(priv_dir, Config)}]). + +%% =========================================================================== + +%% run/0 -end_per_group(_, _) -> - ok. +run() -> + run(all()). -tc() -> - [traffic]. +%% run/1 + +run(dict) -> + compile_dicts(); +%% The example code doesn't use the example dictionaries, so a +%% separate testcase. + +run(code) -> + run_code(?util:tmpdir()); +run({code, Tmpdir}) -> + run_code(Tmpdir); + +%% Eg. erl -noinput -s diameter_examples_SUITE run code -s init stop ... +run(List) -> + ?util:run([{[fun run/1, T], 30000} || T <- List]). %% =========================================================================== -%% dict/1 +%% compile_dicts/0 %% %% Compile example dictionaries in examples/dict. -dict(_Config) -> +compile_dicts() -> Dirs = [filename:join(H ++ ["examples", "dict"]) || H <- [[code:lib_dir(diameter)], [here(), ".."]]], [] = [{F,D,RC} || {_,F} <- sort(find_files(Dirs, ".*\\.dia$")), @@ -201,26 +202,35 @@ make_name(Dict) -> {string:join(["diameter_gen", N, R], "_"), "diameter_" ++ N}. %% =========================================================================== -%% code/1 +%% compile_code/1 %% %% Compile example code under examples/code. -code(Config) -> - {ok, Peer, Node} = ?CT_PEER(), - [] = rpc:call(Node, - ?MODULE, - install, - [proplists:get_value(priv_dir, Config)]), - peer:stop(Peer). - -%% Compile on another node since the code path may be modified. -install(PrivDir) -> - Top = install(here(), PrivDir), +compile_code(Tmpdir) -> + {ok, Pid, Node} = slave(peer:random_name(), here()), + try + {ok, _Ebin} = rpc:call(Node, ?MODULE, install, [Tmpdir]) + after + peer:stop(Pid) + end. + +%% Compile in another node since the code path is modified. +install(Tmpdir) -> + {Top, Dia, Ebin} = install(here(), Tmpdir), + + %% Prepend the created directory just so that code:lib_dir/1 finds + %% it when compile:file/2 tries to resolve include_lib. + true = code:add_patha(Ebin), + Dia = code:lib_dir(diameter), %% assert + Src = filename:join([Top, "examples", "code"]), Files = find_files([Src], ".*\\.erl$"), - [] = [{F,E} || {_,F} <- Files, - {error, _, _} = E <- [compile:file(F, [warnings_as_errors, - return_errors])]]. + [] = [{F,T} || {_,F} <- Files, + T <- [compile:file(F, [warnings_as_errors, + return_errors, + {outdir, Ebin}])], + ok /= element(1, T)], + {ok, Ebin}. %% Copy include files into a temporary directory and adjust the code %% path in order for example code to be able to include them with @@ -230,20 +240,15 @@ install(PrivDir) -> %% preprocessor to find these otherwise. Generated hrls are only be %% under include in an installation. ("Installing" them locally is %% anathema.) -install(Dir, PrivDir) -> - %% Remove the path added to the peer (needed for the rpc:call/4 in - %% compile/1 to find ?MODULE) so the call to code:lib_dir/2 below - %% returns the installed path. - [Ebin | _] = code:get_path(), - true = code:del_path(Ebin), +install(Dir, Tmpdir) -> Top = top(Dir, code:lib_dir(diameter)), %% Create a new diameter/include in priv_dir. Copy all includes %% there, from below ../include and ../src/gen if they exist (in %% the repo). - Tmp = filename:join([PrivDir, "diameter"]), - TmpInc = filename:join([PrivDir, "diameter", "include"]), - TmpEbin = filename:join([PrivDir, "diameter", "ebin"]), + Tmp = filename:join([Tmpdir, "diameter"]), + TmpInc = filename:join([Tmp, "include"]), + TmpEbin = filename:join([Tmp, "ebin"]), [] = [{T,E} || T <- [Tmp, TmpInc, TmpEbin], {error, E} <- [file:make_dir(T)]], @@ -254,13 +259,7 @@ install(Dir, PrivDir) -> B <- [filename:basename(F)], D <- [filename:join([TmpInc, B])], {error, E} <- [file:copy(F,D)]], - - %% Prepend the created directory just so that code:lib_dir/1 finds - %% it when compile:file/2 tries to resolve include_lib. - true = code:add_patha(TmpEbin), - Tmp = code:lib_dir(diameter), %% assert - %% Return the top directory containing examples/code. - Top. + {Top, Tmp, TmpEbin}. find_files(Dirs, RE) -> lists:foldl(fun(D,A) -> fold_files(D, RE, A) end, @@ -275,6 +274,23 @@ store(Path, Dict) -> %% =========================================================================== +%% enslave/1 +%% +%% Start two nodes: one for the server, one for the client. + +enslave(Prefix) -> + [{S,N} || D <- [here()], + S <- ?NODES, + M <- [lists:append(["diameter", Prefix, ?L(S)])], + {ok, _, N} <- [slave(M,D)]]. + +slave(Name, Dir) -> + Args = [["-pa" | [lists:flatten(io_lib:format("~s", [D])) + || D <- [Dir, filename:join([Dir, "..", "ebin"])]]], + ["-setcookie", ?L(erlang:get_cookie())]], + {ok, _Pid, _Node} = peer:start_link(#{name => Name, + args => lists:append(Args)}). + here() -> filename:dirname(code:which(?MODULE)). @@ -285,21 +301,34 @@ top(Dir, LibDir) -> false -> LibDir end. -%% start/1 +%% start/2 -start({server, Prot}) -> +start({server, Prot, Ebin}) -> + true = code:add_patha(Ebin), ok = diameter:start(), ok = server:start(), {ok, Ref} = server:listen({Prot, any, 3868}), - [_] = diameter_util:lport(Prot, Ref), + [_] = ?util:lport(Prot, Ref), ok; -start({client = Svc, Prot}) -> +start({client = Svc, Prot, Ebin}) -> + true = code:add_patha(Ebin), ok = diameter:start(), true = diameter:subscribe(Svc), ok = client:start(), {ok, Ref} = client:connect({Prot, loopback, loopback, 3868}), - receive #diameter_event{info = {up, Ref, _, _, _}} -> ok end. + receive + #diameter_event{info = {up, Ref, _, _, _}} -> + ok + after + 2000 -> + timeout + end; + +start([Prot, Ebin | Nodes]) -> + [] = [RC || {S,N} <- Nodes, + RC <- [rpc:call(N, ?MODULE, start, [{S, Prot, Ebin}])], + RC /= ok]. %% traffic/1 %% @@ -309,21 +338,32 @@ traffic(server) -> ok; traffic(client) -> - {_, MRef} = spawn_monitor(fun() -> call(100) end), + {_, MRef} = spawn_monitor(fun() -> exit(call(100)) end), receive {'DOWN', MRef, process, _, Reason} -> Reason end; -traffic(Config) -> - Prot = proplists:get_value(group, Config), - {ok, ServerPeer, ServerNode} = ?CT_PEER(), - ok = rpc:call(ServerNode, ?MODULE, start, [{server, Prot}]), - {ok, ClientPeer, ClientNode} = ?CT_PEER(), - ok = rpc:call(ClientNode, ?MODULE, start, [{client, Prot}]), - ok = rpc:call(ClientNode, ?MODULE, traffic, [client]), - peer:stop(ClientPeer), - peer:stop(ServerPeer). +traffic({Prot, Ebin}) -> + Nodes = enslave(?L(Prot)), + [] = start([Prot, Ebin | Nodes]), + [] = [RC || {T,N} <- Nodes, + RC <- [rpc:call(N, ?MODULE, traffic, [T])], + RC /= ok]. + +%% run_code/1 + +run_code(Tmpdir) -> + true = is_alive(), %% need distribution for peer nodes + Tmp = ?util:mktemp(filename:join(Tmpdir, "diameter_examples")), + try + {ok, Ebin} = compile_code(Tmp), + [] = ?util:run([[fun traffic/1, {T, Ebin}] || T <- ?PROTS]) + after + file:del_dir_r(Tmp) + end. + +%% call/1 call(0) -> - exit(ok); + ok; call(N) -> {ok, _} = client:call(), diff --git a/lib/diameter/test/diameter_failover_SUITE.erl b/lib/diameter/test/diameter_failover_SUITE.erl index 8a3b3e8413..0c78119e50 100644 --- a/lib/diameter/test/diameter_failover_SUITE.erl +++ b/lib/diameter/test/diameter_failover_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. @@ -36,20 +36,19 @@ -module(diameter_failover_SUITE). +%% testcases, no common_test dependency +-export([run/0]). + +%% common_test wrapping -export([suite/0, - all/0]). - -%% testcases --export([start/1, - start_services/1, - connect/1, - send_ok/1, - send_nok/1, - send_discard_1/1, - send_discard_2/1, - stop_services/1, - empty/1, - stop/1]). + all/0, + parallel/1]). + +%% internal +-export([send_ok/0, + send_nok/0, + send_discard_1/0, + send_discard_2/0]). %% diameter callbacks -export([pick_peer/4, @@ -112,50 +111,61 @@ %% =========================================================================== suite() -> - [{timetrap, {seconds, 60}}]. + [{timetrap, {seconds, 90}}]. all() -> - [start, - start_services, - connect, - send_ok, - send_nok, - send_discard_1, - send_discard_2, - stop_services, - empty, - stop]. + [parallel]. + +parallel(_Config) -> + run(). %% =========================================================================== -%% start/stop testcases -start(_Config) -> - ok = diameter:start(). +%% run/0 + +run() -> + ok = diameter:start(), + try + ?util:run([{fun traffic/0, 60000}]) + after + ok = diameter:stop() + end. + +%% traffic/0 -start_services(_Config) -> +traffic() -> + Servers = start_services(), + ok = connect(Servers), + [] = send(), + [] = stop_services(), + [] = ets:tab2list(diameter_request). + +%% start_services/0 + +start_services() -> Servers = [server(N) || N <- ?SERVERS], [] = [T || C <- ?CLIENTS, T <- [diameter:start_service(C, ?SERVICE(C))], T /= ok], + Servers. - {save_config, Servers}. +%% send/0 -connect(Config) -> - {start_services, Servers} = proplists:get_value(saved_config, Config), +send() -> + Funs = [send_ok, send_nok, send_discard_1, send_discard_2], + ?util:run([[{?MODULE, F, []} || F <- Funs]]). - lists:foreach(fun(C) -> connect(C, Servers) end, ?CLIENTS). +%% connect/1 -stop_services(_Config) -> - [] = [{H,T} || H <- ?CLIENTS ++ ?SERVERS, - T <- [diameter:stop_service(H)], - T /= ok]. +connect(Servers) -> + lists:foreach(fun(C) -> connect(C, Servers) end, ?CLIENTS). -%% Ensure transports have been removed from request table. -empty(_Config) -> - [] = ets:tab2list(diameter_request). +%% stop_services/0 -stop(_Config) -> - ok = diameter:stop(). +stop_services() -> + [{H,T} || H <- ?CLIENTS ++ ?SERVERS, + T <- [diameter:stop_service(H)], + T /= ok]. %% ---------------------------------------- @@ -171,7 +181,7 @@ connect(Name, Refs) -> %% Send an STR and expect success after SERVER3 answers after a couple %% of failovers. -send_ok(_Config) -> +send_ok() -> Req = #diameter_base_STR{'Destination-Realm' = realm(?SERVER1), 'Termination-Cause' = ?LOGOUT, 'Auth-Application-Id' = ?APP_ID}, @@ -180,19 +190,19 @@ send_ok(_Config) -> = call(?CLIENT1, Req). %% Send an STR and expect failure when both servers fail. -send_nok(_Config) -> +send_nok() -> Req = #diameter_base_STR{'Destination-Realm' = realm(?SERVER4), 'Termination-Cause' = ?LOGOUT, 'Auth-Application-Id' = ?APP_ID}, {failover, ?LOGOUT} = call(?CLIENT1, Req). %% Send an STR and have prepare_retransmit discard it. -send_discard_1(_Config) -> +send_discard_1() -> Req = #diameter_base_STR{'Destination-Realm' = realm(?SERVER1), 'Termination-Cause' = ?TIMEOUT, 'Auth-Application-Id' = ?APP_ID}, {rejected, ?TIMEOUT} = call(?CLIENT2, Req). -send_discard_2(_Config) -> +send_discard_2() -> Req = #diameter_base_STR{'Destination-Realm' = realm(?SERVER4), 'Termination-Cause' = ?MOVED, 'Auth-Application-Id' = ?APP_ID}, diff --git a/lib/diameter/test/diameter_gen_sctp_SUITE.erl b/lib/diameter/test/diameter_gen_sctp_SUITE.erl index d3b2e89297..1333431943 100644 --- a/lib/diameter/test/diameter_gen_sctp_SUITE.erl +++ b/lib/diameter/test/diameter_gen_sctp_SUITE.erl @@ -27,14 +27,19 @@ -module(diameter_gen_sctp_SUITE). +%% testcases, no common_test dependency +-export([run/0, + run/1]). + +%% common_test wrapping -export([suite/0, all/0, init_per_suite/1, end_per_suite/1]). %% testcases --export([send_one_from_many/1, send_one_from_many/0, - send_many_from_one/1, send_many_from_one/0, +-export([send_one_from_many/1, + send_many_from_one/1, receive_what_was_sent/1]). -include_lib("kernel/include/inet_sctp.hrl"). @@ -67,7 +72,7 @@ %% =========================================================================== suite() -> - [{timetrap, {seconds, 10}}]. + [{timetrap, {seconds, 15}}]. all() -> [send_one_from_many, @@ -89,13 +94,20 @@ end_per_suite(_Config) -> %% =========================================================================== -%% send_one_from_many/0 +%% run/0 + +run() -> + run(all()). + +%% run/1 + +run(List) -> + diameter_util:run([{{?MODULE, F, [[]]}, 10000} || F <- List]). + +%% send_one_from_many/1 %% %% Demonstrates sluggish delivery of messages. -send_one_from_many() -> - [{timetrap, {seconds, 30}}]. - send_one_from_many(_) -> ?OK = send_multiple(128, 1, 1024). @@ -402,23 +414,20 @@ unmark(Bin) -> %% =========================================================================== -%% send_many_from_one/0 +%% send_many_from_one/1 %% %% Demonstrates sluggish delivery of messages. -send_many_from_one() -> - [{timetrap, {seconds, 30}}]. - send_many_from_one(_) -> ?OK = send_multiple(1, 128, 1024). %% =========================================================================== -%% receive_what_was_sent/1 +%% receive_what_was_sent/0 %% %% Demonstrates reception of a message that differs from that sent. -receive_what_was_sent(_Config) -> +receive_what_was_sent(_) -> ?OK = send_multiple(1, 1, 1024*32). %% =========================================================================== diff --git a/lib/diameter/test/diameter_gen_tcp_SUITE.erl b/lib/diameter/test/diameter_gen_tcp_SUITE.erl index db42ea813e..d1e01da27e 100644 --- a/lib/diameter/test/diameter_gen_tcp_SUITE.erl +++ b/lib/diameter/test/diameter_gen_tcp_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2014-2017. All Rights Reserved. +%% Copyright Ericsson AB 2014-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. @@ -27,11 +27,14 @@ -module(diameter_gen_tcp_SUITE). --export([suite/0, - all/0]). +%% testcases, not common_test dependency +-export([run/0, + run/1]). -%% testcases --export([send_long/1, +%% common_test wrapping +-export([suite/0, + all/0, + send_long/1, connect/1]). -define(LOOPBACK, {127,0,0,1}). @@ -46,13 +49,29 @@ all() -> [connect, %% Appears to fail only when run first. send_long]. +send_long(_) -> + send_long(). + +connect(_) -> + connect(). + %% =========================================================================== -%% send_long/1 +%% run/0 + +run() -> + run(all()). + +%% run/1 + +run(List) -> + diameter_util:run([{{?MODULE, F, [[]]}, 10000} || F <- List]). + +%% send_long/0 %% %% Test that a long message is received. -send_long(_) -> +send_long() -> {Sock, SendF} = connection(), B = binary:copy(<<$X>>, 1 bsl 20), ok = SendF(B), @@ -101,13 +120,13 @@ send(Sock, Bin) -> %% =========================================================================== -%% connect/1 +%% connect/0 %% %% Test that simultaneous connections succeed. This fails sporadically %% on OS X at the time of writing, when gen_tcp:connect/2 returns %% {error, econnreset}. -connect(_) -> +connect() -> {ok, LSock} = gen_tcp:listen(0, ?GEN_OPTS), {ok, {_,PortNr}} = inet:sockname(LSock), Count = lists:seq(1,8), %% 8 simultaneous connects diff --git a/lib/diameter/test/diameter_gh.spec b/lib/diameter/test/diameter_gh.spec index 45adb931e1..9662044402 100644 --- a/lib/diameter/test/diameter_gh.spec +++ b/lib/diameter/test/diameter_gh.spec @@ -1,4 +1,2 @@ {suites, "../diameter_test", all}. -{skip_cases,"../diameter_test",diameter_gen_sctp_SUITE, - [send_one_from_many,send_many_from_one], - "SCTP does not work on Github actions"}. +{skip_suites, "../diameter_test", [diameter_gen_sctp_SUITE], "SCTP does not work on Github actions"}. diff --git a/lib/diameter/test/diameter_length_SUITE.erl b/lib/diameter/test/diameter_length_SUITE.erl index daaaae6e00..66d1be114f 100644 --- a/lib/diameter/test/diameter_length_SUITE.erl +++ b/lib/diameter/test/diameter_length_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2013-2016. All Rights Reserved. +%% Copyright Ericsson AB 2013-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. @@ -24,20 +24,14 @@ -module(diameter_length_SUITE). +%% testcases, no common_test dependency +-export([run/0, + run/1]). + +%% common_test wrapping -export([suite/0, all/0, - groups/0, - init_per_suite/1, - end_per_suite/1, - init_per_group/2, - end_per_group/2, - init_per_testcase/2, - end_per_testcase/2]). - -%% testcases --export([start/1, - send/1, - stop/1]). + parallel/1]). %% diameter callbacks -export([peer_up/3, @@ -83,39 +77,20 @@ -define(LOGOUT, ?'DIAMETER_BASE_TERMINATION-CAUSE_LOGOUT'). --define(GROUPS, [exit, handle, discard]). - -define(L, atom_to_list). %% =========================================================================== suite() -> - [{timetrap, {seconds, 60}}]. + [{timetrap, {seconds, 120}}]. all() -> - [{group, G} || G <- ?GROUPS]. - -groups() -> - [{G, [], [start, send, stop]} || G <- ?GROUPS]. - -init_per_suite(Config) -> - ok = diameter:start(), - Config. - -end_per_suite(_Config) -> - ok = diameter:stop(). - -init_per_group(Group, Config) -> - [{group, Group} | Config]. - -end_per_group(_, _) -> - ok. + [parallel]. -init_per_testcase(_Name, Config) -> - Config. +parallel(_Config) -> + run(). -end_per_testcase(_, _) -> - ok. +%% =========================================================================== origin(exit) -> 0; origin(handle) -> 1; @@ -127,25 +102,39 @@ origin(2) -> discard. %% =========================================================================== +run() -> + run([exit, handle, discard]). + +run(List) + when is_list(List) -> + ok = diameter:start(), + try + ?util:run([[{[fun run/1, T], 30000} || T <- List]]) + after + ok = diameter:stop() + end; + +run(Group) -> + start(Group), + send(Group), + stop(). + %% start/1 -start(Config) -> - Group = proplists:get_value(group, Config), +start(Group) -> ok = diameter:start_service(?SERVER, ?SERVICE(?L(Group))), ok = diameter:start_service(?CLIENT, ?SERVICE(?CLIENT)), - LRef = ?util:listen(?SERVER, - tcp, - [{length_errors, Group}]), + LRef = ?util:listen(?SERVER, tcp, [{length_errors, Group}]), ?util:connect(?CLIENT, tcp, LRef, [{capabilities, [{'Origin-State-Id', origin(Group)}]}]). -%% stop/1 +%% stop/0 -stop(_Config) -> - ok = diameter:remove_transport(?CLIENT, true), +stop() -> ok = diameter:remove_transport(?SERVER, true), + ok = diameter:remove_transport(?CLIENT, true), ok = diameter:stop_service(?SERVER), ok = diameter:stop_service(?CLIENT). @@ -194,10 +183,7 @@ send(discard) -> {error, timeout} = call(4), #diameter_base_STA{'Result-Code' = ?SUCCESS} - = call(0); - -send(Config) -> - send(proplists:get_value(group, Config)). + = call(0). %% =========================================================================== diff --git a/lib/diameter/test/diameter_pool_SUITE.erl b/lib/diameter/test/diameter_pool_SUITE.erl index a36a4fa17a..40d34c6237 100644 --- a/lib/diameter/test/diameter_pool_SUITE.erl +++ b/lib/diameter/test/diameter_pool_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2015-2019. All Rights Reserved. +%% Copyright Ericsson AB 2015-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,17 +25,16 @@ -module(diameter_pool_SUITE). +%% testcases, no common_test dependency +-export([run/0, + run/1]). + +%% common_test wrapping -export([suite/0, all/0, - init_per_testcase/2, - end_per_testcase/2, - init_per_suite/1, - end_per_suite/1]). - -%% testcases --export([tcp_connect/1, - sctp_connect/1, - any_connect/1]). + tcp/1, + sctp/1, + any/1]). %% =========================================================================== @@ -62,44 +61,53 @@ %% =========================================================================== suite() -> - [{timetrap, {seconds, 30}}]. + [{timetrap, {seconds, 45}}]. all() -> - [tcp_connect, - sctp_connect, - any_connect]. + [tcp, sctp, any]. -init_per_testcase(_Name, Config) -> - Config. +tcp(_Config) -> + run([tcp]). -end_per_testcase(_Name, _Config) -> - diameter:stop(). - -init_per_suite(Config) -> - [{sctp, ?util:have_sctp()} | Config]. +sctp(_Config) -> + case ?util:have_sctp() of + true -> run([sctp]); + false -> {skip, no_sctp} + end. -end_per_suite(_Config) -> - ok. +any(_Config) -> + run([any]). %% =========================================================================== -tcp_connect(_Config) -> - connect(tcp, tcp). +%% run/0 -sctp_connect(Config) -> - case lists:member({sctp, true}, Config) of - true -> connect(sctp, sctp); - false -> {skip, no_sctp} - end. +run() -> + run(all()). + +%% run/1 + +run(tcp = T) -> + connect(T, T); -any_connect(_Config) -> - connect(any, tcp). +run(sctp = T) -> + connect(T, T); + +run(any = T) -> + connect(T, tcp); + +run(List) -> + ok = diameter:start(), + try + ?util:run([[{[fun run/1, T], 30000} || T <- List]]) + after + ok = diameter:stop() + end. %% connect/2 %% Establish multiple connections between a client and server. connect(ClientProt, ServerProt) -> - ok = diameter:start(), [] = [{S,T} || S <- ["server", "client"], T <- [diameter:start_service(S, ?SERVICE(S))], T /= ok], @@ -108,20 +116,24 @@ connect(ClientProt, ServerProt) -> LRef = ?util:listen("server", ServerProt, [{pool_size, 4}]), {4,0} = count("server", LRef, accept), %% 4 transports, no connections %% Establish 5 connections. - Ref = ?util:connect("client", ClientProt, LRef, [{pool_size, 5}]), - {5,5} = count("client", Ref, pool), %% 5 connections + N = pool_size(5), %% connections to establish + Ref = ?util:connect("client", ClientProt, LRef, [{pool_size, N}]), + {N,N} = count("client", Ref, pool), %% N connections %% Ensure the server has started replacement transports within a %% reasonable time. Sleepsince there's no guarantee the %% replacements have been started before the client has received %% 'up' events. (Although it's likely.) - sleep(), - {9,5} = count("server", LRef, accept), %% 5 connections + 4 accepting + timer:sleep(1000), + N4 = N + 4, + {N4,N} = count("server", LRef, accept), %% N connections + 4 accepting %% Ensure there are still the expected number of accepting transports %% after stopping the client service. ok = diameter:stop_service("client"), - sleep(), + timer:sleep(1000), {4,0} = count("server", LRef, accept), %% 4 transports, no connections %% Done. + ok = diameter:remove_transport("client", true), + ok = diameter:remove_transport("server", true), ok = diameter:stop_service("server"). count(Name, Ref, Key) -> @@ -131,5 +143,10 @@ count(Name, Ref, Key) -> {Key, Ps} = lists:keyfind(Key, 1, T), {length(Ps), length(Cs)}. %% number of processes, connections -sleep() -> - receive after 1000 -> ok end. +%% Simultaneous connections are often refused on Darwin: don't try to +%% establish more than one. +pool_size(N) -> + case os:type() of + {_, 'darwin'} -> 1; + _ -> rand:uniform(N) + end. diff --git a/lib/diameter/test/diameter_reg_SUITE.erl b/lib/diameter/test/diameter_reg_SUITE.erl index cd9242faa8..02e10ffb74 100644 --- a/lib/diameter/test/diameter_reg_SUITE.erl +++ b/lib/diameter/test/diameter_reg_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. @@ -24,86 +24,76 @@ -module(diameter_reg_SUITE). --export([suite/0, - all/0, - groups/0, - init_per_suite/1, - end_per_suite/1]). +%% testcases, no common_test dependency +-export([run/0, + run/1]). -%% testcases --export([add/1, - add_new/1, - remove/1, - down/1, - terms/1, - pids/1]). +%% common_test wrapping +-export([all/0, + parallel/1]). --define(reg, diameter_reg). --define(util, diameter_util). +-define(reg, diameter_reg). %% =========================================================================== -suite() -> - [{timetrap, {seconds, 60}}]. - all() -> - [{group, all}, - {group, all, [parallel]}]. + [parallel]. -groups() -> - [{all, [], tc()}]. +parallel(_Config) -> + run(). -tc() -> - [add, - add_new, - remove, - down, - terms, - pids]. +%% =========================================================================== -init_per_suite(Config) -> - ok = diameter:start(), - Config. +%% run/0 -end_per_suite(_Config) -> - ok = diameter:stop(). +run() -> + run([add, add_new, remove, down, terms, pids]). -%% =========================================================================== +%% run/1 + +run(List) + when is_list(List) -> + ok = diameter:start(), + try + diameter_util:run([{[fun run/1, T], 10000} || T <- List]) + after + ok = diameter:stop() + end; -add(_) -> +run(add) -> Ref = make_ref(), true = ?reg:add(Ref), true = ?reg:add(Ref), [{Ref, Pid}] = ?reg:match(Ref), - Pid = self(). + Pid = self(); -add_new(_) -> +run(add_new) -> Ref = make_ref(), true = ?reg:add_new(Ref), - false = ?reg:add_new(Ref). + false = ?reg:add_new(Ref); -remove(_) -> +run(remove) -> Ref = make_ref(), true = ?reg:add_new(Ref), true = ?reg:add_new({Ref}), true = ?reg:remove({Ref}), [{Ref, Pid}] = ?reg:match(Ref), - Pid = self(). + Pid = self(); -down(_) -> +run(down) -> Ref = make_ref(), {_, MRef} = spawn_monitor(fun() -> ?reg:add_new(Ref), timer:sleep(1000) end), receive {'DOWN', MRef, process, _, _} -> ok end, timer:sleep(1000), - [] = ?reg:match(Ref). + [] = ?reg:match(Ref); -terms(_) -> +run(terms) -> Ref = make_ref(), true = ?reg:add_new(Ref), [[Pid]] = [L || {T,L} <- ?reg:terms(), T == Ref], - Pid = self(). + Pid = self(); -pids(_) -> +run(pids) -> Ref = make_ref(), true = ?reg:add_new(Ref), %% Don't match [[Ref]] since this will only necessarily be the diff --git a/lib/diameter/test/diameter_relay_SUITE.erl b/lib/diameter/test/diameter_relay_SUITE.erl index 9de5cbe685..2502820e0f 100644 --- a/lib/diameter/test/diameter_relay_SUITE.erl +++ b/lib/diameter/test/diameter_relay_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. @@ -34,26 +34,13 @@ -module(diameter_relay_SUITE). +%% testcases, no common_test dependency +-export([run/0]). + +%% common_test wrapping -export([suite/0, all/0, - groups/0]). - -%% testcases --export([start/1, - start_services/1, - connect/1, - send1/1, - send2/1, - send3/1, - send4/1, - send_loop/1, - send_timeout_1/1, - send_timeout_2/1, - info/1, - counters/1, - disconnect/1, - stop_services/1, - stop/1]). + parallel/1]). %% diameter callbacks -export([pick_peer/4, @@ -115,41 +102,37 @@ %% =========================================================================== suite() -> - [{timetrap, {seconds, 60}}]. + [{timetrap, {seconds, 30}}]. all() -> - [start, - start_services, - connect, - {group, all}, - counters, - {group, all, [parallel]}, - disconnect, - stop_services, - stop]. - -groups() -> - [{all, [], tc()}]. + [parallel]. -%% Traffic cases run when services are started and connections -%% established. -tc() -> - [send1, - send2, - send3, - send4, - send_loop, - send_timeout_1, - send_timeout_2, - info]. +parallel(_Config) -> + run(). %% =========================================================================== -%% start/stop testcases -start(_Config) -> - ok = diameter:start(). +%% run/0 + +run() -> + ok = diameter:start(), + try + ?util:run([{fun traffic/0, 20000}]) + after + ok = diameter:stop() + end. -start_services(_Config) -> +%% traffic/0 + +traffic() -> + Servers = start_services(), + Conns = connect(Servers), + [] = send(), + [] = counters(), + [] = disconnect(Conns), + [] = stop_services(). + +start_services() -> [S1,S2,S3,S4] = [server(N, ?DICT_COMMON) || N <- [?SERVER1, ?SERVER2, ?SERVER3, @@ -158,30 +141,32 @@ start_services(_Config) -> ok = diameter:start_service(?CLIENT, ?SERVICE(?CLIENT, ?DICT_COMMON)), - {save_config, [{?RELAY1, [S1,S2,R2]}, - {?RELAY2, [S3,S4]}, - {?CLIENT, [R1,R2]}]}. - -connect(Config) -> - {_, Conns} = proplists:get_value(saved_config, Config), + [{?RELAY1, [S1,S2,R2]}, {?RELAY2, [S3,S4]}, {?CLIENT, [R1,R2]}]. - ?util:write_priv(Config, - "cfg", - lists:flatmap(fun({CN,Ss}) -> connect(CN, Ss) end, - Conns)). +connect(Servers) -> + lists:flatmap(fun({CN,Ss}) -> connect(CN, Ss) end, Servers). -disconnect(Config) -> - [] = [{T,C} || C <- ?util:read_priv(Config, "cfg"), - T <- [break(C)], - T /= ok]. +disconnect(Conns) -> + [{T,C} || C <- Conns, + T <- [break(C)], + T /= ok]. -stop_services(_Config) -> - [] = [{H,T} || H <- ?SERVICES, - T <- [diameter:stop_service(H)], - T /= ok]. +stop_services() -> + [{H,T} || H <- ?SERVICES, + T <- [diameter:stop_service(H)], + T /= ok]. -stop(_Config) -> - ok = diameter:stop(). +%% Traffic cases run when services are started and connections +%% established. +send() -> + ?util:run([[fun traffic/1, T] || T <- [send1, + send2, + send3, + send4, + send_loop, + send_timeout_1, + send_timeout_2, + info]]). %% ---------------------------------------- @@ -203,50 +188,50 @@ connect(Name, Refs) -> %% traffic testcases %% 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). +traffic(send1) -> + call(?SERVER1); +traffic(send2) -> + call(?SERVER2); +traffic(send3) -> + call(?SERVER3); +traffic(send4) -> + call(?SERVER4); %% Send an ASR that loops between the relays (RELAY1 -> RELAY2 -> %% RELAY1) and expect the loop to be detected. -send_loop(_Config) -> +traffic(send_loop) -> Req = ['ASR', {'Destination-Realm', realm(?SERVER1)}, {'Destination-Host', ?SERVER1}, {'Auth-Application-Id', ?APP_ID}], #'diameter_base_answer-message'{'Result-Code' = ?LOOP_DETECTED} - = call(Req, [{filter, realm}]). + = call(Req, [{filter, realm}]); %% Send a RAR that is incorrectly routed and then discarded and expect %% different results depending on whether or not we or the relay %% timeout first. -send_timeout_1(_Config) -> +traffic(send_timeout_1) -> #'diameter_base_answer-message'{'Result-Code' = ?UNABLE_TO_DELIVER} - = send_timeout(7000). -send_timeout_2(_Config) -> - {error, timeout} = send_timeout(3000). + = traffic({timeout, 7000}); +traffic(send_timeout_2) -> + {error, timeout} = traffic({timeout, 3000}); -send_timeout(Tmo) -> +traffic({timeout, Tmo}) -> Req = ['RAR', {'Destination-Realm', realm(?SERVER1)}, {'Destination-Host', ?SERVER1}, {'Auth-Application-Id', ?APP_ID}, {'Re-Auth-Request-Type', ?AUTHORIZE_ONLY}], - call(Req, [{filter, realm}, {timeout, Tmo}]). + call(Req, [{filter, realm}, {timeout, Tmo}]); -info(_Config) -> +traffic(info) -> %% Wait for RELAY1 to have answered all requests, so that the %% suite doesn't end before all answers are sent and counted. receive after 6000 -> ok end, [] = ?util:info(). -counters(_Config) -> - [] = ?util:run([[fun counters/2, K, S] - || K <- [statistics, transport, connections], - S <- ?SERVICES]). +counters() -> + ?util:run([[fun counters/2, K, S] + || K <- [statistics, transport, connections], + S <- ?SERVICES]). counters(Key, Svc) -> counters(Key, Svc, [_|_] = diameter:service_info(Svc, Key)). diff --git a/lib/diameter/test/diameter_stats_SUITE.erl b/lib/diameter/test/diameter_stats_SUITE.erl index 4716082394..b48e7a84bf 100644 --- a/lib/diameter/test/diameter_stats_SUITE.erl +++ b/lib/diameter/test/diameter_stats_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2015. 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. @@ -24,55 +24,52 @@ -module(diameter_stats_SUITE). +%% testcases, no common_test dependency +-export([run/0, + run/1]). + +%% common_test wrapping -export([suite/0, all/0, - groups/0, - init_per_suite/1, - end_per_suite/1]). - -%% testcases --export([reg/1, - incr/1, - read/1, - sum/1, - flush/1]). + parallel/1]). -define(stat, diameter_stats). %% =========================================================================== suite() -> - [{timetrap, {seconds, 60}}]. + [{timetrap, {seconds, 30}}]. all() -> - [{group, all}, - {group, all, [parallel]}]. + [parallel]. -groups() -> - [{all, [], tc()}]. +parallel(_Config) -> + run(). -tc() -> - [reg, - incr, - read, - sum, - flush]. +%% =========================================================================== -init_per_suite(Config) -> - ok = diameter:start(), - Config. +%% run/0 -end_per_suite(_Config) -> - ok = diameter:stop(). +run() -> + run([reg, incr, read, sum, flush]). -%% =========================================================================== +%% run/1 + +run(List) + when is_list(List) -> + ok = diameter:start(), + try + diameter_util:run([{[fun run/1, T], 15000} || T <- List]) + after + ok = diameter:stop() + end; -reg(_) -> +run(reg) -> Ref = '$1', true = ?stat:reg(Ref), - false = ?stat:reg(Ref). %% duplicate + false = ?stat:reg(Ref); %% duplicate -incr(_) -> +run(incr) -> Ref = '_', Ctr = x, false = ?stat:incr(Ctr), %% not registered, @@ -83,9 +80,9 @@ incr(_) -> 2 = ?stat:incr(Ctr, self(), 2) end), ok = fold(Ctr, Ref, 3), %% folded - ?stat:flush([self(), Ref]). + ?stat:flush([self(), Ref]); -read(_) -> +run(read) -> Ref = make_ref(), C1 = {a,b}, C2 = {b,a}, @@ -99,9 +96,9 @@ read(_) -> = ?stat:read([self(), Ref, make_ref()]), [] = ?stat:read([]), [] = ?stat:read([make_ref()]), - ?stat:flush([self(), Ref, make_ref()]). + ?stat:flush([self(), Ref, make_ref()]); -sum(_) -> +run(sum) -> Ref = make_ref(), C1 = {a,b}, C2 = {b,a}, @@ -116,9 +113,9 @@ sum(_) -> [{Self, [{C1,1}, {C2,2}]}] = ?stat:sum([self()]), [{Ref, [{C1,7}]}, {Self, [{C1,1}, {C2,2}]}] - = ?stat:flush([self(), Ref]). + = ?stat:flush([self(), Ref]); -flush(_) -> +run(flush) -> Ref = make_ref(), Ctr = '_', true = ?stat:reg(Ref), diff --git a/lib/diameter/test/diameter_sync_SUITE.erl b/lib/diameter/test/diameter_sync_SUITE.erl index 2785bd92d6..395c99bd0b 100644 --- a/lib/diameter/test/diameter_sync_SUITE.erl +++ b/lib/diameter/test/diameter_sync_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. @@ -24,63 +24,59 @@ -module(diameter_sync_SUITE). +%% testcases, no common_test depedency +-export([run/0, + run/1]). + +%% common_test wrapping -export([suite/0, all/0, - groups/0, - init_per_suite/1, - end_per_suite/1]). - -%% testcases --export([call/1, - cast/1, - timeout/1, - flush/1]). + parallel/1]). -define(sync, diameter_sync). --define(util, diameter_util). - --define(TIMEOUT, infinity). %% =========================================================================== suite() -> - [{timetrap, {seconds, 60}}]. + [{timetrap, {seconds, 15}}]. all() -> - [{group, all}, - {group, all, [parallel]}]. + [parallel]. -groups() -> - [{all, [], tc()}]. +parallel(_Config) -> + run(). -tc() -> - [call, - cast, - timeout, - flush]. +%% =========================================================================== -init_per_suite(Config) -> - ok = diameter:start(), - Config. +%% run/0 -end_per_suite(_Config) -> - ok = diameter:stop(). +run() -> + run([call, cast, timeout, flush]). -%% =========================================================================== +%% run/1 + +run(List) + when is_list(List) -> + ok = diameter:start(), + try + diameter_util:run([{[fun run/1, T], 10000} || T <- List]) + after + ok = diameter:stop() + end; -call(_) -> +run(call) -> Ref = make_ref(), Q = {q, Ref}, F = fun() -> Ref end, - Ref = ?sync:call(Q, F, infinity, ?TIMEOUT), + Ref = ?sync:call(Q, F, infinity, infinity), Ref = ?sync:call(Q, F, 0, infinity), Ref = call(Q, F), Ref = call(Q, {fun(_) -> Ref end, x}), timeout = call(Q, fun() -> exit(unexpected) end), {_,_,_} = call(Q, {erlang, now, []}), - {_,_,_} = call(Q, [fun erlang:now/0]). + {_,_,_} = call(Q, [fun erlang:now/0]); -cast(_) -> +run(cast) -> Ref = make_ref(), Q = {q, Ref}, false = ?sync:carp(Q), @@ -95,26 +91,21 @@ cast(_) -> true = 2 =< ?sync:pending(), true = lists:member(Q, ?sync:queues()), %% ... and that the max number of requests is respected. - rejected = ?sync:call(Q, {erlang, now, []}, 1, ?TIMEOUT), - rejected = ?sync:cast(Q, {erlang, now, []}, 1, ?TIMEOUT), + rejected = ?sync:call(Q, {erlang, now, []}, 1, infinity), + rejected = ?sync:cast(Q, {erlang, now, []}, 1, infinity), %% Monitor on the identifiable request and see that exits when we %% let the blocking request finish. MRef = erlang:monitor(process, Pid), {value, P} = ?sync:carp(Q), P ! Ref, - Ref = receive - {'DOWN', MRef, process, _, Reason} -> - Reason - after ?TIMEOUT -> - false - end. - -timeout(_) -> + Ref = receive {'DOWN', MRef, process, _, Reason} -> Reason end; + +run(timeout) -> Q = make_ref(), ok = ?sync:cast(Q, {timer, sleep, [2000]}, infinity, 2000), - timeout = ?sync:call(Q, fun() -> ok end, infinity, 1000). + timeout = ?sync:call(Q, fun() -> ok end, infinity, 1000); -flush(_) -> +run(flush) -> Q = make_ref(), F = {timer, sleep, [2000]}, ok = cast(Q, F), 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 a12759bac2..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, @@ -127,14 +115,6 @@ %% =========================================================================== -%% Fraction of shuffle/parallel groups to randomly skip. --define(SKIP, 0.90). - -%% Positive number of testcases from which to select (randomly) from -%% tc(), the list of testcases to run, or [] to run all. The random -%% selection is to limit the time it takes for the suite to run. --define(LIMIT, #{tcp => 42, sctp => 5}). - -define(util, diameter_util). -define(A, list_to_atom). @@ -164,30 +144,19 @@ %% Which dictionary to use in the clients. -define(RFCS, [rfc3588, rfc6733, rfc4005]). -%% Whether to decode stringish Diameter types to strings, or leave -%% them as binary. --define(STRING_DECODES, [false, true]). - %% Which transport protocol to use. --define(TRANSPORTS, [tcp, sctp]). - -%% Send from a dedicated process? --define(SENDERS, [true, false]). - -%% Message callbacks from diameter_{tcp,sctp}? --define(CALLBACKS, [true, false]). - --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. @@ -270,285 +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]. - -%% Redefine this to run one or more groups for debugging purposes. --define(GROUPS, []). -%-define(GROUPS, [[sctp,rfc6733,record,map,false,false,true,false]]). - -%% Issues with gen_sctp sporadically cause huge numbers of failed -%% testcases when running testcases in parallel. -groups() -> - Names = names([] == ?GROUPS orelse ?GROUPS), - [{P, [P], Ts} || Ts <- [tc()], P <- [shuffle, parallel]] - ++ - [{?util:name(N), [], [{group, if T == sctp; S -> shuffle; - true -> parallel end}]} - || [T,_,_,_,S|_] = N <- Names] - ++ - [{T, [], [{group, ?util:name(N)} || N <- Names, - T == hd(N)]} - || T <- ?TRANSPORTS] - ++ - [{traffic, [], [{group, T} || T <- ?TRANSPORTS]}]. - -names() -> - [[T,R,E,D,S,ST,SS,CS] || T <- ?TRANSPORTS, - R <- ?RFCS, - E <- ?ENCODINGS, - D <- ?DECODINGS, - S <- ?STRING_DECODES, - ST <- ?CALLBACKS, - SS <- ?SENDERS, - CS <- ?SENDERS, - ?SKIP =< rand:uniform()]. - -names(true) -> - names(names()); - -names(Names) -> - [N || N <- Names, - [CS,SS|_] <- [lists:reverse(N)], - SS orelse CS]. %% avoid deadlock - -%% -------------------- - -init_per_suite() -> - [{timetrap, {seconds, 60}}]. - -init_per_suite(Config) -> - [{rfc4005, compile_and_load()}, {sctp, ?util:have_sctp()} | Config]. - -end_per_suite(_Config) -> - code:delete(nas4005), - code:purge(nas4005), - ok. + [parallel]. -%% -------------------- +parallel(_Config) -> + run(). -init_per_group(_) -> - [{timetrap, {seconds, 30}}]. +%% =========================================================================== -init_per_group(Name, Config) - when Name == shuffle; - Name == parallel -> - start_services(Config), - add_transports(Config), - replace({sleep, Name == parallel}, Config); +%% 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. + +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. -init_per_group(sctp = Name, Config) -> - {_, Sctp} = lists:keyfind(Name, 1, Config), - if Sctp -> - Config; - true -> - {skip, Name} - end; +%% traffic/1 -init_per_group(Name, Config) -> - Nas = proplists:get_value(rfc4005, Config, false), - case ?util:name(Name) of - [_,R,_,_,_,_,_,_] when R == rfc4005, true /= Nas -> - {skip, rfc4005}; - [T,R,E,D,S,ST,SS,CS] -> - G = #group{transport = T, - strings = S, - encoding = E, - client_service = [$C|?util:unique_string()], - client_dict = appdict(R), - client_sender = CS, - server_service = [$S|?util:unique_string()], - server_decoding = D, - server_sender = SS, - server_throttle = ST}, - replace([{group, G}, {runlist, select(T)}], Config); - _ -> - Config - end. +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). -end_per_group(Name, Config) - when Name == shuffle; - Name == parallel -> - remove_transports(Config), - stop_services(Config); +%% start_service/2 -end_per_group(_, _) -> +start_service(Svc, Opts) -> + {ok, _} = {diameter:start_service(Svc, Opts), Opts}, ok. -select(T) -> - try maps:get(T, ?LIMIT) of - N -> - lists:sublist(?util:scramble(tc()), max(5, rand:uniform(N))) - catch - error:_ -> ?LIMIT - end. +%% send/1 -%% -------------------- - -%% 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) -> - TCs = proplists:get_value(runlist, Config, []), - Run = [] == TCs orelse lists:member(Name, TCs), - case [G || #group{transport = sctp} = G - <- [proplists:get_value(group, Config)]] - of - [_] when Name == send_maxlen; - Name == send_long -> - {skip, sctp}; - _ when not Run -> - {skip, random}; - _ -> - proplists:get_value(sleep, Config, false) - andalso timer:sleep(rand:uniform(200)), - [{testcase, Name} | Config] - end. +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)). -end_per_testcase(_, _) -> - ok. +%% send/2 -%% replace/2 -%% -%% Work around common_test running init functions inappropriately, and -%% this accumulating more config than expected. - -replace(Pairs, Config) - when is_list(Pairs) -> - lists:foldl(fun replace/2, Config, Pairs); - -replace({Key, _} = T, Config) -> - [T | lists:keydelete(Key, 1, Config)]. - -%% -------------------- - -%% 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, #group{transport = sctp}) + when F == send_long; + F == send_maxlen -> + ok; -%% =========================================================================== -%% start/stop testcases +send(F, Cfg) -> + timer:sleep(rand:uniform(2000)), + apply(?MODULE, F, [[{testcase, F}, {group, Cfg}]]). -start(_Config) -> - ok = diameter:start(). +%% wait/1 -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(Refs) + when is_list(Refs) -> + lists:map(fun wait/1, Refs); -bool() -> - 0.5 =< rand:uniform(). +wait(MRef) -> + receive {'DOWN', MRef, process, _, T} -> T end. + +%% =========================================================================== -add_transports(Config) -> +%% server/1 + +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) -> []; @@ -567,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} @@ -600,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, @@ -1135,6 +950,8 @@ send_anything(Config) -> %% =========================================================================== +group(#group{} = Rec) -> + Rec; group(Config) -> #group{} = proplists:get_value(group, Config). @@ -1903,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) -> diff --git a/lib/diameter/test/diameter_util.erl b/lib/diameter/test/diameter_util.erl index e2fd3333d3..18b12da827 100644 --- a/lib/diameter/test/diameter_util.erl +++ b/lib/diameter/test/diameter_util.erl @@ -31,6 +31,9 @@ fold/3, foldl/3, scramble/1, + choose/1, + tmpdir/0, + mktemp/1, unique_string/0, have_sctp/0, eprof/1]). @@ -42,11 +45,6 @@ disconnect/4, info/0]). -%% common_test-specific --export([write_priv/3, - read_priv/2, - map_priv/3]). - -define(L, atom_to_list). %% --------------------------------------------------------------------------- @@ -102,18 +100,37 @@ consult(Path) -> %% --------------------------------------------------------------------------- %% run/1 %% -%% Evaluate functions in parallel and return a list of those that -%% failed to return. The fun takes a boolean (did the function return -%% or not), the function that was evaluated, the return value or exit -%% reason and the prevailing accumulator. +%% Evaluate functions in parallel and raise an error exception if any +%% fail to return. run(L) -> - fold(fun cons/4, [], L). - -cons(true, _, _, Acc) -> - Acc; -cons(false, F, RC, Acc) -> - [{F, RC} | Acc]. + Ref = make_ref(), + AccF = fun(I, [F|T]) -> + Ref == (catch element(1, I)) + orelse error(#{failed => F, reason => I}), + T + end, + Pid = self(), + Funs = [fun() -> down(Pid, self()), {Ref, eval(F)} end || F <- L], + [] = fold(AccF, L, Funs). + +%% down/2 + +down(Parent, Worker) + when is_pid(Parent) -> + spawn(fun() -> + monitor(process, Worker), + down(monitor(process, Parent), Worker) + end); + +%% Die with the worker, kill the worker if the parent dies. +down(MRef, Pid) -> + receive + {'DOWN', MRef, process, _, _} -> + exit(Pid, kill); + {'DOWN', _, process, Pid, _} -> + ok + end. %% --------------------------------------------------------------------------- %% fold/3 @@ -121,61 +138,43 @@ cons(false, F, RC, Acc) -> %% Parallel fold. Results are folded in the order received. fold(Fun, Acc0, L) - when is_function(Fun, 4) -> - Ref = make_ref(), - %% Spawn a middleman to collect down messages from processes - %% spawned for each function so as not to assume that all DOWN - %% messages are ours. - MRef = run1([fun fold/4, Ref, Fun, Acc0, L], Ref), - {Ref, RC} = down(MRef), - RC. - -fold(Ref, Fun, Acc0, L) -> - recv(run(Ref, L), Ref, Fun, Acc0). - -run(Ref, L) -> - [{run1(F, Ref), F} || F <- L]. - -run1(F, Ref) -> - {_, MRef} = spawn_monitor(fun() -> exit({Ref, eval(F)}) end), - MRef. - -recv([], _, _, Acc) -> + when is_list(L) -> + fold(Fun, Acc0, lists:foldl(fun(F,A) -> + {P,M} = spawn_eval(F), + A#{M => P} + end, + #{}, + L)); + +fold(_, Acc, Map) + when 0 == map_size(Map) -> Acc; -recv(L, Ref, Fun, Acc) -> - {MRef, R} = down(), - {MRef, F} = lists:keyfind(MRef, 1, L), - recv(lists:keydelete(MRef, 1, L), - Ref, - Fun, - acc(R, Ref, F, Fun, Acc)). -acc({Ref, RC}, Ref, F, Fun, Acc) -> - Fun(true, F, RC, Acc); -acc(Reason, _, F, Fun, Acc) -> - Fun(false, F, Reason, Acc). +fold(Fun, Acc, #{} = Map) -> + receive + {'DOWN', MRef, process, _, Info} when is_map_key(MRef, Map) -> + fold(Fun, Fun(Info, Acc), maps:remove(MRef, Map)) + end. -down(MRef) -> - receive {'DOWN', MRef, process, _, Reason} -> Reason end. +%% spawn_eval/1 -down() -> - receive {'DOWN', MRef, process, _, Reason} -> {MRef, Reason} end. +spawn_eval(F) -> + spawn_monitor(fun() -> exit(eval(F)) end). %% --------------------------------------------------------------------------- %% foldl/3 %% %% Parallel fold. Results are folded in order of the function list. -foldl(Fun, Acc0, L) - when is_function(Fun, 4) -> - Ref = make_ref(), - recvl(run(Ref, L), Ref, Fun, Acc0). +foldl(Fun, Acc0, L) -> + lists:foldl(fun(R,A) -> acc(Fun, R, A) end, + Acc0, + [M || F <- L, {_,M} <- [spawn_eval(F)]]). -recvl([], _, _, Acc) -> - Acc; -recvl([{MRef, F} | L], Ref, Fun, Acc) -> - R = down(MRef), - recvl(L, Ref, Fun, acc(R, Ref, F, Fun, Acc)). +%% acc/3 + +acc(Fun, MRef, Acc) -> + receive {'DOWN', MRef, process, _, Info} -> Fun(Info, Acc) end. %% --------------------------------------------------------------------------- %% scramble/1 @@ -186,6 +185,33 @@ scramble(L) -> [X || {_,X} <- lists:sort([{rand:uniform(), T} || T <- L])]. %% --------------------------------------------------------------------------- +%% choose/1 +%% +%% Return a random element from a list. + +choose([_|_] = List) -> + hd(lists:nthtail(rand:uniform(length(List)) - 1, List)). + +%% --------------------------------------------------------------------------- +%% tmpdir/0 + +tmpdir() -> + case os:getenv("TMPDIR") of + false -> + "/tmp"; + Dir -> + Dir + end. + +%% mktemp/1 + +mktemp(Prefix) -> + Suf = integer_to_list(erlang:monotonic_time()), + Tmp = Prefix ++ "." ++ Suf, + ok = file:make_dir(Tmp), + Tmp. + +%% --------------------------------------------------------------------------- %% unique_string/0 unique_string() -> @@ -208,8 +234,7 @@ have_sctp(_) -> {ok, Sock} -> gen_sctp:close(Sock), true; - {error, E} when E == eprotonosupport; - E == esocktnosupport -> %% fail on any other reason + _ -> false end. @@ -218,6 +243,13 @@ have_sctp(_) -> %% %% Evaluate a function in one of a number of forms. +eval({F, infinity}) -> + eval(F); +eval({F, Tmo}) + when is_integer(Tmo) -> + {ok, _} = timer:exit_after(Tmo, timeout), + eval(F); + eval({M,[F|A]}) when is_atom(F) -> apply(M,F,A); @@ -231,55 +263,13 @@ eval([F|A]) eval(L) when is_list(L) -> - run(L); + [eval(F) || F <- L]; eval(F) when is_function(F,0) -> F(). %% --------------------------------------------------------------------------- -%% write_priv/3 -%% -%% Write an arbitrary term to a named file. - -write_priv(Config, Name, Term) -> - write(path(Config, Name), Term). - -write(Path, Term) -> - ok = file:write_file(Path, term_to_binary(Term)). - -%% read_priv/2 -%% -%% Read a term from a file. - -read_priv(Config, Name) -> - read(path(Config, Name)). - -read(Path) -> - {ok, Bin} = file:read_file(Path), - binary_to_term(Bin). - -%% map_priv/3 -%% -%% Modify a term in a file and return both old and new values. - -map_priv(Config, Name, Fun1) -> - map(path(Config, Name), Fun1). - -map(Path, Fun1) -> - T0 = read(Path), - T1 = Fun1(T0), - write(Path, T1), - {T0, T1}. - -path(Config, Name) - when is_atom(Name) -> - path(Config, ?L(Name)); -path(Config, Name) -> - Dir = proplists:get_value(priv_dir, Config), - filename:join([Dir, Name]). - -%% --------------------------------------------------------------------------- %% lport/2 %% %% Lookup the port number of a tcp/sctp listening transport. diff --git a/lib/diameter/test/diameter_watchdog_SUITE.erl b/lib/diameter/test/diameter_watchdog_SUITE.erl index f3f168e671..02f15ff21b 100644 --- a/lib/diameter/test/diameter_watchdog_SUITE.erl +++ b/lib/diameter/test/diameter_watchdog_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2018. 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,18 +25,22 @@ -module(diameter_watchdog_SUITE). +%% testcases, no common_test dependency +-export([run/0, + run/1]). + +%% common_test wrapping -export([suite/0, all/0, - init_per_suite/1, - end_per_suite/1]). - -%% testcases --export([reopen/0, reopen/1, reopen/4, reopen/6, - suspect/1, suspect/4, - okay/1, okay/4]). - --export([id/1, %% jitter callback - run1/1, + reopen/1, + suspect/1, + okay/1]). + +%% internal callbacks +-export([reopen/4, reopen/6, + suspect/4, + okay/4, + id/1, %% jitter callback abuse/1, abuse/2]). @@ -48,7 +52,6 @@ -export([message/3]). -include("diameter.hrl"). --include("diameter_ct.hrl"). %% =========================================================================== @@ -105,49 +108,72 @@ [])). %% Log to make failures identifiable. --define(LOG(T), ?LOG("~p", [T])). --define(LOG(F,A), ct:pal("~p: " ++ F, [self() | A])). --define(WARN(F,A), ct:pal(error, "~p: " ++ F, [self() | A])). +-define(LOG(F,A), io:format("~p: " ++ F ++ "~n", [self() | A])). %% =========================================================================== suite() -> - [{timetrap, {seconds, 90}}]. + [{timetrap, {seconds, 315}}]. all() -> - [reopen, - suspect, - okay]. + [reopen, suspect, okay]. -init_per_suite(Config) -> - ok = diameter:start(), - Config. +reopen(_Config) -> + run([reopen]). + +suspect(_Config) -> + run([suspect]). + +okay(_Config) -> + run([okay]). + +%% =========================================================================== + +%% run/0 -end_per_suite(_Config) -> - ok = diameter:stop(). +run() -> + run(all()). + +%% run/1. + +run(reopen) -> + reopen(); %% 20 watchdogs @ 15 sec + +run(suspect) -> + suspect(); + +run(okay) -> + okay(); + +run(List) -> + ok = diameter:start(), + try + ?util:run([{[fun run/1, T], maps:get(T, #{reopen => 300000}, 90000)} + || T <- List]) + after + ok = diameter:stop() + end. %% =========================================================================== -%% # reopen/1 +%% # reopen/0 %% =========================================================================== %% Test the watchdog state machine for the required failover, failback %% and reopen behaviour by examining watchdog events. reopen() -> - [{timetrap, {minutes, 5}}]. %% 20 watchdogs @ 15 sec - -reopen(_) -> - [] = run([[reopen, T, W, N, M] - || T <- [listen, connect], %% watchdog to test - W <- ?WD_TIMERS, %% watchdog_timer value - N <- [0,1,2], %% DWR's to answer before ignoring - M <- ['DWR', 'DWA', 'RAA']]). %% how to induce failback + ?util:run([{?MODULE, reopen, [T, W, N, M]} + || T <- [listen, connect], %% watchdog to test + W <- ?WD_TIMERS, %% watchdog_timer value + N <- [0,1,2], %% DWR's to answer before ignoring + M <- ['DWR', 'DWA', 'RAA']]). %% how to induce failback reopen(Test, Wd, N, M) -> %% Publish a ref ensure the connecting transport is added only %% once events from the listening transport are subscribed to. Ref = make_ref(), - [] = run([[reopen, T, Test, Ref, Wd, N, M] || T <- [listen, connect]]). + ?util:run([{?MODULE, reopen, [T, Test, Ref, Wd, N, M]} + || T <- [listen, connect]]). %% reopen/6 @@ -377,14 +403,14 @@ tpid(Ref, [[{ref, Ref}, TPid. %% =========================================================================== -%% # suspect/1 +%% # suspect/0 %% =========================================================================== %% Configure transports to require a set number of watchdog timeouts %% before moving from OKAY to SUSPECT. -suspect(_) -> - [] = run([[abuse, [suspect, N]] || N <- [0,1,3]]). +suspect() -> + ?util:run([{?MODULE, abuse, [[suspect, N]]} || N <- [0,1,3]]). suspect(Type, Fake, Ref, N) when is_reference(Ref) -> @@ -417,7 +443,7 @@ suspect(TRef, false, SvcName, N) -> %% abuse/1 abuse(F) -> - [] = run([[abuse, F, T] || T <- [listen, connect]]). + ?util:run([{?MODULE, abuse, [F, T]} || T <- [listen, connect]]). abuse(F, [_,_,_|_] = Args) -> ?LOG("~p", [Args]), @@ -425,21 +451,21 @@ abuse(F, [_,_,_|_] = Args) -> abuse([F|A], Test) -> Ref = make_ref(), - [] = run([[abuse, F, [T, T == Test, Ref] ++ A] - || T <- [listen, connect]]); + ?util:run([{?MODULE, abuse, [F, [T, T == Test, Ref] ++ A]} + || T <- [listen, connect]]); abuse(F, Test) -> abuse([F], Test). %% =========================================================================== -%% # okay/1 +%% # okay/0 %% =========================================================================== %% Configure the number of watchdog exchanges before moving from %% REOPEN to OKAY. -okay(_) -> - [] = run([[abuse, [okay, N]] || N <- [0,2,3]]). +okay() -> + ?util:run([{?MODULE, abuse, [[okay, N]]} || N <- [0,2,3]]). okay(Type, Fake, Ref, N) when is_reference(Ref) -> @@ -626,23 +652,6 @@ choose(false, _, X) -> X. id(T) -> T. -%% run/1 -%% -%% A more useful badmatch in case of failure. - -run(Fs) -> - ?util:run([{?MODULE, [run1, F]} || F <- Fs]). - -run1([F|A]) -> - ok = try - apply(?MODULE, F, A), - ok - catch - E:R:Stack -> - ?WARN("~p", [{A, E, R, Stack}]), - Stack - end. - %% jitter/2 jitter(?WD(T), _) -> diff --git a/lib/diameter/test/modules.mk b/lib/diameter/test/modules.mk index b1717aff00..fb8cfc445c 100644 --- a/lib/diameter/test/modules.mk +++ b/lib/diameter/test/modules.mk @@ -50,9 +50,6 @@ MODULES = \ diameter_transport_SUITE \ diameter_watchdog_SUITE -HRL_FILES = \ - diameter_ct.hrl - DATA = \ diameter_codec_SUITE_data/avps.dia \ diameter_codec_SUITE_data/send.dia \ |