aboutsummaryrefslogtreecommitdiffstats
path: root/lib/diameter/test
diff options
context:
space:
mode:
Diffstat (limited to 'lib/diameter/test')
-rw-r--r--lib/diameter/test/diameter_compiler_SUITE.erl12
-rw-r--r--lib/diameter/test/diameter_dpr_SUITE.erl196
-rw-r--r--lib/diameter/test/diameter_failover_SUITE.erl141
-rw-r--r--lib/diameter/test/diameter_traffic_SUITE.erl46
-rw-r--r--lib/diameter/test/diameter_util.erl18
-rw-r--r--lib/diameter/test/modules.mk5
6 files changed, 341 insertions, 77 deletions
diff --git a/lib/diameter/test/diameter_compiler_SUITE.erl b/lib/diameter/test/diameter_compiler_SUITE.erl
index 4b792b5426..79bf9d32db 100644
--- a/lib/diameter/test/diameter_compiler_SUITE.erl
+++ b/lib/diameter/test/diameter_compiler_SUITE.erl
@@ -31,8 +31,8 @@
%% testcases
-export([format/1, format/2,
replace/1, replace/2,
- generate/1, generate/4, generate/0,
- examples/1, examples/0]).
+ generate/1, generate/4,
+ examples/1]).
-export([dict/0]). %% fake dictionary module
@@ -339,7 +339,7 @@
%% ===========================================================================
suite() ->
- [{timetrap, {minutes, 2}}].
+ [{timetrap, {minutes, 10}}].
all() ->
[format,
@@ -407,9 +407,6 @@ re({RE, Repl}, Bin) ->
%%
%% Ensure success when generating code and compiling.
-generate() ->
- [{timetrap, {seconds, 2*length(?REPLACE)}}].
-
generate(Config) ->
Bin = proplists:get_value(base, Config),
Rs = lists:zip(?REPLACE, lists:seq(1, length(?REPLACE))),
@@ -436,9 +433,6 @@ generate(Mods, Bin, N, Mode) ->
%%
%% Compile dictionaries extracted from various standards.
-examples() ->
- [{timetrap, {seconds, 3*length(?EXAMPLES)}}].
-
examples(_Config) ->
Dir = filename:join([code:lib_dir(diameter, examples), "dict"]),
[D || D <- ?EXAMPLES, _ <- [examples(?S(D), Dir)]].
diff --git a/lib/diameter/test/diameter_dpr_SUITE.erl b/lib/diameter/test/diameter_dpr_SUITE.erl
new file mode 100644
index 0000000000..9252650bf7
--- /dev/null
+++ b/lib/diameter/test/diameter_dpr_SUITE.erl
@@ -0,0 +1,196 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Tests of the disconnect_cb configuration.
+%%
+
+-module(diameter_dpr_SUITE).
+
+-export([suite/0,
+ all/0,
+ groups/0,
+ init_per_group/2,
+ end_per_group/2]).
+
+%% testcases
+-export([start/1,
+ connect/1,
+ remove_transport/1,
+ stop_service/1,
+ check/1,
+ stop/1]).
+
+%% disconnect_cb
+-export([disconnect/5]).
+
+-include("diameter.hrl").
+
+%% ===========================================================================
+
+-define(util, diameter_util).
+
+-define(ADDR, {127,0,0,1}).
+
+-define(CLIENT, "CLIENT").
+-define(SERVER, "SERVER").
+
+-define(DICT_COMMON, ?DIAMETER_DICT_COMMON).
+-define(APP_ID, ?DICT_COMMON:id()).
+
+%% Config for diameter:start_service/2.
+-define(SERVICE(Host),
+ [{'Origin-Host', Host},
+ {'Origin-Realm', "erlang.org"},
+ {'Host-IP-Address', [?ADDR]},
+ {'Vendor-Id', hd(Host)}, %% match this in disconnect/5
+ {'Product-Name', "OTP/diameter"},
+ {'Acct-Application-Id', [?APP_ID]},
+ {restrict_connections, false},
+ {application, [{dictionary, ?DICT_COMMON},
+ {module, #diameter_callback{_ = false}}]}]).
+
+%% Disconnect reasons that diameter passes as the first argument of a
+%% function configured as disconnect_cb.
+-define(REASONS, [transport, service, application]).
+
+%% Valid values for Disconnect-Cause.
+-define(CAUSES, [0, rebooting, 1, busy, 2, goaway]).
+
+%% Establish one client connection for element of this list,
+%% configured with disconnect/5 as disconnect_cb and returning the
+%% specified value.
+-define(RETURNS,
+ [[close, {dpr, [{cause, invalid}]}], [ignore, close], []]
+ ++ [[{dpr, [{timeout, 5000}, {cause, T}]}] || T <- ?CAUSES]).
+
+%% ===========================================================================
+
+suite() ->
+ [{timetrap, {seconds, 60}}].
+
+all() ->
+ [{group, R} || R <- ?REASONS].
+
+%% The group determines how transports are terminated: by remove_transport,
+%% stop_service or application stop.
+groups() ->
+ Ts = tc(),
+ [{R, [], Ts} || R <- ?REASONS].
+
+init_per_group(Name, Config) ->
+ [{group, Name} | Config].
+
+end_per_group(_, _) ->
+ ok.
+
+tc() ->
+ [start, connect, remove_transport, stop_service, check, stop].
+
+%% ===========================================================================
+%% start/stop testcases
+
+start(_Config) ->
+ ok = diameter:start(),
+ ok = diameter:start_service(?SERVER, ?SERVICE(?SERVER)),
+ ok = diameter:start_service(?CLIENT, ?SERVICE(?CLIENT)).
+
+connect(Config) ->
+ Pid = spawn(fun init/0), %% process for disconnect_cb to bang
+ Grp = group(Config),
+ LRef = ?util:listen(?SERVER, tcp),
+ Refs = [?util:connect(?CLIENT, tcp, LRef, opts(RCs, {Grp, Pid}))
+ || RCs <- ?RETURNS],
+ ?util:write_priv(Config, config, [Pid | Refs]).
+
+%% Remove all the client transports only in the transport group.
+remove_transport(Config) ->
+ transport == group(Config)
+ andalso (ok = diameter:remove_transport(?CLIENT, true)).
+
+%% Stop the service only in the service group.
+stop_service(Config) ->
+ service == group(Config)
+ andalso (ok = diameter:stop_service(?CLIENT)).
+
+%% Check for callbacks and stop the service. (Not the other way around
+%% for the timing reason explained below.)
+check(Config) ->
+ Grp = group(Config),
+ [Pid | Refs] = ?util:read_priv(Config, config),
+ Pid ! self(), %% ask for dictionary
+ Dict = receive {Pid, D} -> D end, %% get it
+ check(Refs, ?RETURNS, Grp, Dict). %% check for callbacks
+
+stop(_Config) ->
+ ok = diameter:stop().
+
+%% Whether or not there are callbacks after diameter:stop() depends on
+%% timing as long as the server runs on the same node: a server
+%% transport could close the connection before the client has chance
+%% to apply its callback. Therefore, just check that there haven't
+%% been any callbacks yet.
+check(_, _, application, Dict) ->
+ [] = dict:to_list(Dict);
+
+check([], [], _, _) ->
+ ok;
+
+check([Ref | Refs], CBs, Grp, Dict) ->
+ check1(Ref, hd(CBs), Grp, Dict),
+ check(Refs, tl(CBs), Grp, Dict).
+
+check1(Ref, [ignore | RCs], Reason, Dict) ->
+ check1(Ref, RCs, Reason, Dict);
+
+check1(Ref, [_|_], Reason, Dict) ->
+ {ok, Reason} = dict:find(Ref, Dict); %% callback with expected reason
+
+check1(Ref, [], _, Dict) ->
+ error = dict:find(Ref, Dict). %% no callback
+
+%% ----------------------------------------
+
+group(Config) ->
+ {group, Grp} = lists:keyfind(group, 1, Config),
+ Grp.
+
+%% Configure the callback with the group name (= disconnect reason) as
+%% extra argument.
+opts(RCs, T) ->
+ [{disconnect_cb, {?MODULE, disconnect, [T, RC]}} || RC <- RCs].
+
+%% Match the group name with the disconnect reason to ensure the
+%% callback is being called as expected.
+disconnect(Reason, Ref, Peer, {Reason, Pid}, RC) ->
+ io:format("disconnect: ~p ~p~n", [Ref, Reason]),
+ {_, #diameter_caps{vendor_id = {$C,$S}}} = Peer,
+ Pid ! {Reason, Ref},
+ RC.
+
+init() ->
+ exit(recv(dict:new())).
+
+recv(Dict) ->
+ receive
+ Pid when is_pid(Pid) ->
+ Pid ! {self(), Dict};
+ {Reason, Ref} ->
+ recv(dict:store(Ref, Reason, Dict))
+ end.
diff --git a/lib/diameter/test/diameter_failover_SUITE.erl b/lib/diameter/test/diameter_failover_SUITE.erl
index ed31670031..bb820a8bf2 100644
--- a/lib/diameter/test/diameter_failover_SUITE.erl
+++ b/lib/diameter/test/diameter_failover_SUITE.erl
@@ -18,19 +18,19 @@
%%
%%
-%% Tests of traffic between six Diameter nodes in three realms,
+%% Tests of traffic between seven Diameter nodes in four realms,
%% connected as follows.
%%
-%% ----- SERVER1.REALM2
-%% /
-%% / ----- SERVER2.REALM2
-%% | /
-%% CLIENT.REALM1 ------ SERVER3.REALM2
-%% | \
-%% | \
-%% \ ---- SERVER1.REALM3
-%% \
-%% ----- SERVER2.REALM3
+%% ----- SERVER1.REALM2 -----
+%% / \
+%% / ----- SERVER2.REALM2 ----- \
+%% | / \ |
+%% CLIENT.REALM1 ------ SERVER3.REALM2 ------ CLIENT.REALM4
+%% | \ / |
+%% | \ / |
+%% \ ---- SERVER1.REALM3 ----- /
+%% \ /
+%% ----- SERVER2.REALM3 -----
%%
-module(diameter_failover_SUITE).
@@ -44,12 +44,16 @@
connect/1,
send_ok/1,
send_nok/1,
+ send_discard_1/1,
+ send_discard_2/1,
stop_services/1,
stop/1]).
%% diameter callbacks
-export([pick_peer/4,
prepare_request/3,
+ prepare_retransmit/3,
+ handle_error/4,
handle_answer/4,
handle_request/3]).
@@ -62,14 +66,18 @@
-define(ADDR, {127,0,0,1}).
--define(CLIENT, "CLIENT.REALM1").
+-define(CLIENT1, "CLIENT.REALM1").
+-define(CLIENT2, "CLIENT.REALM4").
-define(SERVER1, "SERVER1.REALM2").
-define(SERVER2, "SERVER2.REALM2").
-define(SERVER3, "SERVER3.REALM2").
-define(SERVER4, "SERVER1.REALM3").
-define(SERVER5, "SERVER2.REALM3").
--define(SERVICES, [?CLIENT, ?SERVER1, ?SERVER2, ?SERVER3, ?SERVER4, ?SERVER5]).
+-define(IS_CLIENT(Svc), Svc == ?CLIENT1; Svc == ?CLIENT2).
+
+-define(CLIENTS, [?CLIENT1, ?CLIENT2]).
+-define(SERVERS, [?SERVER1, ?SERVER2, ?SERVER3, ?SERVER4, ?SERVER5]).
-define(DICT_COMMON, ?DIAMETER_DICT_COMMON).
@@ -77,26 +85,27 @@
-define(APP_ID, ?DICT_COMMON:id()).
%% Config for diameter:start_service/2.
--define(SERVICE(Host, Dict),
+-define(SERVICE(Host),
[{'Origin-Host', Host},
{'Origin-Realm', realm(Host)},
{'Host-IP-Address', [?ADDR]},
{'Vendor-Id', 12345},
{'Product-Name', "OTP/diameter"},
- {'Acct-Application-Id', [Dict:id()]},
+ {'Acct-Application-Id', [?APP_ID]},
{application, [{alias, ?APP_ALIAS},
- {dictionary, Dict},
+ {dictionary, ?DICT_COMMON},
{module, #diameter_callback
{peer_up = false,
peer_down = false,
- handle_error = false,
- prepare_retransmit = false,
default = ?MODULE}},
{answer_errors, callback}]}]).
-define(SUCCESS, 2001).
--define(LOGOUT, ?'DIAMETER_BASE_TERMINATION-CAUSE_DIAMETER_LOGOUT').
+%% Value of Termination-Cause determines client/server behaviour.
+-define(LOGOUT, ?'DIAMETER_BASE_TERMINATION-CAUSE_DIAMETER_LOGOUT').
+-define(MOVED, ?'DIAMETER_BASE_TERMINATION-CAUSE_DIAMETER_USER_MOVED').
+-define(TIMEOUT, ?'DIAMETER_BASE_TERMINATION-CAUSE_DIAMETER_SESSION_TIMEOUT').
%% ===========================================================================
@@ -109,6 +118,8 @@ all() ->
connect,
send_ok,
send_nok,
+ send_discard_1,
+ send_discard_2,
stop_services,
stop].
@@ -119,19 +130,20 @@ start(_Config) ->
ok = diameter:start().
start_services(_Config) ->
- S = [server(N, ?DICT_COMMON) || N <- tl(?SERVICES)],
-
- ok = diameter:start_service(?CLIENT, ?SERVICE(?CLIENT, ?DICT_COMMON)),
+ Servers = [server(N) || N <- ?SERVERS],
+ [] = [T || C <- ?CLIENTS,
+ T <- [diameter:start_service(C, ?SERVICE(C))],
+ T /= ok],
- {save_config, [{?CLIENT, S}]}.
+ {save_config, Servers}.
connect(Config) ->
- {_, Conns} = proplists:get_value(saved_config, Config),
+ {start_services, Servers} = proplists:get_value(saved_config, Config),
- lists:foreach(fun({CN,Ss}) -> connect(CN, Ss) end, Conns).
+ lists:foreach(fun(C) -> connect(C, Servers) end, ?CLIENTS).
stop_services(_Config) ->
- [] = [{H,T} || H <- ?SERVICES,
+ [] = [{H,T} || H <- ?CLIENTS ++ ?SERVERS,
T <- [diameter:stop_service(H)],
T /= ok].
@@ -140,8 +152,8 @@ stop(_Config) ->
%% ----------------------------------------
-server(Name, Dict) ->
- ok = diameter:start_service(Name, ?SERVICE(Name, Dict)),
+server(Name) ->
+ ok = diameter:start_service(Name, ?SERVICE(Name)),
{Name, ?util:listen(Name, tcp)}.
connect(Name, Refs) ->
@@ -153,30 +165,39 @@ connect(Name, Refs) ->
%% Send an STR and expect success after SERVER3 answers after a couple
%% of failovers.
send_ok(_Config) ->
- Req = ['STR', {'Destination-Realm', realm(?SERVER1)},
- {'Termination-Cause', ?LOGOUT},
- {'Auth-Application-Id', ?APP_ID}],
+ Req = #diameter_base_STR{'Destination-Realm' = realm(?SERVER1),
+ 'Termination-Cause' = ?LOGOUT,
+ 'Auth-Application-Id' = ?APP_ID},
#diameter_base_STA{'Result-Code' = ?SUCCESS,
'Origin-Host' = ?SERVER3}
- = call(Req, [{filter, realm}]).
+ = call(?CLIENT1, Req).
%% Send an STR and expect failure when both servers fail.
send_nok(_Config) ->
- Req = ['STR', {'Destination-Realm', realm(?SERVER4)},
- {'Termination-Cause', ?LOGOUT},
- {'Auth-Application-Id', ?APP_ID}],
- {error, failover} = call(Req, [{filter, realm}]).
+ 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) ->
+ 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) ->
+ Req = #diameter_base_STR{'Destination-Realm' = realm(?SERVER4),
+ 'Termination-Cause' = ?MOVED,
+ 'Auth-Application-Id' = ?APP_ID},
+ {discarded, ?MOVED} = call(?CLIENT2, Req).
%% ===========================================================================
realm(Host) ->
tl(lists:dropwhile(fun(C) -> C /= $. end, Host)).
-call(Req, Opts) ->
- diameter:call(?CLIENT, ?APP_ALIAS, Req, Opts).
-
-set([H|T], Vs) ->
- [H | Vs ++ T].
+call(Svc, Req) ->
+ diameter:call(Svc, ?APP_ALIAS, Req, [{filter, realm}]).
%% ===========================================================================
%% diameter callbacks
@@ -184,7 +205,8 @@ set([H|T], Vs) ->
%% pick_peer/4
%% Choose a server other than SERVER3 or SERVER5 if possible.
-pick_peer(Peers, _, ?CLIENT, _State) ->
+pick_peer(Peers, _, Svc, _State)
+ when ?IS_CLIENT(Svc) ->
case lists:partition(fun({_, #diameter_caps{origin_host = {_, OH}}}) ->
OH /= ?SERVER3 andalso OH /= ?SERVER5
end,
@@ -198,20 +220,41 @@ pick_peer(Peers, _, ?CLIENT, _State) ->
%% prepare_request/3
-prepare_request(Pkt, ?CLIENT, {_Ref, Caps}) ->
+prepare_request(Pkt, Svc, {_Ref, Caps})
+ when ?IS_CLIENT(Svc) ->
{send, prepare(Pkt, Caps)}.
prepare(#diameter_packet{msg = Req}, Caps) ->
#diameter_caps{origin_host = {OH, _},
origin_realm = {OR, _}}
= Caps,
- set(Req, [{'Session-Id', diameter:session_id(OH)},
- {'Origin-Host', OH},
- {'Origin-Realm', OR}]).
+ Req#diameter_base_STR{'Origin-Host' = OH,
+ 'Origin-Realm' = OR,
+ 'Session-Id' = diameter:session_id(OH)}.
+
+%% prepare_retransmit/3
+
+prepare_retransmit(#diameter_packet{header = H} = P, Svc, {_,_})
+ when ?IS_CLIENT(Svc) ->
+ #diameter_header{is_retransmitted = true} = H, %% assert
+ prepare(P).
+
+prepare(#diameter_packet{msg = M} = P) ->
+ case M#diameter_base_STR.'Termination-Cause' of
+ ?LOGOUT -> {send, P};
+ ?MOVED -> discard;
+ ?TIMEOUT -> {discard, rejected}
+ end.
+
+%% handle_error/4
+
+handle_error(Reason, Req, _, _) ->
+ {Reason, Req#diameter_base_STR.'Termination-Cause'}.
%% handle_answer/4
-handle_answer(Pkt, _Req, ?CLIENT, _Peer) ->
+handle_answer(Pkt, _Req, Svc, _Peer)
+ when ?IS_CLIENT(Svc) ->
#diameter_packet{msg = Rec, errors = []} = Pkt,
Rec.
@@ -219,8 +262,8 @@ handle_answer(Pkt, _Req, ?CLIENT, _Peer) ->
%% Only SERVER3 actually answers.
handle_request(Pkt, ?SERVER3, {_, Caps}) ->
- #diameter_packet{msg = #diameter_base_STR{'Session-Id' = SId,
- 'Origin-Host' = ?CLIENT}}
+ #diameter_packet{header = #diameter_header{is_retransmitted = true},
+ msg = #diameter_base_STR{'Session-Id' = SId}}
= Pkt,
#diameter_caps{origin_host = {OH, _},
origin_realm = {OR, _}}
diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl
index 5744ff0307..c157b0e304 100644
--- a/lib/diameter/test/diameter_traffic_SUITE.erl
+++ b/lib/diameter/test/diameter_traffic_SUITE.erl
@@ -38,6 +38,7 @@
result_codes/1,
send_ok/1,
send_nok/1,
+ send_bad_answer/1,
send_arbitrary/1,
send_unknown/1,
send_unknown_mandatory/1,
@@ -182,14 +183,14 @@ suite() ->
all() ->
[start, start_services, add_transports, result_codes]
- ++ [{group, name([E,C]), P} || E <- ?ENCODINGS,
- C <- ?CONNECTIONS,
- P <- [[], [parallel]]]
+ ++ [{group, ?util:name([E,C]), P} || E <- ?ENCODINGS,
+ C <- ?CONNECTIONS,
+ P <- [[], [parallel]]]
++ [remove_transports, stop_services, stop].
groups() ->
Ts = tc(),
- [{name([E,C]), [], Ts} || E <- ?ENCODINGS, C <- ?CONNECTIONS].
+ [{?util:name([E,C]), [], Ts} || E <- ?ENCODINGS, C <- ?CONNECTIONS].
init_per_group(Name, Config) ->
[{group, Name} | Config].
@@ -208,6 +209,7 @@ end_per_testcase(_, _) ->
tc() ->
[send_ok,
send_nok,
+ send_bad_answer,
send_arbitrary,
send_unknown,
send_unknown_mandatory,
@@ -308,6 +310,14 @@ send_nok(Config) ->
#'diameter_base_answer-message'{'Result-Code' = ?INVALID_AVP_BITS}
= call(Config, Req).
+%% Send an accounting ACR that the server tries to answer with an
+%% inappropriate header, resulting in no answer being sent and the
+%% request timing out.
+send_bad_answer(Config) ->
+ Req = ['ACR', {'Accounting-Record-Type', ?EVENT_RECORD},
+ {'Accounting-Record-Number', 2}],
+ {error, timeout} = call(Config, Req).
+
%% Send an ASR with an arbitrary AVP and expect success and the same
%% AVP in the reply.
send_arbitrary(Config) ->
@@ -549,7 +559,7 @@ call(Config, Req) ->
call(Config, Req, Opts) ->
Name = proplists:get_value(testcase, Config),
- [Encoding, Client] = name(proplists:get_value(group, Config)),
+ [Encoding, Client] = ?util:name(proplists:get_value(group, Config)),
diameter:call(?CLIENT,
dict(Req),
req(Req, Encoding),
@@ -589,17 +599,6 @@ set(Dict, E, FV, Rec)
set(_, _, _, Rec) ->
Rec.
-%% Contruct and deconstruct names to work around group names being
-%% restricted to atoms.
-
-name(Names)
- when is_list(Names) ->
- ?A(string:join([?L(A) || A <- Names], ","));
-
-name(A)
- when is_atom(A) ->
- [?A(S) || S <- string:tokens(?L(A), ",")].
-
%% ===========================================================================
%% diameter callbacks
@@ -770,6 +769,21 @@ request(#diameter_base_accounting_ACR{'Accounting-Record-Number' = 0},
request(#diameter_base_accounting_ACR{'Session-Id' = SId,
'Accounting-Record-Type' = RT,
+ 'Accounting-Record-Number' = 2 = RN},
+ #diameter_caps{origin_host = {OH, _},
+ origin_realm = {OR, _}}) ->
+ Ans = ['ACA', {'Result-Code', ?SUCCESS},
+ {'Session-Id', SId},
+ {'Origin-Host', OH},
+ {'Origin-Realm', OR},
+ {'Accounting-Record-Type', RT},
+ {'Accounting-Record-Number', RN}],
+
+ {reply, #diameter_packet{header = #diameter_header{is_error = true},%% not
+ msg = Ans}};
+
+request(#diameter_base_accounting_ACR{'Session-Id' = SId,
+ 'Accounting-Record-Type' = RT,
'Accounting-Record-Number' = RN},
#diameter_caps{origin_host = {OH, _},
origin_realm = {OR, _}}) ->
diff --git a/lib/diameter/test/diameter_util.erl b/lib/diameter/test/diameter_util.erl
index 890d24f6f8..5af4ad9ba5 100644
--- a/lib/diameter/test/diameter_util.erl
+++ b/lib/diameter/test/diameter_util.erl
@@ -24,7 +24,8 @@
%%
%% generic
--export([consult/2,
+-export([name/1,
+ consult/2,
run/1,
fold/3,
foldl/3,
@@ -45,6 +46,21 @@
-define(L, atom_to_list).
+
+%% ---------------------------------------------------------------------------
+%% name/2
+%%
+%% Contruct and deconstruct lists of atoms as atoms to work around
+%% group names in common_test being restricted to atoms.
+
+name(Names)
+ when is_list(Names) ->
+ list_to_atom(string:join([atom_to_list(A) || A <- Names], ","));
+
+name(A)
+ when is_atom(A) ->
+ [list_to_atom(S) || S <- string:tokens(atom_to_list(A), ",")].
+
%% ---------------------------------------------------------------------------
%% consult/2
%%
diff --git a/lib/diameter/test/modules.mk b/lib/diameter/test/modules.mk
index 7f163536fb..5898e125ae 100644
--- a/lib/diameter/test/modules.mk
+++ b/lib/diameter/test/modules.mk
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2010-2011. All Rights Reserved.
+# Copyright Ericsson AB 2010-2012. All Rights Reserved.
#
# The contents of this file are subject to the Erlang Public License,
# Version 1.1, (the "License"); you may not use this file except in
@@ -39,7 +39,8 @@ MODULES = \
diameter_traffic_SUITE \
diameter_relay_SUITE \
diameter_tls_SUITE \
- diameter_failover_SUITE
+ diameter_failover_SUITE \
+ diameter_dpr_SUITE
HRL_FILES = \
diameter_ct.hrl