aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/diameter/doc/src/diameter_compile.xml32
-rw-r--r--lib/diameter/doc/src/diameter_dict.xml5
-rw-r--r--lib/diameter/doc/src/diameter_make.xml38
-rw-r--r--lib/diameter/examples/code/redirect_cb.erl4
-rw-r--r--lib/diameter/test/Makefile5
-rw-r--r--lib/diameter/test/diameter_compiler_SUITE.erl51
-rw-r--r--lib/diameter/test/diameter_ct.erl2
-rw-r--r--lib/diameter/test/diameter_examples_SUITE.erl334
-rw-r--r--lib/diameter/test/modules.mk1
9 files changed, 396 insertions, 76 deletions
diff --git a/lib/diameter/doc/src/diameter_compile.xml b/lib/diameter/doc/src/diameter_compile.xml
index 0bd7ad1789..fc81e4efed 100644
--- a/lib/diameter/doc/src/diameter_compile.xml
+++ b/lib/diameter/doc/src/diameter_compile.xml
@@ -11,7 +11,7 @@
<comref>
<header>
<copyright>
-<year>2011</year><year>2012</year>
+<year>2011</year><year>2013</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -59,6 +59,7 @@ The module &man_make; provides an alternate compilation interface.</p>
Compile a single dictionary file to Erlang source.
Valid options are as follows.</p>
+<taglist>
<tag><![CDATA[-i <dir>]]></tag>
<item>
<p>
@@ -71,7 +72,6 @@ dependency, not an erl/hrl dependency.</p>
Multiple <c>-i</c> options can be specified.</p>
</item>
-<taglist>
<tag><![CDATA[-o <dir>]]></tag>
<item>
<p>
@@ -90,18 +90,30 @@ Supress erl and hrl generation, respectively.</p>
<tag><![CDATA[--prefix <prefix>]]></tag>
<item>
<p>
-Set <c>&dict_name;</c> or <c>&dict_prefix;</c> to the specified
-string.
-Overrides any setting in the file itself.</p>
+Transform the input dictionary before compilation, setting
+<c>&dict_name;</c> or <c>&dict_prefix;</c> to the specified
+string.</p>
</item>
-<tag><![CDATA[--inherits <dict>]]></tag>
+<tag><![CDATA[--inherits <arg>]]></tag>
<item>
<p>
-Append &dict_inherits; of the specified module.
-Specifying <c>"-"</c> has the effect of discarding clearing any
-previous inherits, both in the dictionary file and on the options
-list.</p>
+Transform the input dictionary before compilation, appending
+<c>&dict_inherits;</c> of the specified string.</p>
+
+<p>
+Two forms of <c>--inherits</c> have special meaning:</p>
+
+<pre>
+--inherits -
+--inherits Prev/Mod
+</pre>
+
+<p>
+The first has the effect of clearing any previous inherits, the second
+of replacing a previous inherits of <c>Prev</c> to one of <c>Mod</c>.
+This allows the semantics of the input dictionary to be changed without
+modifying the file itself.</p>
<p>
Multiple <c>--inherits</c> options can be specified.</p>
diff --git a/lib/diameter/doc/src/diameter_dict.xml b/lib/diameter/doc/src/diameter_dict.xml
index 1034781ff2..419dc143af 100644
--- a/lib/diameter/doc/src/diameter_dict.xml
+++ b/lib/diameter/doc/src/diameter_dict.xml
@@ -263,15 +263,14 @@ dictionary's definitions but the former makes for easier reuse.</p>
<p>
All dictionaries should typically inherit &the_rfc; AVPs from
-<c>diameter_gen_base_rfc3588</c>.</p>
+<c>diameter_gen_base_rfc6733</c>.</p>
<p>
Example:</p>
<pre>
-@inherits diameter_gen_base_rfc3588
+@inherits diameter_gen_base_rfc6733
</pre>
-
</item>
<marker id="avp_types"/>
diff --git a/lib/diameter/doc/src/diameter_make.xml b/lib/diameter/doc/src/diameter_make.xml
index da6124310e..ec71251be1 100644
--- a/lib/diameter/doc/src/diameter_make.xml
+++ b/lib/diameter/doc/src/diameter_make.xml
@@ -14,6 +14,7 @@
<header>
<copyright>
<year>2012</year>
+<year>2013</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -73,7 +74,7 @@ Compile a single dictionary file to Erlang source.
<taglist>
-<tag><c>{include, Dir::string()}</c></tag>
+<tag><c>{include, string()}</c></tag>
<item>
<p>
Prepend the specified directory to the code path.
@@ -85,7 +86,7 @@ dependency, not an erl/hrl dependency.</p>
Multiple <c>include</c> options can be specified.</p>
</item>
-<tag><c>{outdir, Dir::string()}</c></tag>
+<tag><c>{outdir, string()}</c></tag>
<item>
<p>
Write generated source to the specified directory.
@@ -95,18 +96,30 @@ Defaults to the current working directory.</p>
<tag><c>{name|prefix, string()}</c></tag>
<item>
<p>
-Set <c>&dict_name;</c> or <c>&dict_prefix;</c> to the specified
-string.
-Overrides any setting in the file itself.</p>
+Transform the input dictionary before compilation, setting
+<c>&dict_name;</c> or <c>&dict_prefix;</c> to the specified
+string.</p>
</item>
-<tag><c>{inherits, Mod::string()}</c></tag>
+<tag><c>{inherits, string()}</c></tag>
<item>
<p>
-Append &dict_inherits; of the specified module.
-Specifying <c>"-"</c> has the effect of discarding clearing any
-previous inherits, both in the dictionary file and on the options
-list.</p>
+Transform the input dictionary before compilation, appending
+<c>&dict_inherits;</c> of the specified string.</p>
+
+<p>
+Two forms of <c>@inherits</c> have special meaning:</p>
+
+<pre>
+{inherits, "-"}
+{inherits, "Prev/Mod"}
+</pre>
+
+<p>
+The first has the effect of clearing any previous inherits, the second
+of replacing a previous inherits of <c>Prev</c> to one of <c>Mod</c>.
+This allows the semantics of the input dictionary to be changed without
+modifying the file itself.</p>
<p>
Multiple <c>inherits</c> options can be specified.</p>
@@ -126,8 +139,9 @@ Multiple <c>inherits</c> options can be specified.</p>
<p>
All options are string-valued.
-In particular, it is not currently possible to
-an &dict_inherits; module as an atom() or a path as a &filename;</p>
+In particular, it is not currently possible to specify
+an &dict_inherits; module as an atom(), or a path as an arbitrary
+&filename;</p>
</section>
diff --git a/lib/diameter/examples/code/redirect_cb.erl b/lib/diameter/examples/code/redirect_cb.erl
index da31add70d..69836774a1 100644
--- a/lib/diameter/examples/code/redirect_cb.erl
+++ b/lib/diameter/examples/code/redirect_cb.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2013. 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
@@ -20,7 +20,7 @@
-module(redirect_cb).
-include_lib("diameter/include/diameter.hrl").
--include_lib("diameter/src/app/diameter_gen_base_rfc3588.hrl").
+-include_lib("diameter/include/diameter_gen_base_rfc3588.hrl").
%% diameter callbacks
-export([peer_up/3,
diff --git a/lib/diameter/test/Makefile b/lib/diameter/test/Makefile
index 061f0bcbef..9719c67b32 100644
--- a/lib/diameter/test/Makefile
+++ b/lib/diameter/test/Makefile
@@ -93,6 +93,11 @@ info:
@$(call list,HRL_FILES)
@echo
@$(call list,SUITES)
+ @echo
+ @echo erl = $(shell which erl)
+ @erl -noinput \
+ -eval 'io:format("diameter = ~s~n", [code:lib_dir(diameter)])' \
+ -s init stop
@echo ========================================
help:
diff --git a/lib/diameter/test/diameter_compiler_SUITE.erl b/lib/diameter/test/diameter_compiler_SUITE.erl
index 79bf9d32db..81722c8dca 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-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2013. 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
@@ -31,8 +31,7 @@
%% testcases
-export([format/1, format/2,
replace/1, replace/2,
- generate/1, generate/4,
- examples/1]).
+ generate/1, generate/4]).
-export([dict/0]). %% fake dictionary module
@@ -328,14 +327,6 @@
"@codecs mymod "
"Origin-Host Origin-Realm\n&"}]}]).
-%% Standard dictionaries in examples/dict.
--define(EXAMPLES, [rfc4004_mip,
- rfc4005_nas,
- rfc4006_cc,
- rfc4072_eap,
- rfc4590_digest,
- rfc4740_sip]).
-
%% ===========================================================================
suite() ->
@@ -344,8 +335,7 @@ suite() ->
all() ->
[format,
replace,
- generate,
- examples].
+ generate].
%% Error handling testcases will make an erroneous dictionary out of
%% the base dictionary and check that the expected error results.
@@ -429,41 +419,6 @@ generate(Mods, Bin, N, Mode) ->
andalso ({ok, _} = compile:file(File ++ ".erl", [return_errors])).
%% ===========================================================================
-%% examples/1
-%%
-%% Compile dictionaries extracted from various standards.
-
-examples(_Config) ->
- Dir = filename:join([code:lib_dir(diameter, examples), "dict"]),
- [D || D <- ?EXAMPLES, _ <- [examples(?S(D), Dir)]].
-
-examples(Dict, Dir) ->
- {Name, Pre} = make_name(Dict),
- ok = diameter_make:codec(filename:join([Dir, Dict ++ ".dia"]),
- [{name, Name},
- {prefix, Pre},
- inherits("rfc3588_base")
- | opts(Dict)]),
- {ok, _, _} = compile:file(Name ++ ".erl", [return]).
-
-opts(M)
- when M == "rfc4006_cc";
- M == "rfc4072_eap" ->
- [inherits("rfc4005_nas")];
-opts("rfc4740_sip") ->
- [inherits("rfc4590_digest")];
-opts(_) ->
- [].
-
-inherits(File) ->
- {Name, _} = make_name(File),
- {inherits, File ++ "/" ++ Name}.
-
-make_name(File) ->
- {R, [$_|N]} = lists:splitwith(fun(C) -> C /= $_ end, File),
- {string:join(["diameter_gen", N, R], "_"), "diameter_" ++ N}.
-
-%% ===========================================================================
modify(Bin, Mods) ->
lists:foldl(fun re/2, Bin, Mods).
diff --git a/lib/diameter/test/diameter_ct.erl b/lib/diameter/test/diameter_ct.erl
index 1697287a22..ed2f884681 100644
--- a/lib/diameter/test/diameter_ct.erl
+++ b/lib/diameter/test/diameter_ct.erl
@@ -53,7 +53,7 @@ info(L0, L1) ->
L0,
L1),
Diff = [T, C, {memory, M}],
- ct:pal("INFO: ~p~n", [Diff]).
+ io:format("INFO: ~p~n", [Diff]).
diff(time, T0, T1) ->
timer:now_diff(T1, T0);
diff --git a/lib/diameter/test/diameter_examples_SUITE.erl b/lib/diameter/test/diameter_examples_SUITE.erl
new file mode 100644
index 0000000000..6d797f6911
--- /dev/null
+++ b/lib/diameter/test/diameter_examples_SUITE.erl
@@ -0,0 +1,334 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2013. 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%
+%%
+
+%%
+%% Test example code under ../examples/code.
+%%
+
+-module(diameter_examples_SUITE).
+
+-export([suite/0,
+ all/0]).
+
+%% testcases
+-export([dict/1, dict/0,
+ code/1,
+ enslave/1,
+ start/1,
+ traffic/1,
+ stop/1]).
+
+-export([install/1,
+ call/1]).
+
+-include("diameter.hrl").
+
+%% ===========================================================================
+
+-define(util, diameter_util).
+
+%% The order here is significant and causes the server to listen
+%% before the clients connect.
+-define(NODES, [compile, server, client]).
+
+%% Options to ct_slave:start/2.
+-define(TIMEOUTS, [{T, 15000} || T <- [boot_timeout,
+ init_timeout,
+ start_timeout]]).
+
+%% @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.
+-define(INHERITS, [{rfc4006_cc, [rfc4005_nas]},
+ {rfc4072_eap, [rfc4005_nas]},
+ {rfc4740_sip, [rfc4590_digest]}]).
+
+%% Common dictionaries to inherit from examples.
+-define(DICT0, [rfc3588_base, rfc6733_base]).
+
+%% ===========================================================================
+
+suite() ->
+ [{timetrap, {seconds, 45}}].
+
+all() ->
+ [dict,
+ code,
+ enslave,
+ start,
+ traffic,
+ stop].
+
+%% ===========================================================================
+%% dict/1
+%%
+%% Compile example dictionaries in examples/dict.
+
+dict() ->
+ [{timetrap, {minutes, 10}}].
+
+dict(_Config) ->
+ Dirs = [filename:join(H ++ ["examples", "dict"])
+ || H <- [[code:lib_dir(diameter)], [here(), ".."]]],
+ [] = [{F,D,RC} || {_,F} <- sort(find_files(Dirs, ".*\\.dia")),
+ D <- ?DICT0,
+ RC <- [make(F,D)],
+ RC /= ok].
+
+sort([{_,_} | _] = Files) ->
+ lists:sort(fun({A,_},{B,_}) ->
+ sort([filename:rootname(F) || F <- [A,B]])
+ end,
+ Files);
+
+sort([A,B] = L) ->
+ [DA,DB] = [dep([D],[]) || D <- L],
+ case {[A] -- DB, [B] -- DA} of
+ {[], [_]} -> %% B depends on A
+ true;
+ {[_], []} -> %% A depends on B
+ false;
+ {[_],[_]} -> %% or not
+ length(DA) < length(DB)
+ end.
+
+%% Recursively accumulate inherited dictionaries.
+dep([D|Rest], Acc) ->
+ dep(dep(D), Rest, Acc);
+dep([], Acc) ->
+ Acc.
+
+dep([{Dict, _} | T], Rest, Acc) ->
+ dep(T, [Dict | Rest], [Dict | Acc]);
+dep([], Rest, Acc) ->
+ dep(Rest, Acc).
+
+make(Path, Dict0)
+ when is_atom(Dict0) ->
+ make(Path, atom_to_list(Dict0));
+
+make(Path, Dict0) ->
+ Dict = filename:rootname(filename:basename(Path)),
+ {Mod, Pre} = make_name(Dict),
+ {"diameter_gen_base" ++ Suf = Mod0, _} = make_name(Dict0),
+ Name = Mod ++ Suf,
+ try
+ ok = to_erl(Path, [{name, Name},
+ {prefix, Pre},
+ {inherits, "rfc3588_base/" ++ Mod0}
+ | [{inherits, D ++ "/" ++ M ++ Suf}
+ || {D,M} <- dep(Dict)]]),
+ ok = to_beam(Name)
+ catch
+ throw: {_,_} = E ->
+ E
+ end.
+
+to_erl(File, Opts) ->
+ case diameter_make:codec(File, Opts) of
+ ok ->
+ ok;
+ No ->
+ throw({make, No})
+ end.
+
+to_beam(Name) ->
+ case compile:file(Name ++ ".erl", [return]) of
+ {ok, _, _} ->
+ ok;
+ No ->
+ throw({compile, No})
+ end.
+
+dep(Dict) ->
+ case lists:keyfind(list_to_atom(Dict), 1, ?INHERITS) of
+ {_, Is} ->
+ lists:map(fun inherits/1, Is);
+ false ->
+ []
+ end.
+
+inherits(Dict)
+ when is_atom(Dict) ->
+ inherits(atom_to_list(Dict));
+
+inherits(Dict) ->
+ {Name, _} = make_name(Dict),
+ {Dict, Name}.
+
+make_name(Dict) ->
+ {R, [$_|N]} = lists:splitwith(fun(C) -> C /= $_ end, Dict),
+ {string:join(["diameter_gen", N, R], "_"), "diameter_" ++ N}.
+
+%% ===========================================================================
+%% code/1
+%%
+%% Compile example code under examples/code.
+
+code(Config) ->
+ Node = slave(hd(?NODES), here()),
+ [] = rpc:call(Node,
+ ?MODULE,
+ install,
+ [proplists:get_value(priv_dir, Config)]).
+
+%% Compile on another node since the code path may be modified.
+install(PrivDir) ->
+ Top = install(here(), PrivDir),
+ 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])]].
+
+%% Copy include files into a temporary directory and adjust the code
+%% path in order for example code to be able to include them with
+%% include_lib. This is really only required when running in the reop
+%% since generated includes, that the example code wants to
+%% include_lib, are under src/gen and there's no way to get get the
+%% 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 by slave/1 (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),
+ 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"]),
+ [] = [{T,E} || T <- [Tmp, TmpInc, TmpEbin],
+ {error, E} <- [file:make_dir(T)]],
+
+ Inc = filename:join([Top, "include"]),
+ Gen = filename:join([Top, "src", "gen"]),
+ Files = find_files([Inc, Gen], ".*\\.hrl"),
+ [] = [{F,E} || {_,F} <- Files,
+ 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.
+
+find_files(Dirs, RE) ->
+ lists:foldl(fun(D,A) -> fold_files(D, RE, A) end,
+ orddict:new(),
+ Dirs).
+
+fold_files(Dir, RE, Acc) ->
+ filelib:fold_files(Dir, RE, false, fun store/2, Acc).
+
+store(Path, Dict) ->
+ orddict:store(filename:basename(Path), Path, Dict).
+
+%% ===========================================================================
+
+%% enslave/1
+%%
+%% Start two nodes: one for the server, one for the client.
+
+enslave(Config) ->
+ Dir = here(),
+ Nodes = [{N, slave(N, Dir)} || N <- tl(?NODES)],
+ ?util:write_priv(Config, nodes, Nodes).
+
+slave(Name, Dir) ->
+ {ok, Node} = ct_slave:start(Name, ?TIMEOUTS),
+ ok = rpc:call(Node,
+ code,
+ add_pathsa,
+ [[Dir, filename:join([Dir, "..", "ebin"])]]),
+ Node.
+
+here() ->
+ filename:dirname(code:which(?MODULE)).
+
+top(Dir, LibDir) ->
+ File = filename:join([Dir, "depend.sed"]), %% only in the repo
+ case filelib:is_regular(File) of
+ true -> filename:join([Dir, ".."]);
+ false -> LibDir
+ end.
+
+%% start/1
+
+start(server) ->
+ ok = diameter:start(),
+ ok = server:start(),
+ {ok, Ref} = server:listen(tcp),
+ [_] = ?util:lport(tcp, Ref, 20),
+ ok;
+
+start(client) ->
+ ok = diameter:start(),
+ true = diameter:subscribe(client),
+ ok = client:start(),
+ {ok, Ref} = client:connect(tcp),
+ receive #diameter_event{info = {up, Ref, _, _, _}} -> ok end;
+
+start(Config) ->
+ Nodes = ?util:read_priv(Config, nodes),
+ [] = [RC || {T,N} <- Nodes,
+ RC <- [rpc:call(N, ?MODULE, start, [T])],
+ RC /= ok].
+
+%% traffic/1
+%%
+%% Send successful messages from client to server.
+
+traffic(server) ->
+ ok;
+
+traffic(client) ->
+ {_, MRef} = spawn_monitor(fun() -> call(100) end),
+ receive {'DOWN', MRef, process, _, Reason} -> Reason end;
+
+traffic(Config) ->
+ Nodes = ?util:read_priv(Config, nodes),
+ [] = [RC || {T,N} <- Nodes,
+ RC <- [rpc:call(N, ?MODULE, traffic, [T])],
+ RC /= ok].
+
+call(0) ->
+ exit(ok);
+
+call(N) ->
+ {ok, _} = client:call(),
+ call(N-1).
+
+%% stop/1
+
+stop(Name)
+ when is_atom(Name) ->
+ {ok, _Node} = ct_slave:stop(Name),
+ ok;
+
+stop(_Config) ->
+ [] = [RC || N <- ?NODES, RC <- [stop(N)], RC /= ok].
diff --git a/lib/diameter/test/modules.mk b/lib/diameter/test/modules.mk
index beff588a02..c123de6d0b 100644
--- a/lib/diameter/test/modules.mk
+++ b/lib/diameter/test/modules.mk
@@ -34,6 +34,7 @@ MODULES = \
diameter_distribution_SUITE \
diameter_dpr_SUITE \
diameter_event_SUITE \
+ diameter_examples_SUITE \
diameter_failover_SUITE \
diameter_gen_sctp_SUITE \
diameter_length_SUITE \