From 483aceacd063d0a9b787bf468e795617d52e0507 Mon Sep 17 00:00:00 2001
From: Anders Svensson
Date: Wed, 14 Jun 2017 16:53:01 +0200
Subject: Exercise example RFC 4005 dictionary in traffic suite
Only exercising the standard dictionaries has missed some problems in
the past.
---
lib/diameter/test/diameter_traffic_SUITE.erl | 269 ++++++++++++++++++++-------
1 file changed, 202 insertions(+), 67 deletions(-)
diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl
index 84b41f14b7..0a93033d83 100644
--- a/lib/diameter/test/diameter_traffic_SUITE.erl
+++ b/lib/diameter/test/diameter_traffic_SUITE.erl
@@ -35,7 +35,8 @@
end_per_testcase/2]).
%% testcases
--export([start/1,
+-export([rfc4005/1,
+ start/1,
start_services/1,
add_transports/1,
result_codes/1,
@@ -125,7 +126,7 @@
-define(L, atom_to_list).
%% Don't use is_record/2 since dictionary hrl's aren't included.
-%% (Since they define conflicting reqcords with the same names.)
+%% (Since they define conflicting records with the same names.)
-define(is_record(Rec, Name), (Name == element(1, Rec))).
-define(ADDR, {127,0,0,1}).
@@ -144,8 +145,8 @@
%% How to send answers, in a diameter_packet or not.
-define(CONTAINERS, [pkt, msg]).
-%% Which common dictionary to use in the clients.
--define(RFCS, [rfc3588, rfc6733]).
+%% 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.
@@ -165,7 +166,7 @@
strings,
client_service,
client_encoding,
- client_dict0,
+ client_dict,
client_sender,
server_service,
server_encoding,
@@ -198,8 +199,8 @@
{'Host-IP-Address', [?ADDR]},
{'Vendor-Id', 12345},
{'Product-Name', "OTP/diameter"},
- {'Auth-Application-Id', [?DIAMETER_APP_ID_COMMON]},
- {'Acct-Application-Id', [?DIAMETER_APP_ID_ACCOUNTING]},
+ {'Auth-Application-Id', [0]}, %% common messages
+ {'Acct-Application-Id', [3]}, %% base accounting
{restrict_connections, false},
{string_decode, Decode},
{incoming_maxlen, 1 bsl 21}
@@ -209,7 +210,9 @@
|| D <- [diameter_gen_base_rfc3588,
diameter_gen_base_accounting,
diameter_gen_base_rfc6733,
- diameter_gen_acct_rfc6733]]]).
+ diameter_gen_acct_rfc6733,
+ nas4005],
+ D /= nas4005 orelse have_nas()]]).
-define(SUCCESS,
?'DIAMETER_BASE_RESULT-CODE_SUCCESS').
@@ -254,7 +257,7 @@ suite() ->
[{timetrap, {seconds, 10}}].
all() ->
- [start, result_codes, {group, traffic}, empty, stop].
+ [rfc4005, start, result_codes, {group, traffic}, empty, stop].
groups() ->
[{P, [P], Ts} || Ts <- [tc(tc())], P <- [shuffle, parallel]]
@@ -300,9 +303,11 @@ tc(L) ->
%% --------------------
init_per_suite(Config) ->
- [{sctp, ?util:have_sctp()} | Config].
+ [{rfc4005, compile_and_load()}, {sctp, ?util:have_sctp()} | Config].
end_per_suite(_Config) ->
+ code:delete(nas4005),
+ code:purge(nas4005),
ok.
%% --------------------
@@ -322,13 +327,16 @@ init_per_group(sctp = Name, Config) ->
end;
init_per_group(Name, Config) ->
+ Nas = proplists:get_value(rfc4005, Config, false),
case ?util:name(Name) of
+ [_,_,D,_,_,_, _, _, _] when D == rfc4005, true /= Nas ->
+ {skip, rfc4005};
[T,R,D,A,C,S,SS,ST,CS] ->
G = #group{transport = T,
strings = S,
client_service = [$C|?util:unique_string()],
client_encoding = R,
- client_dict0 = dict0(D),
+ client_dict = appdict(D),
client_sender = CS,
server_service = [$S|?util:unique_string()],
server_encoding = A,
@@ -463,26 +471,45 @@ add_transports(Config) ->
| [{packet, hd(?util:scramble([false, raw]))}
|| T == sctp andalso CS]],
[{capabilities_cb, fun capx/2},
- {pool_size, 8},
- {applications, apps(rfc3588)}]
+ {pool_size, 8}
+ | server_apps()]
++ [{spawn_opt, {erlang, spawn, []}} || CS]),
Cs = [?util:connect(CN,
[T, {sender, CS}],
LRef,
- [{id, Id},
- {capabilities, [{'Origin-State-Id', origin(Id)}]},
- {applications, apps(D)}])
+ [{id, Id}
+ | client_apps(D, [{'Origin-State-Id', origin(Id)}])])
|| A <- ?ENCODINGS,
C <- ?CONTAINERS,
D <- ?RFCS,
+ D /= rfc4005 orelse have_nas(),
Id <- [{A,C}]],
%% The server uses the client's Origin-State-Id to decide how to
%% answer.
?util:write_priv(Config, "transport", [LRef | Cs]).
-apps(D0) ->
- D = dict0(D0),
- [acct(D), D].
+server_apps() ->
+ B = have_nas(),
+ [{applications, [diameter_gen_base_rfc3588,
+ diameter_gen_base_accounting]
+ ++ [nas4005 || B]},
+ {capabilities, [{'Auth-Application-Id', [0] ++ [1 || B]}, %% common, NAS
+ {'Acct-Application-Id', [3]}]}]. %% accounting
+
+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.
+
+have_nas() ->
+ false /= code:is_loaded(nas4005).
remove_transports(Config) ->
#group{client_service = CN,
@@ -515,6 +542,11 @@ capx(_, #diameter_caps{origin_host = {OH,DH}}) ->
%% ===========================================================================
+%% 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, 3001, 3002, 3003, 3004, 3007, 3008, 3009, 5001, 5011, 5014}
@@ -615,12 +647,10 @@ send_unknown_short(Config, M, RC) ->
data = <<17>>}]}],
['ASA', {'Session-Id', _}, {'Result-Code', RC} | Avps]
= call(Config, Req),
- [#'diameter_base_Failed-AVP'{'AVP' = As}]
- = proplists:get_value('Failed-AVP', Avps),
- [#diameter_avp{code = 999,
- is_mandatory = M,
- data = <<17, _/binary>>}] %% extra bits from padding
- = As.
+ [[#diameter_avp{code = 999,
+ is_mandatory = M,
+ data = <<17, _/binary>>}]] %% extra bits from padding
+ = failed_avps(Avps, Config).
%% Ditto but set the M flag.
send_unknown_mandatory(Config) ->
@@ -629,12 +659,10 @@ send_unknown_mandatory(Config) ->
data = <<17>>}]}],
['ASA', {'Session-Id', _}, {'Result-Code', ?AVP_UNSUPPORTED} | Avps]
= call(Config, Req),
- [#'diameter_base_Failed-AVP'{'AVP' = As}]
- = proplists:get_value('Failed-AVP', Avps),
- [#diameter_avp{code = 999,
- is_mandatory = true,
- data = <<17>>}]
- = As.
+ [[#diameter_avp{code = 999,
+ is_mandatory = true,
+ data = <<17>>}]]
+ = failed_avps(Avps, Config).
%% Ditto, and point the AVP length past the end of the message. Expect
%% 5014 instead of 5001.
@@ -649,13 +677,11 @@ send_unexpected_mandatory_decode(Config) ->
data = <<12:32>>}]}],
['ASA', {'Session-Id', _}, {'Result-Code', ?AVP_UNSUPPORTED} | Avps]
= call(Config, Req),
- [#'diameter_base_Failed-AVP'{'AVP' = As}]
- = proplists:get_value('Failed-AVP', Avps),
- [#diameter_avp{code = 27,
- is_mandatory = true,
- value = 12,
- data = <<12:32>>}]
- = As.
+ [[#diameter_avp{code = 27,
+ is_mandatory = true,
+ value = 12,
+ data = <<12:32>>}]]
+ = failed_avps(Avps, Config).
%% Send an containing a faulty Grouped AVP (empty Proxy-Host in
%% Proxy-Info) and expect that only the faulty AVP is sent in
@@ -667,13 +693,9 @@ send_grouped_error(Config) ->
{'Proxy-State', ""}]]}],
['ASA', {'Session-Id', _}, {'Result-Code', ?INVALID_AVP_LENGTH} | Avps]
= call(Config, Req),
- [#'diameter_base_Failed-AVP'{'AVP' = As}]
- = proplists:get_value('Failed-AVP', Avps),
- [#diameter_avp{name = 'Proxy-Info',
- value = #'diameter_base_Proxy-Info'
- {'Proxy-Host' = Empty,
- 'Proxy-State' = undefined}}]
- = As,
+ [[#diameter_avp{name = 'Proxy-Info', value = V}]]
+ = failed_avps(Avps, Config),
+ {Empty, undefined, []} = proxy_info(V, Config),
<<0>> = iolist_to_binary(Empty).
%% Send an STR that the server ignores.
@@ -729,10 +751,10 @@ send_invalid_avp_length(Config) ->
{'User-Name', _},
{'Class', _},
{'Error-Message', _},
- {'Error-Reporting-Host', _},
- {'Failed-AVP', [#'diameter_base_Failed-AVP'{'AVP' = [_]}]}
- | _]
- = call(Config, Req).
+ {'Error-Reporting-Host', _}
+ | Avps]
+ = call(Config, Req),
+ [[_]] = failed_avps(Avps, Config).
%% Send a request containing 5xxx errors that the server rejects with
%% 3xxx.
@@ -935,6 +957,29 @@ send_anything(Config) ->
%% ===========================================================================
+failed_avps(Avps, Config) ->
+ #group{client_dict = D} = proplists:get_value(group, Config),
+ [failed_avp(D, T) || T <- proplists:get_value('Failed-AVP', Avps)].
+
+failed_avp(nas4005, {'nas_Failed-AVP', As}) ->
+ As;
+failed_avp(_, #'diameter_base_Failed-AVP'{'AVP' = As}) ->
+ As.
+
+proxy_info(Rec, Config) ->
+ #group{client_dict = D} = proplists:get_value(group, Config),
+ if D == nas4005 ->
+ {'nas_Proxy-Info', H, S, As}
+ = Rec,
+ {H,S,As};
+ true ->
+ #'diameter_base_Proxy-Info'{'Proxy-Host' = H,
+ 'Proxy-State' = S,
+ 'AVP' = As}
+ = Rec,
+ {H,S,As}
+ end.
+
group(Config) ->
#group{} = proplists:get_value(group, Config).
@@ -956,7 +1001,7 @@ call(Config, Req, Opts) ->
Name = proplists:get_value(testcase, Config),
#group{client_service = CN,
client_encoding = ReqEncoding,
- client_dict0 = Dict0}
+ client_dict = Dict0}
= Group
= group(Config),
diameter:call(CN,
@@ -996,9 +1041,21 @@ msg([H|T], record, Dict) ->
msg(Msg, _, _) ->
Msg.
+appdict(rfc4005) ->
+ nas4005;
+appdict(D) ->
+ dict0(D).
+
dict0(D) ->
?A("diameter_gen_base_" ++ ?L(D)).
+dict(Msg, nas4005 = D) ->
+ if 'answer-message' == hd(Msg);
+ ?is_record(Msg, 'diameter_base_answer-message') ->
+ diameter_gen_base_rfc3588;
+ true ->
+ D
+ end;
dict(Msg, Dict0)
when 'ACR' == hd(Msg);
'ACA' == hd(Msg);
@@ -1016,7 +1073,7 @@ acct(diameter_gen_base_rfc6733) ->
%% Set only values that aren't already.
set(_, [H|T], Vs) ->
[H | Vs ++ T];
-set(#group{client_dict0 = Dict0} = _Group, Rec, Vs) ->
+set(#group{client_dict = Dict0} = _Group, Rec, Vs) ->
Dict = dict(Rec, Dict0),
lists:foldl(fun({F,_} = FV, A) ->
set(Dict, Dict:'#get-'(F, A), FV, A)
@@ -1086,7 +1143,7 @@ log(#diameter_packet{bin = Bin} = P, T)
%% prepare/4
-prepare(Pkt, Caps, N, #group{client_dict0 = Dict0} = Group)
+prepare(Pkt, Caps, N, #group{client_dict = Dict0} = Group)
when N == send_unknown_short_mandatory;
N == send_unknown_short ->
Req = prepare(Pkt, Caps, Group),
@@ -1106,7 +1163,7 @@ prepare(Pkt, Caps, N, #group{client_dict0 = Dict0} = Group)
<> = Bin,
E#diameter_packet{bin = <>};
-prepare(Pkt, Caps, N, #group{client_dict0 = Dict0} = Group)
+prepare(Pkt, Caps, N, #group{client_dict = Dict0} = Group)
when N == send_long_avp_length;
N == send_short_avp_length;
N == send_zero_avp_length ->
@@ -1132,7 +1189,7 @@ prepare(Pkt, Caps, N, #group{client_dict0 = Dict0} = Group)
T/binary,
Hdr/binary, AL:24, Data/binary>>};
-prepare(Pkt, Caps, N, #group{client_dict0 = Dict0} = Group)
+prepare(Pkt, Caps, N, #group{client_dict = Dict0} = Group)
when N == send_invalid_avp_length;
N == send_invalid_reject ->
Req = prepare(Pkt, Caps, Group),
@@ -1147,7 +1204,7 @@ prepare(Pkt, Caps, N, #group{client_dict0 = Dict0} = Group)
<> = H0, %% assert
E#diameter_packet{bin = <>};
-prepare(Pkt, Caps, send_unexpected_mandatory, #group{client_dict0 = Dict0}
+prepare(Pkt, Caps, send_unexpected_mandatory, #group{client_dict = Dict0}
= Group) ->
Req = prepare(Pkt, Caps, Group),
#diameter_packet{bin = <>}
@@ -1157,7 +1214,7 @@ prepare(Pkt, Caps, send_unexpected_mandatory, #group{client_dict0 = Dict0}
Avp = <>,
E#diameter_packet{bin = <>};
-prepare(Pkt, Caps, send_grouped_error, #group{client_dict0 = Dict0}
+prepare(Pkt, Caps, send_grouped_error, #group{client_dict = Dict0}
= Group) ->
Req = prepare(Pkt, Caps, Group),
#diameter_packet{bin = Bin}
@@ -1189,14 +1246,14 @@ prepare(Pkt, Caps, send_grouped_error, #group{client_dict0 = Dict0}
Payload/binary,
T/binary>>};
-prepare(Pkt, Caps, send_unsupported, #group{client_dict0 = Dict0} = Group) ->
+prepare(Pkt, Caps, send_unsupported, #group{client_dict = Dict0} = Group) ->
Req = prepare(Pkt, Caps, Group),
#diameter_packet{bin = <>}
= E
= diameter_codec:encode(Dict0, Pkt#diameter_packet{msg = Req}),
E#diameter_packet{bin = <>};
-prepare(Pkt, Caps, send_unsupported_app, #group{client_dict0 = Dict0}
+prepare(Pkt, Caps, send_unsupported_app, #group{client_dict = Dict0}
= Group) ->
Req = prepare(Pkt, Caps, Group),
#diameter_packet{bin = <>}
@@ -1225,6 +1282,7 @@ prepare(Pkt, Caps, _Name, Group) ->
prepare(#diameter_packet{msg = Req}, Caps, Group)
when ?is_record(Req, diameter_base_accounting_ACR);
+ ?is_record(Req, nas_ACR);
'ACR' == hd(Req) ->
#diameter_caps{origin_host = {OH, _},
origin_realm = {OR, DR}}
@@ -1237,6 +1295,7 @@ prepare(#diameter_packet{msg = Req}, Caps, Group)
prepare(#diameter_packet{msg = Req}, Caps, Group)
when ?is_record(Req, diameter_base_ASR);
+ ?is_record(Req, nas_ASR);
'ASR' == hd(Req) ->
#diameter_caps{origin_host = {OH, DH},
origin_realm = {OR, DR}}
@@ -1250,6 +1309,7 @@ prepare(#diameter_packet{msg = Req}, Caps, Group)
prepare(#diameter_packet{msg = Req}, Caps, Group)
when ?is_record(Req, diameter_base_STR);
+ ?is_record(Req, nas_STR);
'STR' == hd(Req) ->
#diameter_caps{origin_host = {OH, _},
origin_realm = {OR, DR}}
@@ -1262,6 +1322,7 @@ prepare(#diameter_packet{msg = Req}, Caps, Group)
prepare(#diameter_packet{msg = Req}, Caps, Group)
when ?is_record(Req, diameter_base_RAR);
+ ?is_record(Req, nas_RAR);
'RAR' == hd(Req) ->
#diameter_caps{origin_host = {OH, DH},
origin_realm = {OR, DR}}
@@ -1287,7 +1348,7 @@ handle_answer(Pkt, Req, [$C|_], Peer, {send_detach = Name, Group}, _, X) ->
{Pid, Ref} = X,
Pid ! {Ref, answer(Pkt, Req, Peer, Name, Group)}.
-answer(Pkt, Req, _Peer, Name, #group{client_dict0 = Dict0}) ->
+answer(Pkt, Req, _Peer, Name, #group{client_dict = Dict0}) ->
#diameter_packet{header = H, msg = Ans, errors = Es} = Pkt,
ApplId = app(Req, Name, Dict0),
#diameter_header{application_id = ApplId} = H, %% assert
@@ -1343,20 +1404,68 @@ handle_request(#diameter_packet{header = H, msg = M, avps = As},
V = EI bsr B, %% assert
V = HI bsr B, %%
#diameter_caps{origin_state_id = {_,[Id]}} = Caps,
- answer(origin(Id), request(M, [H|As], Caps)).
+ wrap(origin(Id), H, request(nas_to_base(M, H), [H|As], Caps)).
-answer(T, {Tag, Action, Post}) ->
- {Tag, answer(T, Action), Post};
-answer(_, {reply, [#diameter_header{} | _]} = T) ->
+wrap(T, H, {Tag, Action, Post}) ->
+ {Tag, wrap(T, H, Action), Post};
+wrap(_, _, {reply, [#diameter_header{} | _]} = T) ->
T;
-answer({A,C}, {reply, Ans}) ->
- answer(C, {reply, msg(Ans, A, diameter_gen_base_rfc3588)});
-answer(pkt, {reply, Ans})
+wrap({A,C}, H, {reply, Ans}) ->
+ Msg = msg(Ans, A, diameter_gen_base_rfc3588),
+ wrap(C, H, {reply, base_to_nas(Msg, H)});
+wrap(pkt, _, {reply, Ans})
when not is_record(Ans, diameter_packet) ->
{reply, #diameter_packet{msg = Ans}};
-answer(_, T) ->
+wrap(_, _, T) ->
T.
+%% nas_to_base/1
+%%
+%% Map an RFC 4005 message to RFC 3588, to return the same answer in
+%% both cases.
+
+nas_to_base(Rec, #diameter_header{application_id = 1}) ->
+ [R | Values] = nas4005:'#get-'(Rec),
+ "nas_" ++ Name = ?L(R),
+ {D, RN} = case Name of
+ "ACR" ->
+ {diameter_gen_base_accounting,
+ diameter_base_accounting_ACR};
+ _ ->
+ {diameter_gen_base_rfc3588,
+ ?A("diameter_base_" ++ Name)}
+ end,
+ Fs = D:'#info-'(RN),
+ D:'#new-'([RN | [T || {F,_} = T <- Values, lists:member(F, Fs)]]);
+
+nas_to_base(Rec, _) ->
+ Rec.
+
+%% base_to_nas/2
+
+base_to_nas(#diameter_packet{msg = Msg} = Pkt, H) ->
+ Pkt#diameter_packet{msg = base_to_nas(Msg, H)};
+
+base_to_nas(Rec, #diameter_header{application_id = 1})
+ when is_tuple(Rec), not ?is_record(Rec, 'diameter_base_answer-message') ->
+ D = case element(1, Rec) of
+ diameter_base_accounting_ACA ->
+ diameter_gen_base_accounting;
+ _ ->
+ diameter_gen_base_rfc3588
+ end,
+ [R | Values] = D:'#get-'(Rec),
+ "diameter_base_" ++ N = ?L(R),
+ Name = ?A("nas_" ++ if N == "accounting_ACA" ->
+ "ACA";
+ true ->
+ N
+ end),
+ nas4005:'#new-'([Name | Values]);
+
+base_to_nas(Msg, _) ->
+ Msg.
+
%% request/3
%% send_experimental_result
@@ -1523,3 +1632,29 @@ message(ack, <<_:32, 1, _/bits>>, _) ->
%% sent answer or discarded request
message(ack, _, N) ->
[0 =< N, fun ?MODULE:message/3, N+1].
+
+%% ------------------------------------------------------------------------
+
+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 ->
+ {E, R, erlang:get_stacktrace()}
+ end.
+
+here() ->
+ filename:dirname(code:which(?MODULE)).
--
cgit v1.2.3
From c63f31deeff7eea054ff3b84b73c1b5b03d5aec6 Mon Sep 17 00:00:00 2001
From: Anders Svensson
Date: Wed, 26 Jul 2017 14:17:37 +0200
Subject: Fix message_cb in traffic suite
Matched a byte instead of a bit, and increment/decrement wasn't
symmetric. Allow more requests since some requests timeout.
Bungled in commit 09089872.
---
lib/diameter/test/diameter_traffic_SUITE.erl | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl
index 0a93033d83..dd0dfc776d 100644
--- a/lib/diameter/test/diameter_traffic_SUITE.erl
+++ b/lib/diameter/test/diameter_traffic_SUITE.erl
@@ -467,7 +467,7 @@ add_transports(Config) ->
LRef = ?util:listen(SN,
[T,
{sender, SS},
- {message_cb, ST andalso {?MODULE, message, [4]}}
+ {message_cb, ST andalso {?MODULE, message, [0]}}
| [{packet, hd(?util:scramble([false, raw]))}
|| T == sctp andalso CS]],
[{capabilities_cb, fun capx/2},
@@ -1614,8 +1614,8 @@ message(Dir, #diameter_packet{bin = Bin}, N) ->
message(Dir, Bin, N);
%% incoming request
-message(recv, <<_:32, 1, _/bits>> = Bin, N) ->
- [Bin, 1 < N, fun ?MODULE:message/3, N-1];
+message(recv, <<_:32, 1:1, _/bits>> = Bin, N) ->
+ [Bin, N < 16, fun ?MODULE:message/3, N+1];
%% incoming answer
message(recv, Bin, _) ->
@@ -1626,12 +1626,12 @@ message(send, Bin, _) ->
[Bin];
%% sent request
-message(ack, <<_:32, 1, _/bits>>, _) ->
+message(ack, <<_:32, 1:1, _/bits>>, _) ->
[];
%% sent answer or discarded request
message(ack, _, N) ->
- [0 =< N, fun ?MODULE:message/3, N+1].
+ [N =< 16, fun ?MODULE:message/3, N-1].
%% ------------------------------------------------------------------------
--
cgit v1.2.3
From b9f2d5a867806563c11f8b13e7977f8d03b64a54 Mon Sep 17 00:00:00 2001
From: Anders Svensson
Date: Mon, 3 Jul 2017 11:49:23 +0200
Subject: Fix obsolete diameter_gen.hrl comments
Most of the contents were moved to module diameter_gen in commit
205521d3.
---
lib/diameter/src/base/diameter_codec.erl | 2 +-
lib/diameter/src/compiler/diameter_codegen.erl | 17 ++++++++---------
2 files changed, 9 insertions(+), 10 deletions(-)
diff --git a/lib/diameter/src/base/diameter_codec.erl b/lib/diameter/src/base/diameter_codec.erl
index 82fa796e69..93c1b28f4c 100644
--- a/lib/diameter/src/base/diameter_codec.erl
+++ b/lib/diameter/src/base/diameter_codec.erl
@@ -29,7 +29,7 @@
msg_name/2,
msg_id/1]).
-%% Towards generated encoders (from diameter_gen.hrl).
+%% towards diameter_gen
-export([pack_data/2,
pack_avp/2]).
diff --git a/lib/diameter/src/compiler/diameter_codegen.erl b/lib/diameter/src/compiler/diameter_codegen.erl
index f56e4a5249..4e6fe32d69 100644
--- a/lib/diameter/src/compiler/diameter_codegen.erl
+++ b/lib/diameter/src/compiler/diameter_codegen.erl
@@ -21,15 +21,14 @@
-module(diameter_codegen).
%%
-%% This module generates erl/hrl files for encode/decode modules
-%% from the orddict parsed from a dictionary file (.dia) by
-%% diameter_dict_util. The generated code is simple (one-liners),
-%% the generated functions being called by code included iin the
-%% generated modules from diameter_gen.hrl. The orddict itself is
-%% returned by dict/0 in the generated module and diameter_dict_util
-%% calls this function when importing dictionaries as a consequence
-%% of @inherits sections. That is, @inherits introduces a dependency
-%% on the beam file of another dictionary.
+%% This module generates erl/hrl files for encode/decode modules from
+%% the orddict parsed from a dictionary file by diameter_dict_util.
+%% The generated code is simple (one-liners), and is called from
+%% diameter_gen. The orddict itself is returned by dict/0 in the
+%% generated module and diameter_dict_util calls this function when
+%% importing dictionaries as a consequence of @inherits sections. That
+%% is, @inherits introduces a dependency on the beam file of another
+%% dictionary.
%%
-export([from_dict/4,
--
cgit v1.2.3
From e30c38a44bbe2872e5b9b0ad46774c19b6af5292 Mon Sep 17 00:00:00 2001
From: Anders Svensson
Date: Mon, 3 Jul 2017 16:40:51 +0200
Subject: Count AVP arities during decode
Instead of after, during the check that AVPs have sufficient arity.
This makes the arity checks independent of the record decode, which
will allow the latter to be made optional.
---
lib/diameter/src/base/diameter_gen.erl | 246 ++++++++++++++++++---------------
1 file changed, 132 insertions(+), 114 deletions(-)
diff --git a/lib/diameter/src/base/diameter_gen.erl b/lib/diameter/src/base/diameter_gen.erl
index e832832876..6f11583868 100644
--- a/lib/diameter/src/base/diameter_gen.erl
+++ b/lib/diameter/src/base/diameter_gen.erl
@@ -172,14 +172,17 @@ enc_AVP(_Name, {_Dict, _AvpName, _Data} = T, Opts, _) ->
when Failed :: [{5000..5999, #diameter_avp{}}].
decode_avps(Name, Recs, #{module := Mod} = Opts) ->
- {Avps, {Rec, Failed}}
+ {Avps, {Rec, AM, Failed}}
= mapfoldl(fun(T,A) -> decode(Name, Opts, Mod, T, A) end,
- {newrec(Mod, Name), []},
+ {newrec(Mod, Name), #{}, []},
Recs),
- {Rec, Avps, Failed ++ missing(Rec, Name, Failed, Opts, Mod)}.
+ %% AM counts the number of top-level AVPs, which missing/4 then
+ %% uses when adding 5005 errors.
+ {Rec, Avps, Failed ++ missing(Name, Opts, Mod, AM)}.
+
%% Append 5005 errors so that errors are reported in the order
%% encountered. Failed-AVP should typically contain the first
-%% encountered error accordg to the RFC.
+%% error encountered.
%% mapfoldl/3
%%
@@ -194,6 +197,8 @@ mapfoldl(F, Acc0, [T|Rest], List) ->
mapfoldl(_, Acc, [], List) ->
{List, Acc}.
+%% missing/4
+
%% 3588:
%%
%% DIAMETER_MISSING_AVP 5005
@@ -204,57 +209,41 @@ mapfoldl(_, Acc, [], List) ->
%% Vendor-Id if applicable. The value field of the missing AVP
%% should be of correct minimum length and contain zeros.
-missing(Rec, Name, Failed, Opts, Mod) ->
- Avps = lists:foldl(fun({_, #diameter_avp{code = C, vendor_id = V}}, A) ->
- maps:put({C,V}, true, A)
- end,
- maps:new(),
- Failed),
- missing(Mod:avp_arity(Name), tl(tuple_to_list(Rec)), Avps, Opts, Mod, []).
-
-missing([{Name, Arity} | As], [Value | Vs], Avps, Opts, Mod, Acc) ->
- missing(As,
- Vs,
- Avps,
- Opts,
- Mod,
- case
- [H || missing_arity(Arity, Value),
- {C,_,V} = H <- [Mod:avp_header(Name)],
- not maps:is_key({C,V}, Avps)]
- of
- [H] ->
- [{5005, empty_avp(Name, H, Opts, Mod)} | Acc];
- [] ->
- Acc
- end);
-
-missing([], [], _, _, _, Acc) ->
- Acc.
-
-%% Maximum arities have already been checked in building the record.
-
-missing_arity(1, V) ->
- V == undefined;
-missing_arity({0, _}, _) ->
- false;
-missing_arity({1, _}, L) ->
- [] == L;
-missing_arity({Min, _}, L) ->
- not has_prefix(Min, L).
-
-%% Compare a non-negative integer and the length of a list without
-%% computing the length.
-has_prefix(0, _) ->
- true;
-has_prefix(_, []) ->
+missing(Name, Opts, Mod, AM) ->
+ lists:foldl(fun(T,A) -> missing(T, AM, Opts, Mod, A) end,
+ [],
+ Mod:avp_arity(Name)).
+
+%% missing/5
+
+missing({Name, Arity}, AM, Opts, Mod, Acc) ->
+ case missing(Name, Arity, AM) of
+ true -> [{5005, empty_avp(Name, Opts, Mod)} | Acc];
+ false -> Acc
+ end.
+
+%% missing/3
+
+missing(Name, Arity, AM) ->
+ 'AVP' /= Name andalso too_few(Name, Arity, AM).
+
+%% too_few/3
+%%
+%% Maximum arities have already been checked during the decode.
+
+too_few(_, {0, _}, _) ->
false;
-has_prefix(N, [_|L]) ->
- has_prefix(N-1, L).
-%% empty_avp/4
+too_few(FieldName, 1, AM) ->
+ not maps:is_key(FieldName, AM);
+
+too_few(FieldName, {M, _}, AM) ->
+ maps:get(FieldName, AM, 0) < M.
-empty_avp(Name, {Code, Flags, VId}, Opts, Mod) ->
+%% empty_avp/3
+
+empty_avp(Name, Opts, Mod) ->
+ {Code, Flags, VId} = Mod:avp_header(Name),
{Name, Type} = Mod:avp_name(Code, VId),
#diameter_avp{name = Name,
code = Code,
@@ -280,8 +269,27 @@ decode(Name,
Mod,
#diameter_avp{code = Code, vendor_id = Vid}
= Avp,
- Acc) ->
- decode(Name, Opts, Mod, Mod:avp_name(Code, Vid), Avp, Acc).
+ {Rec, AM, Failed}) ->
+ T = Mod:avp_name(Code, Vid),
+ decode(Name, Opts, Mod, T, Avp, {Rec, incr(field(T), AM), Failed}).
+
+%% field/1
+
+field({AvpName, _Type}) ->
+ AvpName;
+
+field('AVP' = A) ->
+ A.
+
+%% incr/2
+
+incr(Key, Map) ->
+ maps:update_with(Key, fun incr/1, 1, Map).
+
+%% incr/1
+
+incr(N) ->
+ N + 1.
%% decode/6
@@ -352,15 +360,13 @@ decode(Name, Opts0, Mod, {AvpName, Type}, Avp, Acc) ->
%% decode is packed into 'AVP'.
%% Reset the dictionary for best-effort decode of Failed-AVP.
- DecMod = if Failed ->
- AppMod;
- true ->
- Mod
+ DecMod = if Failed -> AppMod;
+ true -> Mod
end,
- %% On decode, a Grouped AVP is represented as a #diameter_avp{}
- %% list with AVP as head and component AVPs as tail. On encode,
- %% data can be a list of component AVPs.
+ %% A Grouped AVP is represented as a #diameter_avp{} list with AVP
+ %% as head and component AVPs as tail. On encode, data can be a
+ %% list of component AVPs.
try avp_decode(Data, AvpName, Opts, DecMod, Mod) of
{Rec, As} when Type == 'Grouped' ->
@@ -425,7 +431,7 @@ trim(Avp) ->
%% decode_error/7
-decode_error(Name, [_ | Rec], _, #{failed_avp := true} = Opts, Mod, Avp, Acc) ->
+decode_error(Name, [_|Rec], _, #{failed_avp := true} = Opts, Mod, Avp, Acc) ->
decode_AVP(Name, Avp#diameter_avp{value = Rec}, Opts, Mod, Acc);
decode_error(Name, _, _, #{failed_avp := true} = Opts, Mod, Avp, Acc) ->
@@ -437,24 +443,25 @@ decode_error(_, [Error | _], ComponentAvps, _, _, Avp, Acc) ->
decode_error(_, Error, ComponentAvps, _, _, Avp, Acc) ->
decode_error(Error, Avp, Acc, ComponentAvps).
-%% decode_error/5
+%% decode_error/6
decode_error(Name, _Reason, #{failed_avp := true} = Opts, Mod, Avp, Acc) ->
decode_AVP(Name, Avp, Opts, Mod, Acc);
-decode_error(Name, Reason, Opts, Mod, Avp, {Rec, Failed}) ->
+decode_error(Name, Reason, Opts, Mod, Avp, {Rec, AM, Failed}) ->
Stack = diameter_lib:get_stacktrace(),
+ AvpName = Avp#diameter_avp.name,
diameter_lib:log(decode_error,
?MODULE,
?LINE,
- {Reason, Name, Avp#diameter_avp.name, Mod, Stack}),
- {Avp, {Rec, [rc(Reason, Avp, Opts, Mod) | Failed]}}.
+ {Reason, Name, AvpName, Mod, Stack}),
+ {Avp, {Rec, AM, [rc(Reason, Avp, Opts, Mod) | Failed]}}.
%% decode_error/4
-decode_error({RC, ErrorData}, Avp, {Rec, Failed}, ComponentAvps) ->
+decode_error({RC, ErrorData}, Avp, {Rec, AM, Failed}, ComponentAvps) ->
E = Avp#diameter_avp{data = [ErrorData]},
- {[Avp | trim(ComponentAvps)], {Rec, [{RC, E} | Failed]}}.
+ {[Avp | trim(ComponentAvps)], {Rec, AM, [{RC, E} | Failed]}}.
%% set_strict/3
@@ -490,8 +497,8 @@ decode_AVP(Name, Avp, Opts, Mod, Acc) ->
%% DIAMETER_INVALID_AVP_LENGTH (5014). A module specified to a
%% @custom_types tag in a dictionary file can also raise an error of
%% this form.
-rc({'DIAMETER', 5014 = RC, _}, #diameter_avp{name = AvpName} = Avp, Opts, Mod) ->
- {RC, Avp#diameter_avp{data = Mod:empty_value(AvpName, Opts)}};
+rc({'DIAMETER', 5014 = RC, _}, #diameter_avp{name = AvpName} = A, Opts, Mod) ->
+ {RC, A#diameter_avp{data = Mod:empty_value(AvpName, Opts)}};
%% 3588:
%%
@@ -531,20 +538,33 @@ pack_avp(_, Arity, #diameter_avp{name = AvpName} = Avp, _Opts, Mod, Acc) ->
%% type.
pack_AVP(_, #diameter_avp{data = {5014 = RC, Data}} = Avp, _, _, Acc) ->
- {Rec, Failed} = Acc,
- {Rec, [{RC, Avp#diameter_avp{data = Data}} | Failed]};
+ {Rec, AM, Failed} = Acc,
+ {Rec, AM, [{RC, Avp#diameter_avp{data = Data}} | Failed]};
pack_AVP(Name, Avp, Opts, Mod, Acc) ->
- pack_arity(Name, pack_arity(Name, Opts, Mod, Avp), Avp, Mod, Acc).
-
-%% pack_arity/5
+ Arity = pack_arity(Name, Opts, Mod, Avp),
+ if 0 == Arity ->
+ M = Avp#diameter_avp.is_mandatory,
+ {Rec, AM, Failed} = Acc,
+ {Rec, AM, [{if M -> 5001; true -> 5008 end, Avp} | Failed]};
+ true ->
+ pack(Arity, 'AVP', Avp, Mod, Acc)
+ end.
-pack_arity(_, 0, #diameter_avp{is_mandatory = M} = Avp, _, Acc) ->
- {Rec, Failed} = Acc,
- {Rec, [{if M -> 5001; true -> 5008 end, Avp} | Failed]};
+%% 3588:
+%%
+%% DIAMETER_AVP_UNSUPPORTED 5001
+%% The peer received a message that contained an AVP that is not
+%% recognized or supported and was marked with the Mandatory bit. A
+%% Diameter message with this error MUST contain one or more Failed-
+%% AVP AVP containing the AVPs that caused the failure.
+%%
+%% DIAMETER_AVP_NOT_ALLOWED 5008
+%% A message was received with an AVP that MUST NOT be present. The
+%% Failed-AVP AVP MUST be included and contain a copy of the
+%% offending AVP.
-pack_arity(_, Arity, Avp, Mod, Acc) ->
- pack(Arity, 'AVP', Avp, Mod, Acc).
+%% pack_arity/4
%% Give Failed-AVP special treatment since (1) it'll contain any
%% unrecognized mandatory AVP's and (2) the RFC 3588 grammar failed to
@@ -573,31 +593,13 @@ pack_arity(Name,
0
end.
-%% 3588:
-%%
-%% DIAMETER_AVP_UNSUPPORTED 5001
-%% The peer received a message that contained an AVP that is not
-%% recognized or supported and was marked with the Mandatory bit. A
-%% Diameter message with this error MUST contain one or more Failed-
-%% AVP AVP containing the AVPs that caused the failure.
-%%
-%% DIAMETER_AVP_NOT_ALLOWED 5008
-%% A message was received with an AVP that MUST NOT be present. The
-%% Failed-AVP AVP MUST be included and contain a copy of the
-%% offending AVP.
-
%% pack/5
-pack(Arity, FieldName, Avp, Mod, {Rec, _} = Acc) ->
- pack(Mod:'#get-'(FieldName, Rec), Arity, FieldName, Avp, Mod, Acc).
-
-%% pack/6
-
-pack(undefined, 1, 'AVP' = F, Avp, Mod, {Rec, Failed}) -> %% unlikely
- {Mod:'#set-'({F, Avp}, Rec), Failed};
-
-pack(undefined, 1, F, #diameter_avp{value = V}, Mod, {Rec, Failed}) ->
- {Mod:'#set-'({F, V}, Rec), Failed};
+pack(Arity, F, Avp, Mod, {Rec, AM, Failed}) ->
+ case too_many(F, Arity, AM) of
+ true -> {Rec, AM, [{5009, Avp} | Failed]};
+ false -> {set(Arity, F, value(F, Avp), Mod, Rec), AM, Failed}
+ end.
%% 3588:
%%
@@ -608,18 +610,34 @@ pack(undefined, 1, F, #diameter_avp{value = V}, Mod, {Rec, Failed}) ->
%% the offending AVP that exceeded the maximum number of occurrences
%%
-pack(_, 1, _, Avp, _, {Rec, Failed}) ->
- {Rec, [{5009, Avp} | Failed]};
+%% too_many/3
-pack(L, {_, Max}, F, Avp, Mod, {Rec, Failed}) ->
- case '*' /= Max andalso has_prefix(Max+1, L) of
- true ->
- {Rec, [{5009, Avp} | Failed]};
- false when F == 'AVP' ->
- {Mod:'#set-'({F, [Avp | L]}, Rec), Failed};
- false ->
- {Mod:'#set-'({F, [Avp#diameter_avp.value | L]}, Rec), Failed}
- end.
+too_many(_, {_, '*'}, _) ->
+ false;
+
+too_many(FieldName, {_, M}, Map) ->
+ too_many(FieldName, M, Map);
+
+too_many(FieldName, M, Map) ->
+ #{FieldName := N} = Map,
+ M < N.
+
+%% set/5
+
+set(1, F, Value, Mod, Rec) ->
+ Mod:'#set-'({F, Value}, Rec);
+
+set(_, F, V, Mod, Rec) ->
+ Vs = Mod:'#get-'(F, Rec),
+ Mod:'#set-'({F, [V|Vs]}, Rec).
+
+%% value/2
+
+value('AVP', Avp) ->
+ Avp;
+
+value(_, #diameter_avp{value = V}) ->
+ V.
%% ---------------------------------------------------------------------------
%% # grouped_avp/3
--
cgit v1.2.3
From 722fa41564381dff0b7aa2b465193db30bb2f02f Mon Sep 17 00:00:00 2001
From: Anders Svensson
Date: Thu, 6 Jul 2017 09:58:07 +0200
Subject: Add service_opt() record_decode
To control whether or not messages and grouped AVPs are decoded to
records, in #diameter_packet.msg and #diameter_avp.value respectively.
The decode became unnecessary for diameter's needs in parent commit,
which decoupled it from the checking of AVP arities.
---
lib/diameter/doc/src/diameter.xml | 23 ++++++++++++++++++++++
lib/diameter/src/base/diameter.erl | 1 +
lib/diameter/src/base/diameter_codec.erl | 3 ++-
lib/diameter/src/base/diameter_config.erl | 3 +++
lib/diameter/src/base/diameter_gen.erl | 15 +++++++++++++-
lib/diameter/src/base/diameter_peer_fsm.erl | 9 ++++++---
lib/diameter/src/base/diameter_service.erl | 1 +
lib/diameter/src/base/diameter_traffic.erl | 9 ++++++---
lib/diameter/src/base/diameter_watchdog.erl | 9 ++++++---
lib/diameter/test/diameter_codec_SUITE.erl | 1 +
.../diameter_test_unknown.erl | 1 +
lib/diameter/test/diameter_codec_test.erl | 3 ++-
12 files changed, 66 insertions(+), 12 deletions(-)
diff --git a/lib/diameter/doc/src/diameter.xml b/lib/diameter/doc/src/diameter.xml
index 2cbe48ecce..663c9cc785 100644
--- a/lib/diameter/doc/src/diameter.xml
+++ b/lib/diameter/doc/src/diameter.xml
@@ -969,6 +969,29 @@ occur in the message in question.
+
+{record_decode, boolean()}
+-
+
+Whether or not to decode message and grouped AVPs to records in the
+msg field of diameter_packet records and value field of
+diameter_avp records respectively.
+If false then the fields are set to the same value.
+
+
+Defaults to true.
+
+
+
+Disabling the record is useful for applications in which the records
+aren't used/needed.
+AVP values are available in the avps field of
+diameter_packet records regardless of whether or not there is a record
+decode.
+
+
+
+
{string_decode, boolean()}
-
diff --git a/lib/diameter/src/base/diameter.erl b/lib/diameter/src/base/diameter.erl
index bd92e16fba..f411656e90 100644
--- a/lib/diameter/src/base/diameter.erl
+++ b/lib/diameter/src/base/diameter.erl
@@ -338,6 +338,7 @@ call(SvcName, App, Message) ->
| {restrict_connections, restriction()}
| {sequence, sequence() | evaluable()}
| {share_peers, remotes()}
+ | {record_decode, boolean()}
| {string_decode, boolean()}
| {strict_mbit, boolean()}
| {incoming_maxlen, message_length()}
diff --git a/lib/diameter/src/base/diameter_codec.erl b/lib/diameter/src/base/diameter_codec.erl
index 93c1b28f4c..5e4c6e6d8f 100644
--- a/lib/diameter/src/base/diameter_codec.erl
+++ b/lib/diameter/src/base/diameter_codec.erl
@@ -287,7 +287,8 @@ rec2msg(Mod, Rec) ->
%% longer *the* decode.
decode(Mod, Pkt) ->
- Opts = #{string_decode => true,
+ Opts = #{record_decode => true,
+ string_decode => true,
strict_mbit => true,
rfc => 6733},
decode(Mod, Opts, Pkt).
diff --git a/lib/diameter/src/base/diameter_config.erl b/lib/diameter/src/base/diameter_config.erl
index 34018ae6d3..46a3e362ac 100644
--- a/lib/diameter/src/base/diameter_config.erl
+++ b/lib/diameter/src/base/diameter_config.erl
@@ -713,6 +713,7 @@ make_config(SvcName, Opts) ->
{nodes, restrict_connections},
{16#FFFFFF, incoming_maxlen},
{true, strict_mbit},
+ {true, record_decode},
{true, string_decode},
{[], spawn_opt}]),
@@ -756,6 +757,7 @@ opt(K, false = B)
K == monitor;
K == restrict_connections;
K == strict_mbit;
+ K == record_decode;
K == string_decode ->
B;
@@ -763,6 +765,7 @@ opt(K, true = B)
when K == share_peers;
K == use_shared_peers;
K == strict_mbit;
+ K == record_decode;
K == string_decode ->
B;
diff --git a/lib/diameter/src/base/diameter_gen.erl b/lib/diameter/src/base/diameter_gen.erl
index 6f11583868..4879ad8f6c 100644
--- a/lib/diameter/src/base/diameter_gen.erl
+++ b/lib/diameter/src/base/diameter_gen.erl
@@ -174,7 +174,7 @@ enc_AVP(_Name, {_Dict, _AvpName, _Data} = T, Opts, _) ->
decode_avps(Name, Recs, #{module := Mod} = Opts) ->
{Avps, {Rec, AM, Failed}}
= mapfoldl(fun(T,A) -> decode(Name, Opts, Mod, T, A) end,
- {newrec(Mod, Name), #{}, []},
+ {newrec(Mod, Name, Opts), #{}, []},
Recs),
%% AM counts the number of top-level AVPs, which missing/4 then
%% uses when adding 5005 errors.
@@ -624,6 +624,9 @@ too_many(FieldName, M, Map) ->
%% set/5
+set(_, _, _, _, undefined = No) ->
+ No;
+
set(1, F, Value, Mod, Rec) ->
Mod:'#set-'({F, Value}, Rec);
@@ -723,5 +726,15 @@ empty(Name, #{module := Mod} = Opts) ->
%% ------------------------------------------------------------------------------
+%% newrec/3
+
+newrec(_, _, #{record_decode := false}) ->
+ undefined;
+
+newrec(Mod, Name, _) ->
+ newrec(Mod, Name).
+
+%% newrec/2
+
newrec(Mod, Name) ->
Mod:'#new-'(Mod:name2rec(Name)).
diff --git a/lib/diameter/src/base/diameter_peer_fsm.erl b/lib/diameter/src/base/diameter_peer_fsm.erl
index 1b0dc417e5..f2fbb70270 100644
--- a/lib/diameter/src/base/diameter_peer_fsm.erl
+++ b/lib/diameter/src/base/diameter_peer_fsm.erl
@@ -128,7 +128,8 @@
%% outgoing DPR; boolean says whether or not
%% the request was sent explicitly with
%% diameter:call/4.
- codec :: #{string_decode := boolean(),
+ codec :: #{record_decode := true,
+ string_decode := boolean(),
strict_mbit := boolean(),
rfc := 3588 | 6733,
ordered_encode := false},
@@ -253,11 +254,13 @@ i({Ack, WPid, {M, Ref} = T, Opts, {SvcOpts, Nodes, Dict0, Svc}}) ->
length_errors = LengthErr,
strict = Strictness,
incoming_maxlen = Maxlen,
- codec = maps:with([string_decode,
+ codec = maps:with([record_decode,
+ string_decode,
strict_mbit,
rfc,
ordered_encode],
- SvcOpts#{ordered_encode => false})}.
+ SvcOpts#{ordered_encode => false,
+ record_decode => true})}.
%% The transport returns its local ip addresses so that different
%% transports on the same service can use different local addresses.
%% The local addresses are put into Host-IP-Address avps here when
diff --git a/lib/diameter/src/base/diameter_service.erl b/lib/diameter/src/base/diameter_service.erl
index a976a8b998..6dc4889c82 100644
--- a/lib/diameter/src/base/diameter_service.erl
+++ b/lib/diameter/src/base/diameter_service.erl
@@ -113,6 +113,7 @@
restrict_connections := diameter:restriction(),
incoming_maxlen := diameter:message_length(),
strict_mbit := boolean(),
+ record_decode := boolean(),
string_decode := boolean(),
spawn_opt := list() | {module(), atom(), list()}}}).
diff --git a/lib/diameter/src/base/diameter_traffic.erl b/lib/diameter/src/base/diameter_traffic.erl
index 85378babea..228d9802ad 100644
--- a/lib/diameter/src/base/diameter_traffic.erl
+++ b/lib/diameter/src/base/diameter_traffic.erl
@@ -76,7 +76,8 @@
service_name :: diameter:service_name(),
apps :: [#diameter_app{}],
sequence :: diameter:sequence(),
- codec :: #{string_decode := boolean(),
+ codec :: #{record_decode := boolean(),
+ string_decode := boolean(),
strict_mbit := boolean(),
incoming_maxlen := diameter:message_length()}}).
%% Note that incoming_maxlen is currently handled in diameter_peer_fsm,
@@ -102,7 +103,8 @@ make_recvdata([SvcName, PeerT, Apps, SvcOpts | _]) ->
peerT = PeerT,
apps = Apps,
sequence = Mask,
- codec = maps:with([string_decode,
+ codec = maps:with([record_decode,
+ string_decode,
strict_mbit,
ordered_encode,
incoming_maxlen],
@@ -1933,7 +1935,8 @@ choose(false, _, X) -> X.
%% Decode options sufficient for AVP extraction.
decode_opts(Dict) ->
- #{string_decode => false,
+ #{record_decode => true,
+ string_decode => false,
strict_mbit => false,
failed_avp => false,
dictionary => Dict}.
diff --git a/lib/diameter/src/base/diameter_watchdog.erl b/lib/diameter/src/base/diameter_watchdog.erl
index a63425d92a..c3dc8c3bf0 100644
--- a/lib/diameter/src/base/diameter_watchdog.erl
+++ b/lib/diameter/src/base/diameter_watchdog.erl
@@ -72,7 +72,8 @@
restrict := boolean(),
suspect := non_neg_integer(), %% OKAY -> SUSPECT
okay := non_neg_integer()}, %% REOPEN -> OKAY
- codec :: #{string_decode := false,
+ codec :: #{record_decode := false,
+ string_decode := false,
strict_mbit := boolean(),
failed_avp := false,
rfc := 3588 | 6733,
@@ -135,7 +136,8 @@ i({Ack, T, Pid, {Opts,
putr(restart, {T, Opts, Svc, SvcOpts}), %% save seeing it in trace
putr(dwr, dwr(Caps)), %%
Nodes = restrict_nodes(Restrict),
- CodecKeys = [string_decode,
+ CodecKeys = [record_decode,
+ string_decode,
strict_mbit,
incoming_maxlen,
spawn_opt,
@@ -155,7 +157,8 @@ i({Ack, T, Pid, {Opts,
suspect => 1,
okay => 3},
Opts)),
- codec = maps:with(CodecKeys, SvcOpts#{string_decode := false,
+ codec = maps:with(CodecKeys, SvcOpts#{record_decode := false,
+ string_decode := false,
ordered_encode => false})}.
wait(Ref, Pid) ->
diff --git a/lib/diameter/test/diameter_codec_SUITE.erl b/lib/diameter/test/diameter_codec_SUITE.erl
index 9f08f49f9f..31332537e9 100644
--- a/lib/diameter/test/diameter_codec_SUITE.erl
+++ b/lib/diameter/test/diameter_codec_SUITE.erl
@@ -292,6 +292,7 @@ recode(Msg, Dict) ->
opts(Mod) ->
#{dictionary => Mod,
+ record_decode => true,
string_decode => false,
strict_mbit => true,
rfc => 6733,
diff --git a/lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl b/lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl
index 700910878c..fe602c9ee5 100644
--- a/lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl
+++ b/lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl
@@ -78,6 +78,7 @@ dec('BR', #diameter_packet
opts(Mod) ->
#{dictionary => Mod,
+ record_decode => true,
string_decode => true,
strict_mbit => true,
rfc => 6733,
diff --git a/lib/diameter/test/diameter_codec_test.erl b/lib/diameter/test/diameter_codec_test.erl
index b548f85cb8..7595e7edfc 100644
--- a/lib/diameter/test/diameter_codec_test.erl
+++ b/lib/diameter/test/diameter_codec_test.erl
@@ -219,7 +219,8 @@ opts(Mod) ->
dictionary => Mod}.
opts() ->
- #{string_decode => true,
+ #{record_decode => true,
+ string_decode => true,
strict_mbit => true,
rfc => 6733,
failed_avp => false}.
--
cgit v1.2.3
From 1b3b64af3d9a5441b6da37cf4e97b59cb043f33b Mon Sep 17 00:00:00 2001
From: Anders Svensson
Date: Thu, 6 Jul 2017 11:02:31 +0200
Subject: Let messages and grouped AVPs be encoded/decoded from/to maps
With {record_decode, map}. The option name is arguably a bit misleading
now, but not too objectionable given that the encode/decode in question
has historically only been of records.
One advantage of the map decode is that the map only contains values for
those AVPs existing in the message or grouped AVP in question. The name
of the message or grouped AVP is stored in with key ':name', the leading
colon ensuring that the key isn't a diameter-name.
Decoding to maps makes the hrl files generated from dictionary files
largely irrelevant. There are value defines generated into these, but
they're typically so long as to be unusable.
---
lib/diameter/doc/src/diameter.xml | 9 ++--
lib/diameter/doc/src/diameter_codec.xml | 9 +++-
lib/diameter/src/base/diameter.erl | 2 +-
lib/diameter/src/base/diameter_codec.erl | 3 ++
lib/diameter/src/base/diameter_config.erl | 3 ++
lib/diameter/src/base/diameter_gen.erl | 28 +++++++++-
lib/diameter/src/base/diameter_service.erl | 2 +-
lib/diameter/src/base/diameter_traffic.erl | 87 ++++++++++++++++++++++--------
8 files changed, 111 insertions(+), 32 deletions(-)
diff --git a/lib/diameter/doc/src/diameter.xml b/lib/diameter/doc/src/diameter.xml
index 663c9cc785..bfb6da41b5 100644
--- a/lib/diameter/doc/src/diameter.xml
+++ b/lib/diameter/doc/src/diameter.xml
@@ -539,7 +539,7 @@ that matches no peer.
The host and realm filters cause the Destination-Host
and Destination-Realm AVPs to be extracted from the
-outgoing request, assuming it to be a record- or list-valued
+outgoing request, assuming it to be a record-, list- or map-valued
&codec_message;, and assuming at most one of each AVP.
If this is not the case then the {host|realm, &dict_DiameterIdentity;}
filters must be used to achieve the desired result.
@@ -970,13 +970,14 @@ occur in the message in question.
-{record_decode, boolean()}
+{record_decode, boolean() | map}
-
Whether or not to decode message and grouped AVPs to records in the
msg field of diameter_packet records and value field of
-diameter_avp records respectively.
-If false then the fields are set to the same value.
+diameter_avp records respectively, or to an alternate format.
+If false then the fields are set to the same value.
+See also &codec_message;.
Defaults to true.
diff --git a/lib/diameter/doc/src/diameter_codec.xml b/lib/diameter/doc/src/diameter_codec.xml
index 0117c1c88a..6262dbf00d 100644
--- a/lib/diameter/doc/src/diameter_codec.xml
+++ b/lib/diameter/doc/src/diameter_codec.xml
@@ -230,7 +230,7 @@ header.
-message() = record() | list()
+message() = record() | list() | map()
-
The representation of a Diameter message as passed to
@@ -240,7 +240,12 @@ a message as defined in a dictionary file is encoded as a record with
one field for each component AVP.
Equivalently, a message can also be encoded as a list whose head is
the atom-valued message name (as specified in the relevant dictionary
-file) and whose tail is a list of {AvpName, AvpValue} pairs.
+file) and whose tail is a list of {AvpName, AvpValues} pairs,
+or as a map with values keyed on AVP names and the message name in key
+:name.
+The format at decode is determined by &mod_service_opt;
+record_decode.
+Any of the formats is accepted at encode.
Another list-valued representation allows a message to be specified
diff --git a/lib/diameter/src/base/diameter.erl b/lib/diameter/src/base/diameter.erl
index f411656e90..4269c84cd2 100644
--- a/lib/diameter/src/base/diameter.erl
+++ b/lib/diameter/src/base/diameter.erl
@@ -338,7 +338,7 @@ call(SvcName, App, Message) ->
| {restrict_connections, restriction()}
| {sequence, sequence() | evaluable()}
| {share_peers, remotes()}
- | {record_decode, boolean()}
+ | {record_decode, boolean() | map}
| {string_decode, boolean()}
| {strict_mbit, boolean()}
| {incoming_maxlen, message_length()}
diff --git a/lib/diameter/src/base/diameter_codec.erl b/lib/diameter/src/base/diameter_codec.erl
index 5e4c6e6d8f..0c43d52093 100644
--- a/lib/diameter/src/base/diameter_codec.erl
+++ b/lib/diameter/src/base/diameter_codec.erl
@@ -275,6 +275,9 @@ rec2msg(_, [Name|_])
when is_atom(Name) ->
Name;
+rec2msg(_, #{':name' := Name}) ->
+ Name;
+
rec2msg(Mod, Rec) ->
Mod:rec2msg(element(1, Rec)).
diff --git a/lib/diameter/src/base/diameter_config.erl b/lib/diameter/src/base/diameter_config.erl
index 46a3e362ac..a790b946c1 100644
--- a/lib/diameter/src/base/diameter_config.erl
+++ b/lib/diameter/src/base/diameter_config.erl
@@ -769,6 +769,9 @@ opt(K, true = B)
K == string_decode ->
B;
+opt(record_decode, map = T) ->
+ T;
+
opt(restrict_connections, T)
when T == node;
T == nodes ->
diff --git a/lib/diameter/src/base/diameter_gen.erl b/lib/diameter/src/base/diameter_gen.erl
index 4879ad8f6c..be2e221b7e 100644
--- a/lib/diameter/src/base/diameter_gen.erl
+++ b/lib/diameter/src/base/diameter_gen.erl
@@ -50,7 +50,9 @@
%% # encode_avps/3
%% ---------------------------------------------------------------------------
--spec encode_avps(parent_name(), parent_record() | avp_values(), map())
+-spec encode_avps(parent_name(),
+ parent_record() | avp_values() | map(),
+ map())
-> iolist()
| no_return().
@@ -83,6 +85,11 @@ encode(Name, Vals, Opts, Mod)
when is_list(Vals) ->
encode(Name, Mod:'#set-'(Vals, newrec(Mod, Name)), Opts, Mod);
+encode(Name, Map, Opts, Mod)
+ when is_map(Map) ->
+ [enc(Name, F, A, V, Opts, Mod) || {F,A} <- Mod:avp_arity(Name),
+ V <- [maps:get(F, Map, def(A))]];
+
encode(Name, Rec, Opts, Mod) ->
[encode(Name, F, V, Opts, Mod) || {F,V} <- Mod:'#get-'(Rec)].
@@ -627,6 +634,14 @@ too_many(FieldName, M, Map) ->
set(_, _, _, _, undefined = No) ->
No;
+set(1, F, Value, _, Map)
+ when is_map(Map) ->
+ maps:put(F, Value, Map);
+
+set(_, F, V, _, Map)
+ when is_map(Map) ->
+ maps:update_with(F, fun(Vs) -> [V|Vs] end, [V], Map);
+
set(1, F, Value, Mod, Rec) ->
Mod:'#set-'({F, Value}, Rec);
@@ -731,6 +746,9 @@ empty(Name, #{module := Mod} = Opts) ->
newrec(_, _, #{record_decode := false}) ->
undefined;
+newrec(_, Name, #{record_decode := map}) ->
+ #{':name' => Name};
+
newrec(Mod, Name, _) ->
newrec(Mod, Name).
@@ -738,3 +756,11 @@ newrec(Mod, Name, _) ->
newrec(Mod, Name) ->
Mod:'#new-'(Mod:name2rec(Name)).
+
+%% def/1
+
+def(1) ->
+ undefined;
+
+def(_) ->
+ [].
diff --git a/lib/diameter/src/base/diameter_service.erl b/lib/diameter/src/base/diameter_service.erl
index 6dc4889c82..3e555f6263 100644
--- a/lib/diameter/src/base/diameter_service.erl
+++ b/lib/diameter/src/base/diameter_service.erl
@@ -113,7 +113,7 @@
restrict_connections := diameter:restriction(),
incoming_maxlen := diameter:message_length(),
strict_mbit := boolean(),
- record_decode := boolean(),
+ record_decode := boolean() | map,
string_decode := boolean(),
spawn_opt := list() | {module(), atom(), list()}}}).
diff --git a/lib/diameter/src/base/diameter_traffic.erl b/lib/diameter/src/base/diameter_traffic.erl
index 228d9802ad..f7dec2441f 100644
--- a/lib/diameter/src/base/diameter_traffic.erl
+++ b/lib/diameter/src/base/diameter_traffic.erl
@@ -76,7 +76,7 @@
service_name :: diameter:service_name(),
apps :: [#diameter_app{}],
sequence :: diameter:sequence(),
- codec :: #{record_decode := boolean(),
+ codec :: #{record_decode := boolean() | map,
string_decode := boolean(),
strict_mbit := boolean(),
incoming_maxlen := diameter:message_length()}}).
@@ -625,6 +625,12 @@ is_answer_message([#diameter_header{is_request = R, is_error = E} | _], _) ->
is_answer_message([Name | _], _) ->
Name == 'answer-message';
+%% Message sent as a map.
+is_answer_message(Map, _)
+ when is_map(Map) ->
+ #{':name' := Name} = Map,
+ Name == 'answer-message';
+
%% Message sent as a record.
is_answer_message(Rec, Dict) ->
try
@@ -873,6 +879,11 @@ reset(Msg, [RC | Avps], Dict) ->
set([_|_] = Ans, Avps, _) ->
Ans ++ Avps; %% Values nearer tail take precedence.
+%% ... a map ...
+set(Ans, Avps, _)
+ when is_map(Ans) ->
+ maps:merge(Ans, maps:from_list(Avps));
+
%% ... or record.
set(Rec, Avps, Dict) ->
Dict:'#set-'(Avps, Rec).
@@ -891,6 +902,9 @@ rc([MsgName | _], RC, Dict) ->
_ -> []
end;
+rc(#{':name' := Name}, RC, Dict) ->
+ rc([Name], RC, Dict);
+
rc(Rec, RC, Dict) ->
rc([Dict:rec2msg(element(1, Rec))], RC, Dict).
@@ -902,34 +916,50 @@ failed_avp(_, [] = No, _) ->
failed_avp(Msg, [_|_] = Avps, Dict) ->
[failed(Msg, [{'AVP', Avps}], Dict)].
-%% Reply as name and tuple list ...
-failed([MsgName | Values], FailedAvp, Dict) ->
- RecName = Dict:msg2rec(MsgName),
- try
- Dict:'#info-'(RecName, {index, 'Failed-AVP'}),
- {'Failed-AVP', [FailedAvp]}
- catch
- error: _ ->
- Avps = proplists:get_value('AVP', Values, []),
- A = #diameter_avp{name = 'Failed-AVP',
- value = FailedAvp},
- {'AVP', [A|Avps]}
- end;
+%% failed/3
-%% ... or record.
-failed(Rec, FailedAvp, Dict) ->
+failed(Msg, FailedAvp, Dict) ->
+ RecName = msg2rec(Msg, Dict),
try
- RecName = element(1, Rec),
- Dict:'#info-'(RecName, {index, 'Failed-AVP'}),
+ Dict:'#info-'(RecName, {index, 'Failed-AVP'}), %% assert existence
{'Failed-AVP', [FailedAvp]}
catch
error: _ ->
- Avps = Dict:'#get-'('AVP', Rec),
+ Avps = values(Msg, 'AVP', Dict),
A = #diameter_avp{name = 'Failed-AVP',
value = FailedAvp},
{'AVP', [A|Avps]}
end.
+%% msg2rec/2
+
+%% Message as name/values list ...
+msg2rec([MsgName | _], Dict) ->
+ Dict:msg2rec(MsgName);
+
+%% ... map ...
+msg2rec(#{':name' := MsgName}, Dict) ->
+ Dict:msg2rec(MsgName);
+
+%% ... or record.
+msg2rec(Rec, _) ->
+ element(1, Rec).
+
+%% values/2
+
+%% Message as name/values list ...
+values([_ | Avps], F, _) ->
+ proplists:get_value(F, Avps, []);
+
+%% ... map ...
+values(Msg, F, _)
+ when is_map(Msg) ->
+ maps:get(F, Msg, []);
+
+%% ... or record.
+values(Rec, F, Dict) ->
+ Dict:'#get-'(F, Rec).
+
%% 3. Diameter Header
%%
%% E(rror) - If set, the message contains a protocol error,
@@ -1861,7 +1891,7 @@ str(T) ->
get_avp(?RELAY, Name, Msg) ->
get_avp(?BASE, Name, Msg);
-%% Message as a header/avps list.
+%% Message is a header/avps list.
get_avp(Dict, Name, [#diameter_header{} | Avps]) ->
try
{Code, _, VId} = Dict:avp_header(Name),
@@ -1874,7 +1904,7 @@ get_avp(Dict, Name, [#diameter_header{} | Avps]) ->
undefined
end;
-%% Outgoing message as a name/values list.
+%% Message as name/values list ...
get_avp(_, Name, [_MsgName | Avps]) ->
case lists:keyfind(Name, 1, Avps) of
{_, V} ->
@@ -1883,7 +1913,17 @@ get_avp(_, Name, [_MsgName | Avps]) ->
undefined
end;
-%% Message is typically a record but not necessarily.
+%% ... map ...
+get_avp(_, Name, Map)
+ when is_map(Map) ->
+ case maps:find(Name, Map) of
+ {ok, V} ->
+ #diameter_avp{name = Name, value = V};
+ error ->
+ undefined
+ end;
+
+%% ... or record (but not necessarily).
get_avp(Dict, Name, Rec) ->
try
#diameter_avp{name = Name, value = Dict:'#get-'(Name, Rec)}
@@ -1913,7 +1953,8 @@ ungroup(Avp) ->
avp_decode(Dict, Name, #diameter_avp{value = undefined,
data = Bin}
- = Avp) ->
+ = Avp)
+ when is_binary(Bin) ->
try Dict:avp(decode, Bin, Name, decode_opts(Dict)) of
V ->
Avp#diameter_avp{value = V}
--
cgit v1.2.3
From d52611e9bd0628affa7b4f56a6126e4a99b69a7a Mon Sep 17 00:00:00 2001
From: Anders Svensson
Date: Thu, 6 Jul 2017 12:07:36 +0200
Subject: Let messages and grouped AVPs be decoded to lists
That is, decode to the same format that encode already accepts. Only a
message has its name at the head of the list since AVPs are already
name/value pairs.
---
lib/diameter/doc/src/diameter.xml | 3 ++-
lib/diameter/src/base/diameter.erl | 2 +-
lib/diameter/src/base/diameter_codec.erl | 8 ++++++-
lib/diameter/src/base/diameter_config.erl | 4 +++-
lib/diameter/src/base/diameter_gen.erl | 35 ++++++++++++++++++++----------
lib/diameter/src/base/diameter_service.erl | 2 +-
lib/diameter/src/base/diameter_traffic.erl | 2 +-
7 files changed, 38 insertions(+), 18 deletions(-)
diff --git a/lib/diameter/doc/src/diameter.xml b/lib/diameter/doc/src/diameter.xml
index bfb6da41b5..e525ab3345 100644
--- a/lib/diameter/doc/src/diameter.xml
+++ b/lib/diameter/doc/src/diameter.xml
@@ -970,7 +970,8 @@ occur in the message in question.
-{record_decode, boolean() | map}
+
+{record_decode, boolean() | list | map}
-
Whether or not to decode message and grouped AVPs to records in the
diff --git a/lib/diameter/src/base/diameter.erl b/lib/diameter/src/base/diameter.erl
index 4269c84cd2..b033632c47 100644
--- a/lib/diameter/src/base/diameter.erl
+++ b/lib/diameter/src/base/diameter.erl
@@ -338,7 +338,7 @@ call(SvcName, App, Message) ->
| {restrict_connections, restriction()}
| {sequence, sequence() | evaluable()}
| {share_peers, remotes()}
- | {record_decode, boolean() | map}
+ | {record_decode, boolean() | list | map}
| {string_decode, boolean()}
| {strict_mbit, boolean()}
| {incoming_maxlen, message_length()}
diff --git a/lib/diameter/src/base/diameter_codec.erl b/lib/diameter/src/base/diameter_codec.erl
index 0c43d52093..9043af145e 100644
--- a/lib/diameter/src/base/diameter_codec.erl
+++ b/lib/diameter/src/base/diameter_codec.erl
@@ -379,10 +379,16 @@ decode_avps(MsgName, Mod, AppMod, Opts, Pkt, Avps) -> %% ... or not
Opts#{dictionary => AppMod,
failed_avp => false}),
?LOGC([] /= Errors, decode_errors, Pkt#diameter_packet.header),
- Pkt#diameter_packet{msg = Rec,
+ Pkt#diameter_packet{msg = reformat(MsgName, Rec, Opts),
errors = Errors,
avps = As}.
+reformat(MsgName, Avps, #{decode_format := list}) ->
+ [MsgName | Avps];
+
+reformat(_, Msg, _) ->
+ Msg.
+
%%% ---------------------------------------------------------------------------
%%% # decode_header/1
%%% ---------------------------------------------------------------------------
diff --git a/lib/diameter/src/base/diameter_config.erl b/lib/diameter/src/base/diameter_config.erl
index a790b946c1..8f958a67b4 100644
--- a/lib/diameter/src/base/diameter_config.erl
+++ b/lib/diameter/src/base/diameter_config.erl
@@ -769,7 +769,9 @@ opt(K, true = B)
K == string_decode ->
B;
-opt(record_decode, map = T) ->
+opt(record_decode, T)
+ when T == list;
+ T == map ->
T;
opt(restrict_connections, T)
diff --git a/lib/diameter/src/base/diameter_gen.erl b/lib/diameter/src/base/diameter_gen.erl
index be2e221b7e..2381b73d07 100644
--- a/lib/diameter/src/base/diameter_gen.erl
+++ b/lib/diameter/src/base/diameter_gen.erl
@@ -178,14 +178,17 @@ enc_AVP(_Name, {_Dict, _AvpName, _Data} = T, Opts, _) ->
-> {parent_record(), [avp()], Failed}
when Failed :: [{5000..5999, #diameter_avp{}}].
-decode_avps(Name, Recs, #{module := Mod} = Opts) ->
+decode_avps(Name, Recs, #{module := Mod, record_decode := Fmt} = Opts) ->
{Avps, {Rec, AM, Failed}}
= mapfoldl(fun(T,A) -> decode(Name, Opts, Mod, T, A) end,
- {newrec(Mod, Name, Opts), #{}, []},
+ {newrec(Mod, Name, Fmt), #{}, []},
Recs),
%% AM counts the number of top-level AVPs, which missing/4 then
%% uses when adding 5005 errors.
- {Rec, Avps, Failed ++ missing(Name, Opts, Mod, AM)}.
+ Arities = Mod:avp_arity(Name),
+ {reformat(Rec, Arities, Fmt),
+ Avps,
+ Failed ++ missing(Arities, Opts, Mod, AM)}.
%% Append 5005 errors so that errors are reported in the order
%% encountered. Failed-AVP should typically contain the first
@@ -216,10 +219,10 @@ mapfoldl(_, Acc, [], List) ->
%% Vendor-Id if applicable. The value field of the missing AVP
%% should be of correct minimum length and contain zeros.
-missing(Name, Opts, Mod, AM) ->
+missing(Arities, Opts, Mod, AM) ->
lists:foldl(fun(T,A) -> missing(T, AM, Opts, Mod, A) end,
[],
- Mod:avp_arity(Name)).
+ Arities).
%% missing/5
@@ -631,7 +634,7 @@ too_many(FieldName, M, Map) ->
%% set/5
-set(_, _, _, _, undefined = No) ->
+set(_, _, _, _, false = No) ->
No;
set(1, F, Value, _, Map)
@@ -743,20 +746,28 @@ empty(Name, #{module := Mod} = Opts) ->
%% newrec/3
-newrec(_, _, #{record_decode := false}) ->
- undefined;
+newrec(_, _, false = No) ->
+ No;
-newrec(_, Name, #{record_decode := map}) ->
- #{':name' => Name};
+newrec(Mod, Name, true) ->
+ newrec(Mod, Name);
-newrec(Mod, Name, _) ->
- newrec(Mod, Name).
+newrec(_, Name, _) ->
+ #{':name' => Name}.
%% newrec/2
newrec(Mod, Name) ->
Mod:'#new-'(Mod:name2rec(Name)).
+%% reformat/3
+
+reformat(Map, Arities, list) ->
+ [{F,V} || {F,_} <- Arities, #{F := V} <- [Map]];
+
+reformat(Rec, _, _) ->
+ Rec.
+
%% def/1
def(1) ->
diff --git a/lib/diameter/src/base/diameter_service.erl b/lib/diameter/src/base/diameter_service.erl
index 3e555f6263..7f7e3e3a3f 100644
--- a/lib/diameter/src/base/diameter_service.erl
+++ b/lib/diameter/src/base/diameter_service.erl
@@ -113,7 +113,7 @@
restrict_connections := diameter:restriction(),
incoming_maxlen := diameter:message_length(),
strict_mbit := boolean(),
- record_decode := boolean() | map,
+ record_decode := boolean() | map | list,
string_decode := boolean(),
spawn_opt := list() | {module(), atom(), list()}}}).
diff --git a/lib/diameter/src/base/diameter_traffic.erl b/lib/diameter/src/base/diameter_traffic.erl
index f7dec2441f..6594994cfa 100644
--- a/lib/diameter/src/base/diameter_traffic.erl
+++ b/lib/diameter/src/base/diameter_traffic.erl
@@ -76,7 +76,7 @@
service_name :: diameter:service_name(),
apps :: [#diameter_app{}],
sequence :: diameter:sequence(),
- codec :: #{record_decode := boolean() | map,
+ codec :: #{record_decode := boolean() | map | list,
string_decode := boolean(),
strict_mbit := boolean(),
incoming_maxlen := diameter:message_length()}}).
--
cgit v1.2.3
From f0465811faf9085cfbd82b0bc1f91e2f0da07590 Mon Sep 17 00:00:00 2001
From: Anders Svensson
Date: Sat, 8 Jul 2017 00:15:08 +0200
Subject: Test map encoding in traffic suite
---
lib/diameter/test/diameter_traffic_SUITE.erl | 110 ++++++++++++++++++---------
1 file changed, 76 insertions(+), 34 deletions(-)
diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl
index dd0dfc776d..26bc96490a 100644
--- a/lib/diameter/test/diameter_traffic_SUITE.erl
+++ b/lib/diameter/test/diameter_traffic_SUITE.erl
@@ -139,8 +139,8 @@
%% Sequence mask for End-to-End and Hop-by-Hop identifiers.
-define(CLIENT_MASK, {1,26}). %% 1 in top 6 bits
-%% How to construct messages, as record or list.
--define(ENCODINGS, [list, record]).
+%% How to construct messages, as record, list, or map.
+-define(ENCODINGS, [list, record, map]).
%% How to send answers, in a diameter_packet or not.
-define(CONTAINERS, [pkt, msg]).
@@ -1013,15 +1013,17 @@ origin({A,C}) ->
2*codec(A) + container(C);
origin(N) ->
- {codec(N band 2), container(N rem 2)}.
+ {codec(N div 2), container(N rem 2)}.
-%% Map booleans, but the readable atoms are part of (constructed)
-%% group names, so it's good that they're readable.
+%% Map atoms. The atoms are part of (constructed) group names, so it's
+%% good that they're readable.
codec(record) -> 0;
codec(list) -> 1;
+codec(map) -> 2;
codec(0) -> record;
-codec(_) -> list.
+codec(1) -> list;
+codec(2) -> map.
container(pkt) -> 0;
container(msg) -> 1;
@@ -1032,12 +1034,19 @@ msg([H|_] = Msg, record = E, diameter_gen_base_rfc3588)
when H == 'ACR';
H == 'ACA' ->
msg(Msg, E, diameter_gen_base_accounting);
+
msg([H|_] = Msg, record = E, diameter_gen_base_rfc6733)
when H == 'ACR';
H == 'ACA' ->
msg(Msg, E, diameter_gen_acct_rfc6733);
+
msg([H|T], record, Dict) ->
Dict:'#new-'(Dict:msg2rec(H), T);
+
+msg([H|T], map, _) ->
+ Map = maps:from_list(T),
+ Map#{':name' => H};
+
msg(Msg, _, _) ->
Msg.
@@ -1049,20 +1058,26 @@ appdict(D) ->
dict0(D) ->
?A("diameter_gen_base_" ++ ?L(D)).
-dict(Msg, nas4005 = D) ->
- if 'answer-message' == hd(Msg);
- ?is_record(Msg, 'diameter_base_answer-message') ->
+dict(Msg, Dict) ->
+ d(name(Msg), Dict).
+
+d(N, nas4005 = D) ->
+ if N == {list, 'answer-message'};
+ N == {map, 'answer-message'};
+ N == {record, 'diameter_base_answer-message'} ->
diameter_gen_base_rfc3588;
true ->
D
end;
-dict(Msg, Dict0)
- when 'ACR' == hd(Msg);
- 'ACA' == hd(Msg);
- ?is_record(Msg, diameter_base_accounting_ACR);
- ?is_record(Msg, diameter_base_accounting_ACA) ->
+d(N, Dict0)
+ when N == {list, 'ACR'};
+ N == {list, 'ACA'};
+ N == {map, 'ACR'};
+ N == {map, 'ACA'};
+ N == {record, diameter_base_accounting_ACR};
+ N == {record, diameter_base_accounting_ACA} ->
acct(Dict0);
-dict(_, Dict0) ->
+d(_, Dict0) ->
Dict0.
acct(diameter_gen_base_rfc3588) ->
@@ -1071,21 +1086,28 @@ acct(diameter_gen_base_rfc6733) ->
diameter_gen_acct_rfc6733.
%% Set only values that aren't already.
+
set(_, [H|T], Vs) ->
[H | Vs ++ T];
+
+set(_, Map, Vs)
+ when is_map(Map) ->
+ maps:merge(maps:from_list(Vs), Map);
+
set(#group{client_dict = Dict0} = _Group, Rec, Vs) ->
Dict = dict(Rec, Dict0),
lists:foldl(fun({F,_} = FV, A) ->
- set(Dict, Dict:'#get-'(F, A), FV, A)
+ reset(Dict, Dict:'#get-'(F, A), FV, A)
end,
Rec,
Vs).
-set(Dict, E, FV, Rec)
+reset(Dict, E, FV, Rec)
when E == undefined;
E == [] ->
Dict:'#set-'(FV, Rec);
-set(_, _, _, Rec) ->
+
+reset(_, _, _, Rec) ->
Rec.
%% ===========================================================================
@@ -1280,10 +1302,16 @@ prepare(Pkt, Caps, _Name, Group) ->
%% prepare/3
-prepare(#diameter_packet{msg = Req}, Caps, Group)
- when ?is_record(Req, diameter_base_accounting_ACR);
- ?is_record(Req, nas_ACR);
- 'ACR' == hd(Req) ->
+prepare(#diameter_packet{msg = Req} = Pkt, Caps, Group) ->
+ set(name(Req), Pkt, Caps, Group).
+
+%% set/4
+
+set(N, #diameter_packet{msg = Req}, Caps, Group)
+ when N == {record, diameter_base_accounting_ACR};
+ N == {record, nas_ACR};
+ N == {map, 'ACR'};
+ N == {list, 'ACR'} ->
#diameter_caps{origin_host = {OH, _},
origin_realm = {OR, DR}}
= Caps,
@@ -1293,10 +1321,11 @@ prepare(#diameter_packet{msg = Req}, Caps, Group)
{'Origin-Realm', OR},
{'Destination-Realm', DR}]);
-prepare(#diameter_packet{msg = Req}, Caps, Group)
- when ?is_record(Req, diameter_base_ASR);
- ?is_record(Req, nas_ASR);
- 'ASR' == hd(Req) ->
+set(N, #diameter_packet{msg = Req}, Caps, Group)
+ when N == {record, diameter_base_ASR};
+ N == {record, nas_ASR};
+ N == {map, 'ASR'};
+ N == {list, 'ASR'} ->
#diameter_caps{origin_host = {OH, DH},
origin_realm = {OR, DR}}
= Caps,
@@ -1307,10 +1336,11 @@ prepare(#diameter_packet{msg = Req}, Caps, Group)
{'Destination-Realm', DR},
{'Auth-Application-Id', ?APP_ID}]);
-prepare(#diameter_packet{msg = Req}, Caps, Group)
- when ?is_record(Req, diameter_base_STR);
- ?is_record(Req, nas_STR);
- 'STR' == hd(Req) ->
+set(N, #diameter_packet{msg = Req}, Caps, Group)
+ when N == {record, diameter_base_STR};
+ N == {record, nas_STR};
+ N == {map, 'STR'};
+ N == {list, 'STR'} ->
#diameter_caps{origin_host = {OH, _},
origin_realm = {OR, DR}}
= Caps,
@@ -1320,10 +1350,11 @@ prepare(#diameter_packet{msg = Req}, Caps, Group)
{'Destination-Realm', DR},
{'Auth-Application-Id', ?APP_ID}]);
-prepare(#diameter_packet{msg = Req}, Caps, Group)
- when ?is_record(Req, diameter_base_RAR);
- ?is_record(Req, nas_RAR);
- 'RAR' == hd(Req) ->
+set(N, #diameter_packet{msg = Req}, Caps, Group)
+ when N == {record, diameter_base_RAR};
+ N == {record, nas_RAR};
+ N == {map, 'RAR'};
+ N == {list, 'RAR'} ->
#diameter_caps{origin_host = {OH, DH},
origin_realm = {OR, DR}}
= Caps,
@@ -1334,6 +1365,17 @@ prepare(#diameter_packet{msg = Req}, Caps, Group)
{'Destination-Realm', DR},
{'Auth-Application-Id', ?APP_ID}]).
+%% name/1
+
+name([H|_]) ->
+ {list, H};
+
+name(#{} = Map) ->
+ {map, maps:get(':name', Map)};
+
+name(Rec) ->
+ {record, element(1, Rec)}.
+
%% prepare_retransmit/5
prepare_retransmit(_Pkt, false, _Peer, _Name, _Group) ->
--
cgit v1.2.3
From e7e1cda23e60afd807669ab417f45e7faa62a5b8 Mon Sep 17 00:00:00 2001
From: Anders Svensson
Date: Thu, 6 Jul 2017 16:38:03 +0200
Subject: Map answers to maps in traffic suite
Instead of to lists, to simplify matching.
---
lib/diameter/test/diameter_traffic_SUITE.erl | 146 ++++++++++++++++++---------
1 file changed, 98 insertions(+), 48 deletions(-)
diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl
index 26bc96490a..07d1c4937b 100644
--- a/lib/diameter/test/diameter_traffic_SUITE.erl
+++ b/lib/diameter/test/diameter_traffic_SUITE.erl
@@ -183,14 +183,16 @@
%% A common match when receiving answers in a client.
-define(answer_message(SessionId, ResultCode),
- ['answer-message',
- {'Session-Id', SessionId},
- {'Origin-Host', _},
- {'Origin-Realm', _},
- {'Result-Code', ResultCode}
- | _]).
+ #{':name' := 'answer-message',
+ 'Session-Id' := SessionId,
+ 'Origin-Host' := _,
+ 'Origin-Realm' := _,
+ 'Result-Code' := ResultCode}).
-define(answer_message(ResultCode),
- ?answer_message(_, ResultCode)).
+ #{':name' := 'answer-message',
+ 'Origin-Host' := _,
+ 'Origin-Realm' := _,
+ 'Result-Code' := ResultCode}).
%% Config for diameter:start_service/2.
-define(SERVICE(Name, Decode),
@@ -567,7 +569,9 @@ send_ok(Config) ->
Req = ['ACR', {'Accounting-Record-Type', ?EVENT_RECORD},
{'Accounting-Record-Number', 1}],
- ['ACA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | _]
+ #{':name' := 'ACA',
+ 'Result-Code' := ?SUCCESS,
+ 'Session-Id' := _}
= call(Config, Req).
%% Send an accounting ACR that the server answers badly to.
@@ -583,7 +587,9 @@ send_eval(Config) ->
Req = ['ACR', {'Accounting-Record-Type', ?EVENT_RECORD},
{'Accounting-Record-Number', 3}],
- ['ACA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | _]
+ #{':name' := 'ACA',
+ 'Result-Code' := ?SUCCESS,
+ 'Session-Id' := _}
= call(Config, Req).
%% Send an accounting ACR that the server tries to answer with an
@@ -609,7 +615,8 @@ send_protocol_error(Config) ->
send_experimental_result(Config) ->
Req = ['ACR', {'Accounting-Record-Type', ?EVENT_RECORD},
{'Accounting-Record-Number', 5}],
- ['ACA', {'Session-Id', _} | _]
+ #{':name' := 'ACA',
+ 'Session-Id' := _}
= call(Config, Req).
%% Send an ASR with an arbitrary non-mandatory AVP and expect success
@@ -617,11 +624,12 @@ send_experimental_result(Config) ->
send_arbitrary(Config) ->
Req = ['ASR', {'AVP', [#diameter_avp{name = 'Product-Name',
value = "XXX"}]}],
- ['ASA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | Avps]
+ #{':name' := 'ASA',
+ 'Session-Id' := _,
+ 'Result-Code' := ?SUCCESS,
+ 'AVP' := [#diameter_avp{name = 'Product-Name',
+ value = V}]}
= call(Config, Req),
- {'AVP', [#diameter_avp{name = 'Product-Name',
- value = V}]}
- = lists:last(Avps),
"XXX" = string(V, Config).
%% Send an unknown AVP (to some client) and check that it comes back.
@@ -629,12 +637,13 @@ send_unknown(Config) ->
Req = ['ASR', {'AVP', [#diameter_avp{code = 999,
is_mandatory = false,
data = <<17>>}]}],
- ['ASA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | Avps]
- = call(Config, Req),
- {'AVP', [#diameter_avp{code = 999,
- is_mandatory = false,
- data = <<17>>}]}
- = lists:last(Avps).
+ #{':name' := 'ASA',
+ 'Session-Id' := _,
+ 'Result-Code' := ?SUCCESS,
+ 'AVP' := [#diameter_avp{code = 999,
+ is_mandatory = false,
+ data = <<17>>}]}
+ = call(Config, Req).
%% Ditto, and point the AVP length past the end of the message. Expect
%% 5014.
@@ -645,7 +654,10 @@ send_unknown_short(Config, M, RC) ->
Req = ['ASR', {'AVP', [#diameter_avp{code = 999,
is_mandatory = M,
data = <<17>>}]}],
- ['ASA', {'Session-Id', _}, {'Result-Code', RC} | Avps]
+ #{':name' := 'ASA',
+ 'Session-Id' := _,
+ 'Result-Code' := RC,
+ 'Failed-AVP' := Avps}
= call(Config, Req),
[[#diameter_avp{code = 999,
is_mandatory = M,
@@ -657,7 +669,10 @@ send_unknown_mandatory(Config) ->
Req = ['ASR', {'AVP', [#diameter_avp{code = 999,
is_mandatory = true,
data = <<17>>}]}],
- ['ASA', {'Session-Id', _}, {'Result-Code', ?AVP_UNSUPPORTED} | Avps]
+ #{':name' := 'ASA',
+ 'Session-Id' := _,
+ 'Result-Code' := ?AVP_UNSUPPORTED,
+ 'Failed-AVP' := Avps}
= call(Config, Req),
[[#diameter_avp{code = 999,
is_mandatory = true,
@@ -675,7 +690,10 @@ send_unexpected_mandatory_decode(Config) ->
Req = ['ASR', {'AVP', [#diameter_avp{code = 27, %% Session-Timeout
is_mandatory = true,
data = <<12:32>>}]}],
- ['ASA', {'Session-Id', _}, {'Result-Code', ?AVP_UNSUPPORTED} | Avps]
+ #{':name' := 'ASA',
+ 'Session-Id' := _,
+ 'Result-Code' := ?AVP_UNSUPPORTED,
+ 'Failed-AVP' := Avps}
= call(Config, Req),
[[#diameter_avp{code = 27,
is_mandatory = true,
@@ -691,7 +709,10 @@ send_unexpected_mandatory_decode(Config) ->
send_grouped_error(Config) ->
Req = ['ASR', {'Proxy-Info', [[{'Proxy-Host', "abcd"},
{'Proxy-State', ""}]]}],
- ['ASA', {'Session-Id', _}, {'Result-Code', ?INVALID_AVP_LENGTH} | Avps]
+ #{':name' := 'ASA',
+ 'Session-Id' := _,
+ 'Result-Code' := ?INVALID_AVP_LENGTH,
+ 'Failed-AVP' := Avps}
= call(Config, Req),
[[#diameter_avp{name = 'Proxy-Info', value = V}]]
= failed_avps(Avps, Config),
@@ -724,7 +745,9 @@ send_error_bit(Config) ->
%% Send a bad version and check that we get 5011.
send_unsupported_version(Config) ->
Req = ['STR', {'Termination-Cause', ?LOGOUT}],
- ['STA', {'Session-Id', _}, {'Result-Code', ?UNSUPPORTED_VERSION} | _]
+ #{':name' := 'STA',
+ 'Session-Id' := _,
+ 'Result-Code' := ?UNSUPPORTED_VERSION}
= call(Config, Req).
%% Send a request containing an AVP length > data size.
@@ -744,15 +767,16 @@ send_zero_avp_length(Config) ->
send_invalid_avp_length(Config) ->
Req = ['STR', {'Termination-Cause', ?LOGOUT}],
- ['STA', {'Session-Id', _},
- {'Result-Code', ?INVALID_AVP_LENGTH},
- {'Origin-Host', _},
- {'Origin-Realm', _},
- {'User-Name', _},
- {'Class', _},
- {'Error-Message', _},
- {'Error-Reporting-Host', _}
- | Avps]
+ #{':name' := 'STA',
+ 'Session-Id' := _,
+ 'Result-Code' := ?INVALID_AVP_LENGTH,
+ 'Origin-Host' := _,
+ 'Origin-Realm' := _,
+ 'User-Name' := _,
+ 'Class' := _,
+ 'Error-Message' := _,
+ 'Error-Reporting-Host' := _,
+ 'Failed-AVP' := Avps}
= call(Config, Req),
[[_]] = failed_avps(Avps, Config).
@@ -769,14 +793,18 @@ send_invalid_reject(Config) ->
send_unexpected_mandatory(Config) ->
Req = ['STR', {'Termination-Cause', ?LOGOUT}],
- ['STA', {'Session-Id', _}, {'Result-Code', ?AVP_UNSUPPORTED} | _]
+ #{':name' := 'STA',
+ 'Session-Id' := _,
+ 'Result-Code' := ?AVP_UNSUPPORTED}
= call(Config, Req).
%% Send something long that will be fragmented by TCP.
send_long(Config) ->
Req = ['STR', {'Termination-Cause', ?LOGOUT},
{'User-Name', [binary:copy(<<$X>>, 1 bsl 20)]}],
- ['STA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | _]
+ #{':name' := 'STA',
+ 'Session-Id' := _,
+ 'Result-Code' := ?SUCCESS}
= call(Config, Req).
%% Send something longer than the configure incoming_maxlen.
@@ -819,7 +847,9 @@ send_any_2(Config) ->
send_all_1(Config) ->
Req = ['STR', {'Termination-Cause', ?LOGOUT}],
Realm = lists:foldr(fun(C,A) -> [C,A] end, [], ?REALM),
- ['STA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | _]
+ #{':name' := 'STA',
+ 'Session-Id' := _,
+ 'Result-Code' := ?SUCCESS}
= call(Config, Req, [{filter, {all, [{host, any},
{realm, Realm}]}}]).
send_all_2(Config) ->
@@ -848,9 +878,10 @@ send_detach(Config) ->
Req = ['STR', {'Termination-Cause', ?LOGOUT}],
Ref = make_ref(),
ok = call(Config, Req, [{extra, [{self(), Ref}]}, detach]),
- Ans = receive {Ref, T} -> T end,
- ['STA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | _]
- = Ans.
+ #{':name' := 'STA',
+ 'Session-Id' := _,
+ 'Result-Code' := ?SUCCESS}
+ = receive {Ref, T} -> T end.
%% Send a request which can't be encoded and expect {error, encode}.
send_encode_error(Config) ->
@@ -862,11 +893,15 @@ send_destination_1(Config) ->
= group(Config),
Req = ['STR', {'Termination-Cause', ?LOGOUT},
{'Destination-Host', [?HOST(SN, ?REALM)]}],
- ['STA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | _]
+ #{':name' := 'STA',
+ 'Session-Id' := _,
+ 'Result-Code' := ?SUCCESS}
= call(Config, Req, [{filter, {all, [host, realm]}}]).
send_destination_2(Config) ->
Req = ['STR', {'Termination-Cause', ?LOGOUT}],
- ['STA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | _]
+ #{':name' := 'STA',
+ 'Session-Id' := _,
+ 'Result-Code' := ?SUCCESS}
= call(Config, Req, [{filter, {all, [host, realm]}}]).
%% Send with filtering on and expect failure when specifying an
@@ -930,7 +965,9 @@ send_bad_filter(Config, F) ->
%% Specify multiple filter options and expect them be conjunctive.
send_multiple_filters_1(Config) ->
Fun = fun(#diameter_caps{}) -> true end,
- ['STA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | _]
+ #{':name' := 'STA',
+ 'Session-Id' := _,
+ 'Result-Code' := ?SUCCESS}
= send_multiple_filters(Config, [host, {eval, Fun}]).
send_multiple_filters_2(Config) ->
E = {erlang, is_tuple, []},
@@ -941,7 +978,9 @@ send_multiple_filters_3(Config) ->
E2 = {erlang, is_tuple, []},
E3 = {erlang, is_record, [diameter_caps]},
E4 = [{erlang, is_record, []}, diameter_caps],
- ['STA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | _]
+ #{':name' := 'STA',
+ 'Session-Id' := _,
+ 'Result-Code' := ?SUCCESS}
= send_multiple_filters(Config, [{eval, E} || E <- [E1,E2,E3,E4]]).
send_multiple_filters(Config, Fs) ->
@@ -952,14 +991,16 @@ send_multiple_filters(Config, Fs) ->
%% only the return value from the prepare_request callback being
%% significant.
send_anything(Config) ->
- ['STA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | _]
+ #{':name' := 'STA',
+ 'Session-Id' := _,
+ 'Result-Code' := ?SUCCESS}
= call(Config, anything).
%% ===========================================================================
failed_avps(Avps, Config) ->
#group{client_dict = D} = proplists:get_value(group, Config),
- [failed_avp(D, T) || T <- proplists:get_value('Failed-AVP', Avps)].
+ [failed_avp(D, T) || T <- Avps].
failed_avp(nas4005, {'nas_Failed-AVP', As}) ->
As;
@@ -1374,7 +1415,12 @@ name(#{} = Map) ->
{map, maps:get(':name', Map)};
name(Rec) ->
- {record, element(1, Rec)}.
+ try
+ {record, element(1, Rec)}
+ catch
+ error: badarg ->
+ false
+ end.
%% prepare_retransmit/5
@@ -1396,7 +1442,11 @@ answer(Pkt, Req, _Peer, Name, #group{client_dict = Dict0}) ->
#diameter_header{application_id = ApplId} = H, %% assert
Dict = dict(Ans, Dict0),
[R | Vs] = Dict:'#get-'(answer(Ans, Es, Name)),
- [Dict:rec2msg(R) | Vs].
+ maps:put(':name',
+ Dict:rec2msg(R),
+ maps:from_list([T || {_,V} = T <- Vs,
+ V /= undefined,
+ V /= []])).
%% Missing Result-Code and inappropriate Experimental-Result-Code.
answer(Rec, Es, send_experimental_result) ->
--
cgit v1.2.3
From f87aeb3fb2c84790b37796d5e57b4a09ac2f4ed7 Mon Sep 17 00:00:00 2001
From: Anders Svensson
Date: Thu, 6 Jul 2017 17:55:48 +0200
Subject: Test record_decode in traffic suite
---
lib/diameter/test/diameter_traffic_SUITE.erl | 237 ++++++++++++++++-----------
1 file changed, 140 insertions(+), 97 deletions(-)
diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl
index 07d1c4937b..47f83676bb 100644
--- a/lib/diameter/test/diameter_traffic_SUITE.erl
+++ b/lib/diameter/test/diameter_traffic_SUITE.erl
@@ -139,9 +139,12 @@
%% Sequence mask for End-to-End and Hop-by-Hop identifiers.
-define(CLIENT_MASK, {1,26}). %% 1 in top 6 bits
-%% How to construct messages, as record, list, or map.
+%% How to construct outgoing messages.
-define(ENCODINGS, [list, record, map]).
+%% How to set record_decode.
+-define(DECODINGS, [true, false, map, list]).
+
%% How to send answers, in a diameter_packet or not.
-define(CONTAINERS, [pkt, msg]).
@@ -169,6 +172,7 @@
client_dict,
client_sender,
server_service,
+ server_decoding,
server_encoding,
server_container,
server_sender,
@@ -264,25 +268,27 @@ all() ->
groups() ->
[{P, [P], Ts} || Ts <- [tc(tc())], P <- [shuffle, parallel]]
++
- [{?util:name([T,R,D,A,C,S,SS,ST,CS]),
+ [{?util:name([T,CE,D,SE,SD,SC,S,SS,ST,CS]),
[],
[{group, if S -> shuffle; not S -> parallel end}]}
- || T <- ?TRANSPORTS,
- R <- ?ENCODINGS,
- D <- ?RFCS,
- A <- ?ENCODINGS,
- C <- ?CONTAINERS,
- S <- ?STRING_DECODES,
+ || T <- ?TRANSPORTS,
+ CE <- ?ENCODINGS,
+ D <- ?RFCS,
+ SE <- ?ENCODINGS,
+ SD <- ?DECODINGS,
+ SC <- ?CONTAINERS,
+ S <- ?STRING_DECODES,
SS <- ?SENDERS,
ST <- ?CALLBACKS,
CS <- ?SENDERS]
++
- [{T, [], groups([[T,R,D,A,C,S,SS,ST,CS]
- || R <- ?ENCODINGS,
- D <- ?RFCS,
- A <- ?ENCODINGS,
- C <- ?CONTAINERS,
- S <- ?STRING_DECODES,
+ [{T, [], groups([[T,CE,D,SE,SD,SC,S,SS,ST,CS]
+ || CE <- ?ENCODINGS,
+ D <- ?RFCS,
+ SE <- ?ENCODINGS,
+ SD <- ?DECODINGS,
+ SC <- ?CONTAINERS,
+ S <- ?STRING_DECODES,
SS <- ?SENDERS,
ST <- ?CALLBACKS,
CS <- ?SENDERS,
@@ -292,7 +298,7 @@ groups() ->
[{traffic, [], [{group, T} || T <- ?TRANSPORTS]}].
%groups(_) -> %% debug
-% Name = [sctp,record,rfc6733,record,pkt,false,false,false,false],
+% Name = [tcp,record,rfc6733,record,map,pkt,false,false,false,false],
% [{group, ?util:name(Name)}];
groups(Names) ->
[{group, ?util:name(L)} || L <- Names].
@@ -331,18 +337,19 @@ init_per_group(sctp = Name, Config) ->
init_per_group(Name, Config) ->
Nas = proplists:get_value(rfc4005, Config, false),
case ?util:name(Name) of
- [_,_,D,_,_,_, _, _, _] when D == rfc4005, true /= Nas ->
+ [_,_,D,_,_,_,_,_,_,_] when D == rfc4005, true /= Nas ->
{skip, rfc4005};
- [T,R,D,A,C,S,SS,ST,CS] ->
+ [T,CE,D,SE,SD,SC,S,SS,ST,CS] ->
G = #group{transport = T,
strings = S,
client_service = [$C|?util:unique_string()],
- client_encoding = R,
+ client_encoding = CE,
client_dict = appdict(D),
client_sender = CS,
server_service = [$S|?util:unique_string()],
- server_encoding = A,
- server_container = C,
+ server_decoding = SD,
+ server_encoding = SE,
+ server_container = SC,
server_sender = SS,
server_throttle = ST},
%% Limit the number of testcase, since the number of
@@ -452,9 +459,11 @@ start(_Config) ->
start_services(Config) ->
#group{strings = S,
client_service = CN,
- server_service = SN}
+ server_service = SN,
+ server_decoding = SD}
= group(Config),
- ok = diameter:start_service(SN, ?SERVICE(SN, S)),
+ ok = diameter:start_service(SN, [{record_decode, SD}
+ | ?SERVICE(SN, S)]),
ok = diameter:start_service(CN, [{sequence, ?CLIENT_MASK}
| ?SERVICE(CN, S)]).
@@ -480,12 +489,13 @@ add_transports(Config) ->
[T, {sender, CS}],
LRef,
[{id, Id}
- | client_apps(D, [{'Origin-State-Id', origin(Id)}])])
- || A <- ?ENCODINGS,
+ | client_apps(R, [{'Origin-State-Id', origin(Id)}])])
+ || D <- ?DECODINGS,
+ E <- ?ENCODINGS,
C <- ?CONTAINERS,
- D <- ?RFCS,
- D /= rfc4005 orelse have_nas(),
- Id <- [{A,C}]],
+ R <- ?RFCS,
+ R /= rfc4005 orelse have_nas(),
+ Id <- [{D,E,C}]],
%% The server uses the client's Origin-State-Id to decide how to
%% answer.
?util:write_priv(Config, "transport", [LRef | Cs]).
@@ -772,10 +782,6 @@ send_invalid_avp_length(Config) ->
'Result-Code' := ?INVALID_AVP_LENGTH,
'Origin-Host' := _,
'Origin-Realm' := _,
- 'User-Name' := _,
- 'Class' := _,
- 'Error-Message' := _,
- 'Error-Reporting-Host' := _,
'Failed-AVP' := Avps}
= call(Config, Req),
[[_]] = failed_avps(Avps, Config).
@@ -1050,21 +1056,30 @@ call(Config, Req, Opts) ->
msg(Req, ReqEncoding, Dict0),
[{extra, [{Name, Group}, diameter_lib:now()]} | Opts]).
-origin({A,C}) ->
- 2*codec(A) + container(C);
+origin({D,E,C}) ->
+ 8*decode(D) + 2*encode(E) + container(C);
origin(N) ->
- {codec(N div 2), container(N rem 2)}.
+ {decode(N bsr 3), encode((N bsr 1) rem 4), container(N rem 2)}.
%% Map atoms. The atoms are part of (constructed) group names, so it's
%% good that they're readable.
-codec(record) -> 0;
-codec(list) -> 1;
-codec(map) -> 2;
-codec(0) -> record;
-codec(1) -> list;
-codec(2) -> map.
+decode(true) -> 0; %% record
+decode(list) -> 1;
+decode(map) -> 2;
+decode(false) -> 3;
+decode(0) -> true;
+decode(1) -> list;
+decode(2) -> map;
+decode(3) -> false.
+
+encode(record) -> 0;
+encode(list) -> 1;
+encode(map) -> 2;
+encode(0) -> record;
+encode(1) -> list;
+encode(2) -> map.
container(pkt) -> 0;
container(msg) -> 1;
@@ -1091,6 +1106,46 @@ msg([H|T], map, _) ->
msg(Msg, _, _) ->
Msg.
+to_map(map, #diameter_packet{msg = Msg})
+ when is_map(Msg) ->
+ Msg;
+
+to_map(list, #diameter_packet{msg = [MsgName | Avps]}) ->
+ maps:put(':name', MsgName, maps:from_list(Avps));
+
+to_map(true, #diameter_packet{header = H, msg = Rec}) ->
+ rec_to_map(Rec, dict(H));
+
+%% No record decode: do it ourselves.
+to_map(false, #diameter_packet{header = H,
+ msg = false,
+ bin = Bin}) ->
+ Opts = #{record_decode => map,
+ string_decode => false,
+ strict_mbit => true,
+ rfc => 6733},
+ #diameter_packet{msg = Msg}
+ = diameter_codec:decode(dict(H), Opts, Bin),
+ Msg.
+
+dict(#diameter_header{application_id = Id,
+ cmd_code = Code}) ->
+ if Id == 1 ->
+ nas4005;
+ Code == 271 ->
+ diameter_gen_base_accounting;
+ true ->
+ diameter_gen_base_rfc3588
+ end.
+
+rec_to_map(Rec, Dict) ->
+ [R | Vs] = Dict:'#get-'(Rec),
+ maps:put(':name',
+ Dict:rec2msg(R),
+ maps:from_list([T || {_,V} = T <- Vs,
+ V /= undefined,
+ V /= []])).
+
appdict(rfc4005) ->
nas4005;
appdict(D) ->
@@ -1177,10 +1232,11 @@ pick_peer(Peers, _, [$C|_], _State, {send_detach, Group}, _, {_,_}) ->
find(Group, Peers).
find(#group{client_service = CN,
- server_encoding = A,
+ server_decoding = D,
+ server_encoding = E,
server_container = C},
[_|_] = Peers) ->
- Id = {A,C},
+ Id = {D,E,C},
[P] = [P || P <- Peers, id(Id, P, CN)],
{ok, P}.
@@ -1441,12 +1497,7 @@ answer(Pkt, Req, _Peer, Name, #group{client_dict = Dict0}) ->
ApplId = app(Req, Name, Dict0),
#diameter_header{application_id = ApplId} = H, %% assert
Dict = dict(Ans, Dict0),
- [R | Vs] = Dict:'#get-'(answer(Ans, Es, Name)),
- maps:put(':name',
- Dict:rec2msg(R),
- maps:from_list([T || {_,V} = T <- Vs,
- V /= undefined,
- V /= []])).
+ rec_to_map(answer(Ans, Es, Name), Dict).
%% Missing Result-Code and inappropriate Experimental-Result-Code.
answer(Rec, Es, send_experimental_result) ->
@@ -1486,7 +1537,8 @@ handle_error(Reason, _Req, [$C|_], _Peer, _, _Time) ->
%% Note that diameter will set Result-Code and Failed-AVPs if
%% #diameter_packet.errors is non-null.
-handle_request(#diameter_packet{header = H, msg = M, avps = As},
+handle_request(#diameter_packet{header = H, avps = As}
+ = Pkt,
_,
{_Ref, Caps}) ->
#diameter_header{end_to_end_id = EI,
@@ -1496,14 +1548,15 @@ handle_request(#diameter_packet{header = H, msg = M, avps = As},
V = EI bsr B, %% assert
V = HI bsr B, %%
#diameter_caps{origin_state_id = {_,[Id]}} = Caps,
- wrap(origin(Id), H, request(nas_to_base(M, H), [H|As], Caps)).
+ {D,_,_} = T = origin(Id),
+ wrap(T, H, request(to_map(D, Pkt), [H|As], Caps)).
-wrap(T, H, {Tag, Action, Post}) ->
- {Tag, wrap(T, H, Action), Post};
+wrap(Id, H, {Tag, Action, Post}) ->
+ {Tag, wrap(Id, H, Action), Post};
wrap(_, _, {reply, [#diameter_header{} | _]} = T) ->
T;
-wrap({A,C}, H, {reply, Ans}) ->
- Msg = msg(Ans, A, diameter_gen_base_rfc3588),
+wrap({_,E,C}, H, {reply, Ans}) ->
+ Msg = msg(Ans, E, diameter_gen_base_rfc3588),
wrap(C, H, {reply, base_to_nas(Msg, H)});
wrap(pkt, _, {reply, Ans})
when not is_record(Ans, diameter_packet) ->
@@ -1511,28 +1564,6 @@ wrap(pkt, _, {reply, Ans})
wrap(_, _, T) ->
T.
-%% nas_to_base/1
-%%
-%% Map an RFC 4005 message to RFC 3588, to return the same answer in
-%% both cases.
-
-nas_to_base(Rec, #diameter_header{application_id = 1}) ->
- [R | Values] = nas4005:'#get-'(Rec),
- "nas_" ++ Name = ?L(R),
- {D, RN} = case Name of
- "ACR" ->
- {diameter_gen_base_accounting,
- diameter_base_accounting_ACR};
- _ ->
- {diameter_gen_base_rfc3588,
- ?A("diameter_base_" ++ Name)}
- end,
- Fs = D:'#info-'(RN),
- D:'#new-'([RN | [T || {F,_} = T <- Values, lists:member(F, Fs)]]);
-
-nas_to_base(Rec, _) ->
- Rec.
-
%% base_to_nas/2
base_to_nas(#diameter_packet{msg = Msg} = Pkt, H) ->
@@ -1561,7 +1592,8 @@ base_to_nas(Msg, _) ->
%% request/3
%% send_experimental_result
-request(#diameter_base_accounting_ACR{'Accounting-Record-Number' = 5},
+request(#{':name' := 'ACR',
+ 'Accounting-Record-Number' := 5},
[Hdr | Avps],
#diameter_caps{origin_host = {OH, _},
origin_realm = {OR, _}}) ->
@@ -1594,14 +1626,16 @@ request(Msg, _Avps, Caps) ->
%% request/2
%% send_nok
-request(#diameter_base_accounting_ACR{'Accounting-Record-Number' = 0},
+request(#{':name' := 'ACR',
+ 'Accounting-Record-Number' := 0},
_) ->
{eval_packet, {protocol_error, ?INVALID_AVP_BITS}, [fun log/2, invalid]};
%% send_bad_answer
-request(#diameter_base_accounting_ACR{'Session-Id' = SId,
- 'Accounting-Record-Type' = RT,
- 'Accounting-Record-Number' = 2 = RN},
+request(#{':name' := '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},
@@ -1615,9 +1649,10 @@ request(#diameter_base_accounting_ACR{'Session-Id' = SId,
msg = Ans}};
%% send_eval
-request(#diameter_base_accounting_ACR{'Session-Id' = SId,
- 'Accounting-Record-Type' = RT,
- 'Accounting-Record-Number' = 3 = RN},
+request(#{':name' := 'ACR',
+ 'Session-Id' := SId,
+ 'Accounting-Record-Type' := RT,
+ 'Accounting-Record-Number' := 3 = RN},
#diameter_caps{origin_host = {OH, _},
origin_realm = {OR, _}}) ->
Ans = ['ACA', {'Result-Code', ?SUCCESS},
@@ -1629,9 +1664,10 @@ request(#diameter_base_accounting_ACR{'Session-Id' = SId,
{eval, {reply, Ans}, {erlang, now, []}};
%% send_ok
-request(#diameter_base_accounting_ACR{'Session-Id' = SId,
- 'Accounting-Record-Type' = RT,
- 'Accounting-Record-Number' = 1 = RN},
+request(#{':name' := 'ACR',
+ 'Session-Id' := SId,
+ 'Accounting-Record-Type' := RT,
+ 'Accounting-Record-Number' := 1 = RN},
#diameter_caps{origin_host = {OH, _},
origin_realm = {OR, _}}) ->
{reply, ['ACA', {'Result-Code', ?SUCCESS},
@@ -1642,7 +1678,8 @@ request(#diameter_base_accounting_ACR{'Session-Id' = SId,
{'Accounting-Record-Number', RN}]};
%% send_protocol_error
-request(#diameter_base_accounting_ACR{'Accounting-Record-Number' = 4},
+request(#{':name' := 'ACR',
+ 'Accounting-Record-Number' := 4},
#diameter_caps{origin_host = {OH, _},
origin_realm = {OR, _}}) ->
Ans = ['answer-message', {'Result-Code', ?TOO_BUSY},
@@ -1650,40 +1687,46 @@ request(#diameter_base_accounting_ACR{'Accounting-Record-Number' = 4},
{'Origin-Realm', OR}],
{reply, Ans};
-request(#diameter_base_ASR{'Session-Id' = SId,
- 'AVP' = Avps},
+request(#{':name' := 'ASR',
+ 'Session-Id' := SId}
+ = Req,
#diameter_caps{origin_host = {OH, _},
origin_realm = {OR, _}}) ->
{reply, ['ASA', {'Result-Code', ?SUCCESS},
{'Session-Id', SId},
{'Origin-Host', OH},
{'Origin-Realm', OR},
- {'AVP', Avps}]};
+ {'AVP', maps:get('AVP', Req, [])}]};
%% send_invalid_reject
-request(#diameter_base_STR{'Termination-Cause' = ?USER_MOVED},
+request(#{':name' := 'STR',
+ 'Termination-Cause' := ?USER_MOVED},
_Caps) ->
{protocol_error, ?TOO_BUSY};
%% send_noreply
-request(#diameter_base_STR{'Termination-Cause' = T},
+request(#{':name' := 'STR',
+ 'Termination-Cause' := T},
_Caps)
when T /= ?LOGOUT ->
discard;
%% send_destination_5
-request(#diameter_base_STR{'Destination-Realm' = R},
+request(#{':name' := 'STR',
+ 'Destination-Realm' := R},
#diameter_caps{origin_realm = {OR, _}})
when R /= undefined, R /= OR ->
{protocol_error, ?REALM_NOT_SERVED};
%% send_destination_6
-request(#diameter_base_STR{'Destination-Host' = [H]},
+request(#{':name' := 'STR',
+ 'Destination-Host' := [H]},
#diameter_caps{origin_host = {OH, _}})
when H /= OH ->
{protocol_error, ?UNABLE_TO_DELIVER};
-request(#diameter_base_STR{'Session-Id' = SId},
+request(#{':name' := 'STR',
+ 'Session-Id' := SId},
#diameter_caps{origin_host = {OH, _},
origin_realm = {OR, _}}) ->
{reply, ['STA', {'Result-Code', ?SUCCESS},
@@ -1692,7 +1735,7 @@ request(#diameter_base_STR{'Session-Id' = SId},
{'Origin-Realm', OR}]};
%% send_error/send_timeout
-request(#diameter_base_RAR{}, _Caps) ->
+request(#{':name' := 'RAR'}, _Caps) ->
receive after 2000 -> {protocol_error, ?TOO_BUSY} end.
%% message/3
--
cgit v1.2.3
From df12f634bec4b784f4c8d16846f2c24297b0e1ac Mon Sep 17 00:00:00 2001
From: Anders Svensson
Date: Fri, 7 Jul 2017 23:58:19 +0200
Subject: Create fewer client connections in traffic suite
One for each server decoding/encoding/container combination is overkill.
Just want a few from which one can be chosen in the pick_peer callback.
---
lib/diameter/test/diameter_traffic_SUITE.erl | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl
index 47f83676bb..adf8bf4d66 100644
--- a/lib/diameter/test/diameter_traffic_SUITE.erl
+++ b/lib/diameter/test/diameter_traffic_SUITE.erl
@@ -472,6 +472,8 @@ add_transports(Config) ->
client_service = CN,
client_sender = CS,
server_service = SN,
+ server_encoding = SE,
+ server_container = SC,
server_sender = SS,
server_throttle = ST}
= group(Config),
@@ -490,12 +492,10 @@ add_transports(Config) ->
LRef,
[{id, Id}
| client_apps(R, [{'Origin-State-Id', origin(Id)}])])
- || D <- ?DECODINGS,
- E <- ?ENCODINGS,
- C <- ?CONTAINERS,
+ || D <- ?DECODINGS, %% for multiple candidate peers
R <- ?RFCS,
R /= rfc4005 orelse have_nas(),
- Id <- [{D,E,C}]],
+ Id <- [{D,SE,SC}]],
%% The server uses the client's Origin-State-Id to decide how to
%% answer.
?util:write_priv(Config, "transport", [LRef | Cs]).
--
cgit v1.2.3
From 55e65b262cdf0b794ab443928676720a323cf6b0 Mon Sep 17 00:00:00 2001
From: Anders Svensson
Date: Sat, 8 Jul 2017 00:48:07 +0200
Subject: Rename record_decode -> decode_format
{record_decode, map} is a bit too quirky.
---
lib/diameter/doc/src/diameter.xml | 48 +++++++++++-----------
lib/diameter/doc/src/diameter_codec.xml | 2 +-
lib/diameter/src/base/diameter.erl | 6 ++-
lib/diameter/src/base/diameter_codec.erl | 2 +-
lib/diameter/src/base/diameter_config.erl | 10 ++---
lib/diameter/src/base/diameter_gen.erl | 4 +-
lib/diameter/src/base/diameter_peer_fsm.erl | 6 +--
lib/diameter/src/base/diameter_service.erl | 2 +-
lib/diameter/src/base/diameter_traffic.erl | 6 +--
lib/diameter/src/base/diameter_watchdog.erl | 6 +--
lib/diameter/test/diameter_codec_SUITE.erl | 2 +-
.../diameter_test_unknown.erl | 2 +-
lib/diameter/test/diameter_codec_test.erl | 2 +-
lib/diameter/test/diameter_traffic_SUITE.erl | 14 +++----
14 files changed, 57 insertions(+), 55 deletions(-)
diff --git a/lib/diameter/doc/src/diameter.xml b/lib/diameter/doc/src/diameter.xml
index e525ab3345..a7f001e096 100644
--- a/lib/diameter/doc/src/diameter.xml
+++ b/lib/diameter/doc/src/diameter.xml
@@ -797,6 +797,29 @@ be matched by corresponding &capability; configuration, of
+
+
+{decode_format, record | list | map | false}
+-
+
+The type of decoded messages and grouped AVPs in the msg field
+of diameter_packet records and value field of diameter_avp
+records respectively.
+If false then the fields are set this value.
+See also &codec_message;.
+
+
+Defaults to record.
+
+
+
+AVPs are decoded into a list of diameter_avp records in avps
+field of diameter_packet records independently of
+decode_format.
+
+
+
+
{incoming_maxlen, 0..16777215}
-
@@ -969,31 +992,6 @@ occur in the message in question.
-
-
-{record_decode, boolean() | list | map}
--
-
-Whether or not to decode message and grouped AVPs to records in the
-msg field of diameter_packet records and value field of
-diameter_avp records respectively, or to an alternate format.
-If false then the fields are set to the same value.
-See also &codec_message;.
-
-
-Defaults to true.
-
-
-
-Disabling the record is useful for applications in which the records
-aren't used/needed.
-AVP values are available in the avps field of
-diameter_packet records regardless of whether or not there is a record
-decode.
-
-
-
-
{string_decode, boolean()}
-
diff --git a/lib/diameter/doc/src/diameter_codec.xml b/lib/diameter/doc/src/diameter_codec.xml
index 6262dbf00d..4df8e788b7 100644
--- a/lib/diameter/doc/src/diameter_codec.xml
+++ b/lib/diameter/doc/src/diameter_codec.xml
@@ -244,7 +244,7 @@ file) and whose tail is a list of {AvpName, AvpValues} pairs,
or as a map with values keyed on AVP names and the message name in key
:name.
The format at decode is determined by &mod_service_opt;
-record_decode.
+decode_format.
Any of the formats is accepted at encode.
diff --git a/lib/diameter/src/base/diameter.erl b/lib/diameter/src/base/diameter.erl
index b033632c47..75deaad511 100644
--- a/lib/diameter/src/base/diameter.erl
+++ b/lib/diameter/src/base/diameter.erl
@@ -47,6 +47,7 @@
stop/0]).
-export_type([evaluable/0,
+ decode_format/0,
restriction/0,
message_length/0,
remotes/0,
@@ -330,6 +331,9 @@ call(SvcName, App, Message) ->
-type message_length()
:: 0..16#FFFFFF.
+-type decode_format()
+ :: record | list | map | false.
+
%% Options passed to start_service/2
-type service_opt()
@@ -338,7 +342,7 @@ call(SvcName, App, Message) ->
| {restrict_connections, restriction()}
| {sequence, sequence() | evaluable()}
| {share_peers, remotes()}
- | {record_decode, boolean() | list | map}
+ | {decode_format, decode_format()}
| {string_decode, boolean()}
| {strict_mbit, boolean()}
| {incoming_maxlen, message_length()}
diff --git a/lib/diameter/src/base/diameter_codec.erl b/lib/diameter/src/base/diameter_codec.erl
index 9043af145e..275e80b9bb 100644
--- a/lib/diameter/src/base/diameter_codec.erl
+++ b/lib/diameter/src/base/diameter_codec.erl
@@ -290,7 +290,7 @@ rec2msg(Mod, Rec) ->
%% longer *the* decode.
decode(Mod, Pkt) ->
- Opts = #{record_decode => true,
+ Opts = #{decode_format => record,
string_decode => true,
strict_mbit => true,
rfc => 6733},
diff --git a/lib/diameter/src/base/diameter_config.erl b/lib/diameter/src/base/diameter_config.erl
index 8f958a67b4..09018308d5 100644
--- a/lib/diameter/src/base/diameter_config.erl
+++ b/lib/diameter/src/base/diameter_config.erl
@@ -713,7 +713,7 @@ make_config(SvcName, Opts) ->
{nodes, restrict_connections},
{16#FFFFFF, incoming_maxlen},
{true, strict_mbit},
- {true, record_decode},
+ {record, decode_format},
{true, string_decode},
{[], spawn_opt}]),
@@ -757,7 +757,7 @@ opt(K, false = B)
K == monitor;
K == restrict_connections;
K == strict_mbit;
- K == record_decode;
+ K == decode_format;
K == string_decode ->
B;
@@ -765,12 +765,12 @@ opt(K, true = B)
when K == share_peers;
K == use_shared_peers;
K == strict_mbit;
- K == record_decode;
K == string_decode ->
B;
-opt(record_decode, T)
- when T == list;
+opt(decode_format, T)
+ when T == record;
+ T == list;
T == map ->
T;
diff --git a/lib/diameter/src/base/diameter_gen.erl b/lib/diameter/src/base/diameter_gen.erl
index 2381b73d07..239d4a535f 100644
--- a/lib/diameter/src/base/diameter_gen.erl
+++ b/lib/diameter/src/base/diameter_gen.erl
@@ -178,7 +178,7 @@ enc_AVP(_Name, {_Dict, _AvpName, _Data} = T, Opts, _) ->
-> {parent_record(), [avp()], Failed}
when Failed :: [{5000..5999, #diameter_avp{}}].
-decode_avps(Name, Recs, #{module := Mod, record_decode := Fmt} = Opts) ->
+decode_avps(Name, Recs, #{module := Mod, decode_format := Fmt} = Opts) ->
{Avps, {Rec, AM, Failed}}
= mapfoldl(fun(T,A) -> decode(Name, Opts, Mod, T, A) end,
{newrec(Mod, Name, Fmt), #{}, []},
@@ -749,7 +749,7 @@ empty(Name, #{module := Mod} = Opts) ->
newrec(_, _, false = No) ->
No;
-newrec(Mod, Name, true) ->
+newrec(Mod, Name, record) ->
newrec(Mod, Name);
newrec(_, Name, _) ->
diff --git a/lib/diameter/src/base/diameter_peer_fsm.erl b/lib/diameter/src/base/diameter_peer_fsm.erl
index f2fbb70270..abf948593f 100644
--- a/lib/diameter/src/base/diameter_peer_fsm.erl
+++ b/lib/diameter/src/base/diameter_peer_fsm.erl
@@ -128,7 +128,7 @@
%% outgoing DPR; boolean says whether or not
%% the request was sent explicitly with
%% diameter:call/4.
- codec :: #{record_decode := true,
+ codec :: #{decode_format := record,
string_decode := boolean(),
strict_mbit := boolean(),
rfc := 3588 | 6733,
@@ -254,13 +254,13 @@ i({Ack, WPid, {M, Ref} = T, Opts, {SvcOpts, Nodes, Dict0, Svc}}) ->
length_errors = LengthErr,
strict = Strictness,
incoming_maxlen = Maxlen,
- codec = maps:with([record_decode,
+ codec = maps:with([decode_format,
string_decode,
strict_mbit,
rfc,
ordered_encode],
SvcOpts#{ordered_encode => false,
- record_decode => true})}.
+ decode_format => record})}.
%% The transport returns its local ip addresses so that different
%% transports on the same service can use different local addresses.
%% The local addresses are put into Host-IP-Address avps here when
diff --git a/lib/diameter/src/base/diameter_service.erl b/lib/diameter/src/base/diameter_service.erl
index 7f7e3e3a3f..43be4d889a 100644
--- a/lib/diameter/src/base/diameter_service.erl
+++ b/lib/diameter/src/base/diameter_service.erl
@@ -113,7 +113,7 @@
restrict_connections := diameter:restriction(),
incoming_maxlen := diameter:message_length(),
strict_mbit := boolean(),
- record_decode := boolean() | map | list,
+ decode_format := diameter:decode_format(),
string_decode := boolean(),
spawn_opt := list() | {module(), atom(), list()}}}).
diff --git a/lib/diameter/src/base/diameter_traffic.erl b/lib/diameter/src/base/diameter_traffic.erl
index 6594994cfa..f684f60cb7 100644
--- a/lib/diameter/src/base/diameter_traffic.erl
+++ b/lib/diameter/src/base/diameter_traffic.erl
@@ -76,7 +76,7 @@
service_name :: diameter:service_name(),
apps :: [#diameter_app{}],
sequence :: diameter:sequence(),
- codec :: #{record_decode := boolean() | map | list,
+ codec :: #{decode_format := diameter:decode_format(),
string_decode := boolean(),
strict_mbit := boolean(),
incoming_maxlen := diameter:message_length()}}).
@@ -103,7 +103,7 @@ make_recvdata([SvcName, PeerT, Apps, SvcOpts | _]) ->
peerT = PeerT,
apps = Apps,
sequence = Mask,
- codec = maps:with([record_decode,
+ codec = maps:with([decode_format,
string_decode,
strict_mbit,
ordered_encode,
@@ -1976,7 +1976,7 @@ choose(false, _, X) -> X.
%% Decode options sufficient for AVP extraction.
decode_opts(Dict) ->
- #{record_decode => true,
+ #{decode_format => record,
string_decode => false,
strict_mbit => false,
failed_avp => false,
diff --git a/lib/diameter/src/base/diameter_watchdog.erl b/lib/diameter/src/base/diameter_watchdog.erl
index c3dc8c3bf0..60baf1e8a4 100644
--- a/lib/diameter/src/base/diameter_watchdog.erl
+++ b/lib/diameter/src/base/diameter_watchdog.erl
@@ -72,7 +72,7 @@
restrict := boolean(),
suspect := non_neg_integer(), %% OKAY -> SUSPECT
okay := non_neg_integer()}, %% REOPEN -> OKAY
- codec :: #{record_decode := false,
+ codec :: #{decode_format := false,
string_decode := false,
strict_mbit := boolean(),
failed_avp := false,
@@ -136,7 +136,7 @@ i({Ack, T, Pid, {Opts,
putr(restart, {T, Opts, Svc, SvcOpts}), %% save seeing it in trace
putr(dwr, dwr(Caps)), %%
Nodes = restrict_nodes(Restrict),
- CodecKeys = [record_decode,
+ CodecKeys = [decode_format,
string_decode,
strict_mbit,
incoming_maxlen,
@@ -157,7 +157,7 @@ i({Ack, T, Pid, {Opts,
suspect => 1,
okay => 3},
Opts)),
- codec = maps:with(CodecKeys, SvcOpts#{record_decode := false,
+ codec = maps:with(CodecKeys, SvcOpts#{decode_format := false,
string_decode := false,
ordered_encode => false})}.
diff --git a/lib/diameter/test/diameter_codec_SUITE.erl b/lib/diameter/test/diameter_codec_SUITE.erl
index 31332537e9..c79b642c09 100644
--- a/lib/diameter/test/diameter_codec_SUITE.erl
+++ b/lib/diameter/test/diameter_codec_SUITE.erl
@@ -292,7 +292,7 @@ recode(Msg, Dict) ->
opts(Mod) ->
#{dictionary => Mod,
- record_decode => true,
+ decode_format => record,
string_decode => false,
strict_mbit => true,
rfc => 6733,
diff --git a/lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl b/lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl
index fe602c9ee5..735339ebb9 100644
--- a/lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl
+++ b/lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl
@@ -78,7 +78,7 @@ dec('BR', #diameter_packet
opts(Mod) ->
#{dictionary => Mod,
- record_decode => true,
+ decode_format => record,
string_decode => true,
strict_mbit => true,
rfc => 6733,
diff --git a/lib/diameter/test/diameter_codec_test.erl b/lib/diameter/test/diameter_codec_test.erl
index 7595e7edfc..22fb0550ea 100644
--- a/lib/diameter/test/diameter_codec_test.erl
+++ b/lib/diameter/test/diameter_codec_test.erl
@@ -219,7 +219,7 @@ opts(Mod) ->
dictionary => Mod}.
opts() ->
- #{record_decode => true,
+ #{decode_format => record,
string_decode => true,
strict_mbit => true,
rfc => 6733,
diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl
index adf8bf4d66..aa0098ccd6 100644
--- a/lib/diameter/test/diameter_traffic_SUITE.erl
+++ b/lib/diameter/test/diameter_traffic_SUITE.erl
@@ -142,8 +142,8 @@
%% How to construct outgoing messages.
-define(ENCODINGS, [list, record, map]).
-%% How to set record_decode.
--define(DECODINGS, [true, false, map, list]).
+%% How to decode incoming messages.
+-define(DECODINGS, [record, false, map, list]).
%% How to send answers, in a diameter_packet or not.
-define(CONTAINERS, [pkt, msg]).
@@ -462,7 +462,7 @@ start_services(Config) ->
server_service = SN,
server_decoding = SD}
= group(Config),
- ok = diameter:start_service(SN, [{record_decode, SD}
+ ok = diameter:start_service(SN, [{decode_format, SD}
| ?SERVICE(SN, S)]),
ok = diameter:start_service(CN, [{sequence, ?CLIENT_MASK}
| ?SERVICE(CN, S)]).
@@ -1065,11 +1065,11 @@ origin(N) ->
%% Map atoms. The atoms are part of (constructed) group names, so it's
%% good that they're readable.
-decode(true) -> 0; %% record
+decode(record) -> 0;
decode(list) -> 1;
decode(map) -> 2;
decode(false) -> 3;
-decode(0) -> true;
+decode(0) -> record;
decode(1) -> list;
decode(2) -> map;
decode(3) -> false.
@@ -1113,14 +1113,14 @@ to_map(map, #diameter_packet{msg = Msg})
to_map(list, #diameter_packet{msg = [MsgName | Avps]}) ->
maps:put(':name', MsgName, maps:from_list(Avps));
-to_map(true, #diameter_packet{header = H, msg = Rec}) ->
+to_map(record, #diameter_packet{header = H, msg = Rec}) ->
rec_to_map(Rec, dict(H));
%% No record decode: do it ourselves.
to_map(false, #diameter_packet{header = H,
msg = false,
bin = Bin}) ->
- Opts = #{record_decode => map,
+ Opts = #{decode_format => map,
string_decode => false,
strict_mbit => true,
rfc => 6733},
--
cgit v1.2.3
From fa2f0572aa0604bf03d4d3eaa358719ffd877545 Mon Sep 17 00:00:00 2001
From: Anders Svensson
Date: Sat, 8 Jul 2017 02:06:11 +0200
Subject: Add decode_format record_from_map
Undocumented, for transforming a map decode to record.
The record decode becomes more expensive the larger the number of AVPs
in the message definition in question, since the record is recreated
each time an AVP value is set in it. The map decode can potentially do
better.
---
lib/diameter/src/base/diameter.erl | 6 +++++-
lib/diameter/src/base/diameter_config.erl | 3 ++-
lib/diameter/src/base/diameter_gen.erl | 13 +++++++++----
3 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/lib/diameter/src/base/diameter.erl b/lib/diameter/src/base/diameter.erl
index 75deaad511..85a54c8e61 100644
--- a/lib/diameter/src/base/diameter.erl
+++ b/lib/diameter/src/base/diameter.erl
@@ -332,7 +332,11 @@ call(SvcName, App, Message) ->
:: 0..16#FFFFFF.
-type decode_format()
- :: record | list | map | false.
+ :: record
+ | list
+ | map
+ | false
+ | record_from_map.
%% Options passed to start_service/2
diff --git a/lib/diameter/src/base/diameter_config.erl b/lib/diameter/src/base/diameter_config.erl
index 09018308d5..d591fa903e 100644
--- a/lib/diameter/src/base/diameter_config.erl
+++ b/lib/diameter/src/base/diameter_config.erl
@@ -771,7 +771,8 @@ opt(K, true = B)
opt(decode_format, T)
when T == record;
T == list;
- T == map ->
+ T == map;
+ T == record_from_map ->
T;
opt(restrict_connections, T)
diff --git a/lib/diameter/src/base/diameter_gen.erl b/lib/diameter/src/base/diameter_gen.erl
index 239d4a535f..78d8bd2fa3 100644
--- a/lib/diameter/src/base/diameter_gen.erl
+++ b/lib/diameter/src/base/diameter_gen.erl
@@ -186,7 +186,7 @@ decode_avps(Name, Recs, #{module := Mod, decode_format := Fmt} = Opts) ->
%% AM counts the number of top-level AVPs, which missing/4 then
%% uses when adding 5005 errors.
Arities = Mod:avp_arity(Name),
- {reformat(Rec, Arities, Fmt),
+ {reformat(Rec, Arities, Mod, Fmt),
Avps,
Failed ++ missing(Arities, Opts, Mod, AM)}.
@@ -760,12 +760,17 @@ newrec(_, Name, _) ->
newrec(Mod, Name) ->
Mod:'#new-'(Mod:name2rec(Name)).
-%% reformat/3
+%% reformat/4
-reformat(Map, Arities, list) ->
+reformat(Map, Arities, _Mod, list) ->
[{F,V} || {F,_} <- Arities, #{F := V} <- [Map]];
-reformat(Rec, _, _) ->
+reformat(Map, Arities, Mod, record_from_map) ->
+ #{':name' := Name} = Map,
+ RecName = Mod:name2rec(Name),
+ list_to_tuple([RecName | [maps:get(F, Map, def(A)) || {F,A} <- Arities]]);
+
+reformat(Rec, _, _, _) ->
Rec.
%% def/1
--
cgit v1.2.3
From 2984749c093cc4b599190e2dcdaad4335899ecd4 Mon Sep 17 00:00:00 2001
From: Anders Svensson
Date: Sat, 8 Jul 2017 02:17:42 +0200
Subject: Don't exercise client/server encoding independently in traffic suite
To reduce the number of config combinations that are tested. The
encoding is the format in which messages are provided to diameter for
encode (to binary), and if there is any difference in the end result
then the peer will detect this at decode, independently of its encoding
format.
---
lib/diameter/test/diameter_traffic_SUITE.erl | 36 +++++++++++++---------------
1 file changed, 16 insertions(+), 20 deletions(-)
diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl
index aa0098ccd6..eb2a9833f7 100644
--- a/lib/diameter/test/diameter_traffic_SUITE.erl
+++ b/lib/diameter/test/diameter_traffic_SUITE.erl
@@ -167,13 +167,12 @@
-record(group,
{transport,
strings,
+ encoding,
client_service,
- client_encoding,
client_dict,
client_sender,
server_service,
server_decoding,
- server_encoding,
server_container,
server_sender,
server_throttle}).
@@ -268,13 +267,12 @@ all() ->
groups() ->
[{P, [P], Ts} || Ts <- [tc(tc())], P <- [shuffle, parallel]]
++
- [{?util:name([T,CE,D,SE,SD,SC,S,SS,ST,CS]),
+ [{?util:name([T,E,D,SD,SC,S,SS,ST,CS]),
[],
[{group, if S -> shuffle; not S -> parallel end}]}
|| T <- ?TRANSPORTS,
- CE <- ?ENCODINGS,
+ E <- ?ENCODINGS,
D <- ?RFCS,
- SE <- ?ENCODINGS,
SD <- ?DECODINGS,
SC <- ?CONTAINERS,
S <- ?STRING_DECODES,
@@ -282,10 +280,9 @@ groups() ->
ST <- ?CALLBACKS,
CS <- ?SENDERS]
++
- [{T, [], groups([[T,CE,D,SE,SD,SC,S,SS,ST,CS]
- || CE <- ?ENCODINGS,
+ [{T, [], groups([[T,E,D,SD,SC,S,SS,ST,CS]
+ || E <- ?ENCODINGS,
D <- ?RFCS,
- SE <- ?ENCODINGS,
SD <- ?DECODINGS,
SC <- ?CONTAINERS,
S <- ?STRING_DECODES,
@@ -298,7 +295,7 @@ groups() ->
[{traffic, [], [{group, T} || T <- ?TRANSPORTS]}].
%groups(_) -> %% debug
-% Name = [tcp,record,rfc6733,record,map,pkt,false,false,false,false],
+% Name = [tcp,record,rfc6733,map,pkt,false,false,false,false],
% [{group, ?util:name(Name)}];
groups(Names) ->
[{group, ?util:name(L)} || L <- Names].
@@ -337,18 +334,17 @@ init_per_group(sctp = Name, Config) ->
init_per_group(Name, Config) ->
Nas = proplists:get_value(rfc4005, Config, false),
case ?util:name(Name) of
- [_,_,D,_,_,_,_,_,_,_] when D == rfc4005, true /= Nas ->
+ [_,_,D,_,_,_,_,_,_] when D == rfc4005, true /= Nas ->
{skip, rfc4005};
- [T,CE,D,SE,SD,SC,S,SS,ST,CS] ->
+ [T,E,D,SD,SC,S,SS,ST,CS] ->
G = #group{transport = T,
strings = S,
+ encoding = E,
client_service = [$C|?util:unique_string()],
- client_encoding = CE,
client_dict = appdict(D),
client_sender = CS,
server_service = [$S|?util:unique_string()],
server_decoding = SD,
- server_encoding = SE,
server_container = SC,
server_sender = SS,
server_throttle = ST},
@@ -469,10 +465,10 @@ start_services(Config) ->
add_transports(Config) ->
#group{transport = T,
+ encoding = E,
client_service = CN,
client_sender = CS,
server_service = SN,
- server_encoding = SE,
server_container = SC,
server_sender = SS,
server_throttle = ST}
@@ -495,7 +491,7 @@ add_transports(Config) ->
|| D <- ?DECODINGS, %% for multiple candidate peers
R <- ?RFCS,
R /= rfc4005 orelse have_nas(),
- Id <- [{D,SE,SC}]],
+ Id <- [{D,E,SC}]],
%% The server uses the client's Origin-State-Id to decide how to
%% answer.
?util:write_priv(Config, "transport", [LRef | Cs]).
@@ -1046,14 +1042,14 @@ call(Config, Req) ->
call(Config, Req, Opts) ->
Name = proplists:get_value(testcase, Config),
- #group{client_service = CN,
- client_encoding = ReqEncoding,
+ #group{encoding = Enc,
+ client_service = CN,
client_dict = Dict0}
= Group
= group(Config),
diameter:call(CN,
dict(Req, Dict0),
- msg(Req, ReqEncoding, Dict0),
+ msg(Req, Enc, Dict0),
[{extra, [{Name, Group}, diameter_lib:now()]} | Opts]).
origin({D,E,C}) ->
@@ -1231,9 +1227,9 @@ pick_peer(_Peers, _, [$C|_], _State, {send_nopeer, _}, _, ?EXTRA) ->
pick_peer(Peers, _, [$C|_], _State, {send_detach, Group}, _, {_,_}) ->
find(Group, Peers).
-find(#group{client_service = CN,
+find(#group{encoding = E,
+ client_service = CN,
server_decoding = D,
- server_encoding = E,
server_container = C},
[_|_] = Peers) ->
Id = {D,E,C},
--
cgit v1.2.3
From 6c30cae16dcb1dc320c51e38c5cc477d52b46078 Mon Sep 17 00:00:00 2001
From: Anders Svensson
Date: Mon, 10 Jul 2017 15:08:28 +0200
Subject: Randomly wrap answers in diameter_packet in transport suite
To reduce the number of combinations tested, as in the parent commit.
---
lib/diameter/test/diameter_traffic_SUITE.erl | 61 +++++++++++++---------------
1 file changed, 29 insertions(+), 32 deletions(-)
diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl
index eb2a9833f7..8533dcaf77 100644
--- a/lib/diameter/test/diameter_traffic_SUITE.erl
+++ b/lib/diameter/test/diameter_traffic_SUITE.erl
@@ -145,9 +145,6 @@
%% How to decode incoming messages.
-define(DECODINGS, [record, false, map, list]).
-%% How to send answers, in a diameter_packet or not.
--define(CONTAINERS, [pkt, msg]).
-
%% Which dictionary to use in the clients.
-define(RFCS, [rfc3588, rfc6733, rfc4005]).
@@ -173,7 +170,6 @@
client_sender,
server_service,
server_decoding,
- server_container,
server_sender,
server_throttle}).
@@ -267,24 +263,22 @@ all() ->
groups() ->
[{P, [P], Ts} || Ts <- [tc(tc())], P <- [shuffle, parallel]]
++
- [{?util:name([T,E,D,SD,SC,S,SS,ST,CS]),
+ [{?util:name([T,E,D,SD,S,SS,ST,CS]),
[],
[{group, if S -> shuffle; not S -> parallel end}]}
|| T <- ?TRANSPORTS,
E <- ?ENCODINGS,
D <- ?RFCS,
SD <- ?DECODINGS,
- SC <- ?CONTAINERS,
S <- ?STRING_DECODES,
SS <- ?SENDERS,
ST <- ?CALLBACKS,
CS <- ?SENDERS]
++
- [{T, [], groups([[T,E,D,SD,SC,S,SS,ST,CS]
+ [{T, [], groups([[T,E,D,SD,S,SS,ST,CS]
|| E <- ?ENCODINGS,
D <- ?RFCS,
SD <- ?DECODINGS,
- SC <- ?CONTAINERS,
S <- ?STRING_DECODES,
SS <- ?SENDERS,
ST <- ?CALLBACKS,
@@ -295,7 +289,7 @@ groups() ->
[{traffic, [], [{group, T} || T <- ?TRANSPORTS]}].
%groups(_) -> %% debug
-% Name = [tcp,record,rfc6733,map,pkt,false,false,false,false],
+% Name = [tcp,record,rfc6733,map,false,false,false,false],
% [{group, ?util:name(Name)}];
groups(Names) ->
[{group, ?util:name(L)} || L <- Names].
@@ -334,9 +328,9 @@ init_per_group(sctp = Name, Config) ->
init_per_group(Name, Config) ->
Nas = proplists:get_value(rfc4005, Config, false),
case ?util:name(Name) of
- [_,_,D,_,_,_,_,_,_] when D == rfc4005, true /= Nas ->
+ [_,_,D,_,_,_,_,_] when D == rfc4005, true /= Nas ->
{skip, rfc4005};
- [T,E,D,SD,SC,S,SS,ST,CS] ->
+ [T,E,D,SD,S,SS,ST,CS] ->
G = #group{transport = T,
strings = S,
encoding = E,
@@ -345,7 +339,6 @@ init_per_group(Name, Config) ->
client_sender = CS,
server_service = [$S|?util:unique_string()],
server_decoding = SD,
- server_container = SC,
server_sender = SS,
server_throttle = ST},
%% Limit the number of testcase, since the number of
@@ -469,7 +462,6 @@ add_transports(Config) ->
client_service = CN,
client_sender = CS,
server_service = SN,
- server_container = SC,
server_sender = SS,
server_throttle = ST}
= group(Config),
@@ -491,7 +483,7 @@ add_transports(Config) ->
|| D <- ?DECODINGS, %% for multiple candidate peers
R <- ?RFCS,
R /= rfc4005 orelse have_nas(),
- Id <- [{D,E,SC}]],
+ Id <- [{D,E}]],
%% The server uses the client's Origin-State-Id to decide how to
%% answer.
?util:write_priv(Config, "transport", [LRef | Cs]).
@@ -1052,11 +1044,11 @@ call(Config, Req, Opts) ->
msg(Req, Enc, Dict0),
[{extra, [{Name, Group}, diameter_lib:now()]} | Opts]).
-origin({D,E,C}) ->
- 8*decode(D) + 2*encode(E) + container(C);
+origin({D,E}) ->
+ 4*decode(D) + encode(E);
origin(N) ->
- {decode(N bsr 3), encode((N bsr 1) rem 4), container(N rem 2)}.
+ {decode(N bsr 2), encode(N rem 4)}.
%% Map atoms. The atoms are part of (constructed) group names, so it's
%% good that they're readable.
@@ -1077,11 +1069,6 @@ encode(0) -> record;
encode(1) -> list;
encode(2) -> map.
-container(pkt) -> 0;
-container(msg) -> 1;
-container(0) -> pkt;
-container(_) -> msg.
-
msg([H|_] = Msg, record = E, diameter_gen_base_rfc3588)
when H == 'ACR';
H == 'ACA' ->
@@ -1229,10 +1216,9 @@ pick_peer(Peers, _, [$C|_], _State, {send_detach, Group}, _, {_,_}) ->
find(#group{encoding = E,
client_service = CN,
- server_decoding = D,
- server_container = C},
+ server_decoding = D},
[_|_] = Peers) ->
- Id = {D,E,C},
+ Id = {D,E},
[P] = [P || P <- Peers, id(Id, P, CN)],
{ok, P}.
@@ -1544,22 +1530,33 @@ handle_request(#diameter_packet{header = H, avps = As}
V = EI bsr B, %% assert
V = HI bsr B, %%
#diameter_caps{origin_state_id = {_,[Id]}} = Caps,
- {D,_,_} = T = origin(Id),
+ {D,_} = T = origin(Id),
wrap(T, H, request(to_map(D, Pkt), [H|As], Caps)).
wrap(Id, H, {Tag, Action, Post}) ->
{Tag, wrap(Id, H, Action), Post};
+
wrap(_, _, {reply, [#diameter_header{} | _]} = T) ->
T;
-wrap({_,E,C}, H, {reply, Ans}) ->
- Msg = msg(Ans, E, diameter_gen_base_rfc3588),
- wrap(C, H, {reply, base_to_nas(Msg, H)});
-wrap(pkt, _, {reply, Ans})
- when not is_record(Ans, diameter_packet) ->
- {reply, #diameter_packet{msg = Ans}};
+
+wrap({_,E}, H, {reply, Ans}) ->
+ Msg = base_to_nas(msg(Ans, E, diameter_gen_base_rfc3588), H),
+ {reply, wrap(Msg)};
+
wrap(_, _, T) ->
T.
+%% Randomly wrap the answer in a diameter_packet.
+
+wrap(#diameter_packet{} = Pkt) ->
+ Pkt;
+
+wrap(Msg) ->
+ case rand:uniform(2) of
+ 1 -> #diameter_packet{msg = Msg};
+ 2 -> Msg
+ end.
+
%% base_to_nas/2
base_to_nas(#diameter_packet{msg = Msg} = Pkt, H) ->
--
cgit v1.2.3
From 58f9d631df0c256f7bc4ff3de2670b3b04e265f7 Mon Sep 17 00:00:00 2001
From: Anders Svensson
Date: Sat, 8 Jul 2017 09:35:59 +0200
Subject: Rearrange group names in traffic suite
For slightly better readability in the ct logs
---
lib/diameter/test/diameter_traffic_SUITE.erl | 28 ++++++++++++++--------------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl
index 8533dcaf77..100a4eebc9 100644
--- a/lib/diameter/test/diameter_traffic_SUITE.erl
+++ b/lib/diameter/test/diameter_traffic_SUITE.erl
@@ -263,25 +263,25 @@ all() ->
groups() ->
[{P, [P], Ts} || Ts <- [tc(tc())], P <- [shuffle, parallel]]
++
- [{?util:name([T,E,D,SD,S,SS,ST,CS]),
+ [{?util:name([T,R,E,D,S,ST,SS,CS]),
[],
[{group, if S -> shuffle; not S -> parallel end}]}
|| T <- ?TRANSPORTS,
+ R <- ?RFCS,
E <- ?ENCODINGS,
- D <- ?RFCS,
- SD <- ?DECODINGS,
+ D <- ?DECODINGS,
S <- ?STRING_DECODES,
- SS <- ?SENDERS,
ST <- ?CALLBACKS,
+ SS <- ?SENDERS,
CS <- ?SENDERS]
++
- [{T, [], groups([[T,E,D,SD,S,SS,ST,CS]
- || E <- ?ENCODINGS,
- D <- ?RFCS,
- SD <- ?DECODINGS,
+ [{T, [], groups([[T,R,E,D,S,ST,SS,CS]
+ || R <- ?RFCS,
+ E <- ?ENCODINGS,
+ D <- ?DECODINGS,
S <- ?STRING_DECODES,
- SS <- ?SENDERS,
ST <- ?CALLBACKS,
+ SS <- ?SENDERS,
CS <- ?SENDERS,
SS orelse CS])} %% avoid deadlock
|| T <- ?TRANSPORTS]
@@ -289,7 +289,7 @@ groups() ->
[{traffic, [], [{group, T} || T <- ?TRANSPORTS]}].
%groups(_) -> %% debug
-% Name = [tcp,record,rfc6733,map,false,false,false,false],
+% Name = [tcp,rfc6733,record,map,false,false,false,false],
% [{group, ?util:name(Name)}];
groups(Names) ->
[{group, ?util:name(L)} || L <- Names].
@@ -328,17 +328,17 @@ init_per_group(sctp = Name, Config) ->
init_per_group(Name, Config) ->
Nas = proplists:get_value(rfc4005, Config, false),
case ?util:name(Name) of
- [_,_,D,_,_,_,_,_] when D == rfc4005, true /= Nas ->
+ [_,R,_,_,_,_,_,_] when R == rfc4005, true /= Nas ->
{skip, rfc4005};
- [T,E,D,SD,S,SS,ST,CS] ->
+ [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(D),
+ client_dict = appdict(R),
client_sender = CS,
server_service = [$S|?util:unique_string()],
- server_decoding = SD,
+ server_decoding = D,
server_sender = SS,
server_throttle = ST},
%% Limit the number of testcase, since the number of
--
cgit v1.2.3
From e0603ba18a67c1ef33f60122fe6f00393c0c0203 Mon Sep 17 00:00:00 2001
From: Anders Svensson
Date: Thu, 13 Jul 2017 01:28:06 +0200
Subject: Tweak map-valued decode
Use the same [MsgName | Avps] representation as for the list decode, but
with Avps a map instead of a AVP name/values list. As a result, don't
set the message/AVP name on an additional key in the map, which felt a
bit odd. Messages are [MsgName :: atom() | map()], Grouped AVPs are just
map().
Fix at least one problem in the traffic suite along the way: with
decode_format false, the own decode in to_map/2 didn't know whether or
not to decode strings, resulting on some failures.
---
lib/diameter/doc/src/diameter.xml | 12 +-
lib/diameter/doc/src/diameter_codec.xml | 8 +-
lib/diameter/src/base/diameter_codec.erl | 7 +-
lib/diameter/src/base/diameter_gen.erl | 13 +-
lib/diameter/src/base/diameter_traffic.erl | 58 ++---
lib/diameter/test/diameter_traffic_SUITE.erl | 332 ++++++++++++---------------
6 files changed, 193 insertions(+), 237 deletions(-)
diff --git a/lib/diameter/doc/src/diameter.xml b/lib/diameter/doc/src/diameter.xml
index a7f001e096..43cb3a538c 100644
--- a/lib/diameter/doc/src/diameter.xml
+++ b/lib/diameter/doc/src/diameter.xml
@@ -539,7 +539,7 @@ that matches no peer.
The host and realm filters cause the Destination-Host
and Destination-Realm AVPs to be extracted from the
-outgoing request, assuming it to be a record-, list- or map-valued
+outgoing request, assuming it to be a record- or list-valued
&codec_message;, and assuming at most one of each AVP.
If this is not the case then the {host|realm, &dict_DiameterIdentity;}
filters must be used to achieve the desired result.
@@ -802,10 +802,16 @@ be matched by corresponding &capability; configuration, of
{decode_format, record | list | map | false}
-
-The type of decoded messages and grouped AVPs in the msg field
+The format of decoded messages and grouped AVPs in the msg field
of diameter_packet records and value field of diameter_avp
records respectively.
-If false then the fields are set this value.
+If record then a record whose definition is generated from the
+dictionary file in question.
+If list or map then a [Name | Avps] pair where
+Avps is either a list of AVP name/values pairs or a map keyed on
+AVP names respectively.
+If false then the representation is omitted and msg and
+value fields are set to false.
See also &codec_message;.
diff --git a/lib/diameter/doc/src/diameter_codec.xml b/lib/diameter/doc/src/diameter_codec.xml
index 4df8e788b7..0846334d23 100644
--- a/lib/diameter/doc/src/diameter_codec.xml
+++ b/lib/diameter/doc/src/diameter_codec.xml
@@ -230,7 +230,8 @@ header.
-message() = record() | list() | map()
+message() = record()
+ | maybe_improper_list()
-
The representation of a Diameter message as passed to
@@ -240,9 +241,8 @@ a message as defined in a dictionary file is encoded as a record with
one field for each component AVP.
Equivalently, a message can also be encoded as a list whose head is
the atom-valued message name (as specified in the relevant dictionary
-file) and whose tail is a list of {AvpName, AvpValues} pairs,
-or as a map with values keyed on AVP names and the message name in key
-:name.
+file) and whose tail is either a list of AVP name/values
+pairs or a map with values keyed on AVP names.
The format at decode is determined by &mod_service_opt;
decode_format.
Any of the formats is accepted at encode.
diff --git a/lib/diameter/src/base/diameter_codec.erl b/lib/diameter/src/base/diameter_codec.erl
index 275e80b9bb..9b21bf4141 100644
--- a/lib/diameter/src/base/diameter_codec.erl
+++ b/lib/diameter/src/base/diameter_codec.erl
@@ -275,9 +275,6 @@ rec2msg(_, [Name|_])
when is_atom(Name) ->
Name;
-rec2msg(_, #{':name' := Name}) ->
- Name;
-
rec2msg(Mod, Rec) ->
Mod:rec2msg(element(1, Rec)).
@@ -383,7 +380,9 @@ decode_avps(MsgName, Mod, AppMod, Opts, Pkt, Avps) -> %% ... or not
errors = Errors,
avps = As}.
-reformat(MsgName, Avps, #{decode_format := list}) ->
+reformat(MsgName, Avps, #{decode_format := T})
+ when T == map;
+ T == list ->
[MsgName | Avps];
reformat(_, Msg, _) ->
diff --git a/lib/diameter/src/base/diameter_gen.erl b/lib/diameter/src/base/diameter_gen.erl
index 78d8bd2fa3..597ec143a8 100644
--- a/lib/diameter/src/base/diameter_gen.erl
+++ b/lib/diameter/src/base/diameter_gen.erl
@@ -186,7 +186,7 @@ decode_avps(Name, Recs, #{module := Mod, decode_format := Fmt} = Opts) ->
%% AM counts the number of top-level AVPs, which missing/4 then
%% uses when adding 5005 errors.
Arities = Mod:avp_arity(Name),
- {reformat(Rec, Arities, Mod, Fmt),
+ {reformat(Name, Rec, Arities, Mod, Fmt),
Avps,
Failed ++ missing(Arities, Opts, Mod, AM)}.
@@ -752,8 +752,8 @@ newrec(_, _, false = No) ->
newrec(Mod, Name, record) ->
newrec(Mod, Name);
-newrec(_, Name, _) ->
- #{':name' => Name}.
+newrec(_, _, _) ->
+ #{}.
%% newrec/2
@@ -762,15 +762,14 @@ newrec(Mod, Name) ->
%% reformat/4
-reformat(Map, Arities, _Mod, list) ->
+reformat(_, Map, Arities, _Mod, list) ->
[{F,V} || {F,_} <- Arities, #{F := V} <- [Map]];
-reformat(Map, Arities, Mod, record_from_map) ->
- #{':name' := Name} = Map,
+reformat(Name, Map, Arities, Mod, record_from_map) ->
RecName = Mod:name2rec(Name),
list_to_tuple([RecName | [maps:get(F, Map, def(A)) || {F,A} <- Arities]]);
-reformat(Rec, _, _, _) ->
+reformat(_, Rec, _, _, _) ->
Rec.
%% def/1
diff --git a/lib/diameter/src/base/diameter_traffic.erl b/lib/diameter/src/base/diameter_traffic.erl
index f684f60cb7..e9c422d6ab 100644
--- a/lib/diameter/src/base/diameter_traffic.erl
+++ b/lib/diameter/src/base/diameter_traffic.erl
@@ -621,16 +621,10 @@ is_answer_message(#diameter_packet{msg = Msg}, Dict0) ->
is_answer_message([#diameter_header{is_request = R, is_error = E} | _], _) ->
E andalso not R;
-%% Message sent as a tagged avp/value list.
+%% Message sent as a map or tagged avp/value list.
is_answer_message([Name | _], _) ->
Name == 'answer-message';
-%% Message sent as a map.
-is_answer_message(Map, _)
- when is_map(Map) ->
- #{':name' := Name} = Map,
- Name == 'answer-message';
-
%% Message sent as a record.
is_answer_message(Rec, Dict) ->
try
@@ -875,15 +869,13 @@ reset(Msg, [RC | Avps], Dict) ->
%% set/3
-%% Reply as name and tuple list ...
+%% Reply as name/values list ...
+set([Name|As], Avps, _)
+ when is_map(As) ->
+ [Name | maps:merge(As, maps:from_list(Avps))];
set([_|_] = Ans, Avps, _) ->
Ans ++ Avps; %% Values nearer tail take precedence.
-%% ... a map ...
-set(Ans, Avps, _)
- when is_map(Ans) ->
- maps:merge(Ans, maps:from_list(Avps));
-
%% ... or record.
set(Rec, Avps, Dict) ->
Dict:'#set-'(Avps, Rec).
@@ -902,9 +894,6 @@ rc([MsgName | _], RC, Dict) ->
_ -> []
end;
-rc(#{':name' := Name}, RC, Dict) ->
- rc([Name], RC, Dict);
-
rc(Rec, RC, Dict) ->
rc([Dict:rec2msg(element(1, Rec))], RC, Dict).
@@ -937,10 +926,6 @@ failed(Msg, FailedAvp, Dict) ->
msg2rec([MsgName | _], Dict) ->
Dict:msg2rec(MsgName);
-%% ... map ...
-msg2rec(#{':name' := MsgName}, Dict) ->
- Dict:msg2rec(MsgName);
-
%% ... or record.
msg2rec(Rec, _) ->
element(1, Rec).
@@ -949,12 +934,11 @@ msg2rec(Rec, _) ->
%% Message as name/values list ...
values([_ | Avps], F, _) ->
- proplists:get_value(F, Avps, []);
-
-%% ... map ...
-values(Msg, F, _)
- when is_map(Msg) ->
- maps:get(F, Msg, []);
+ if is_map(Avps) ->
+ maps:get(F, Avps, []);
+ is_list(Avps) ->
+ proplists:get_value(F, Avps, [])
+ end;
%% ... or record.
values(Rec, F, Dict) ->
@@ -1906,23 +1890,13 @@ get_avp(Dict, Name, [#diameter_header{} | Avps]) ->
%% Message as name/values list ...
get_avp(_, Name, [_MsgName | Avps]) ->
- case lists:keyfind(Name, 1, Avps) of
+ case find(Name, Avps) of
{_, V} ->
#diameter_avp{name = Name, value = V};
_ ->
undefined
end;
-%% ... map ...
-get_avp(_, Name, Map)
- when is_map(Map) ->
- case maps:find(Name, Map) of
- {ok, V} ->
- #diameter_avp{name = Name, value = V};
- error ->
- undefined
- end;
-
%% ... or record (but not necessarily).
get_avp(Dict, Name, Rec) ->
try
@@ -1932,6 +1906,16 @@ get_avp(Dict, Name, Rec) ->
undefined
end.
+%% find/2
+
+find(Key, Map)
+ when is_map(Map) ->
+ maps:find(Key, Map);
+
+find(Key, List)
+ when is_list(List) ->
+ lists:keyfind(Key, 1, List).
+
%% get_avp_value/3
get_avp_value(Dict, Name, Msg) ->
diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl
index 100a4eebc9..fae9f86c38 100644
--- a/lib/diameter/test/diameter_traffic_SUITE.erl
+++ b/lib/diameter/test/diameter_traffic_SUITE.erl
@@ -99,14 +99,14 @@
stop/1]).
%% diameter callbacks
--export([peer_up/3,
- peer_down/3,
- pick_peer/6, pick_peer/7,
- prepare_request/5, prepare_request/6,
- prepare_retransmit/5,
- handle_answer/6, handle_answer/7,
- handle_error/6,
- handle_request/3]).
+-export([peer_up/4,
+ peer_down/4,
+ pick_peer/7, pick_peer/8,
+ prepare_request/6, prepare_request/7,
+ prepare_retransmit/6,
+ handle_answer/7, handle_answer/8,
+ handle_error/7,
+ handle_request/4]).
%% diameter_{tcp,sctp} callbacks
-export([message/3]).
@@ -182,19 +182,17 @@
%% A common match when receiving answers in a client.
-define(answer_message(SessionId, ResultCode),
- #{':name' := 'answer-message',
- 'Session-Id' := SessionId,
- 'Origin-Host' := _,
- 'Origin-Realm' := _,
- 'Result-Code' := ResultCode}).
+ ['answer-message' | #{'Session-Id' := SessionId,
+ 'Origin-Host' := _,
+ 'Origin-Realm' := _,
+ 'Result-Code' := ResultCode}]).
-define(answer_message(ResultCode),
- #{':name' := 'answer-message',
- 'Origin-Host' := _,
- 'Origin-Realm' := _,
- 'Result-Code' := ResultCode}).
+ ['answer-message' | #{'Origin-Host' := _,
+ 'Origin-Realm' := _,
+ 'Result-Code' := ResultCode}]).
%% Config for diameter:start_service/2.
--define(SERVICE(Name, Decode),
+-define(SERVICE(Name, Grp),
[{'Origin-Host', Name ++ "." ++ ?REALM},
{'Origin-Realm', ?REALM},
{'Host-IP-Address', [?ADDR]},
@@ -203,10 +201,10 @@
{'Auth-Application-Id', [0]}, %% common messages
{'Acct-Application-Id', [3]}, %% base accounting
{restrict_connections, false},
- {string_decode, Decode},
+ {string_decode, Grp#group.strings},
{incoming_maxlen, 1 bsl 21}
| [{application, [{dictionary, D},
- {module, ?MODULE},
+ {module, [?MODULE, Grp]},
{answer_errors, callback}]}
|| D <- [diameter_gen_base_rfc3588,
diameter_gen_base_accounting,
@@ -446,15 +444,15 @@ start(_Config) ->
ok = diameter:start().
start_services(Config) ->
- #group{strings = S,
- client_service = CN,
+ #group{client_service = CN,
server_service = SN,
server_decoding = SD}
+ = Grp
= group(Config),
ok = diameter:start_service(SN, [{decode_format, SD}
- | ?SERVICE(SN, S)]),
+ | ?SERVICE(SN, Grp)]),
ok = diameter:start_service(CN, [{sequence, ?CLIENT_MASK}
- | ?SERVICE(CN, S)]).
+ | ?SERVICE(CN, Grp)]).
add_transports(Config) ->
#group{transport = T,
@@ -484,8 +482,6 @@ add_transports(Config) ->
R <- ?RFCS,
R /= rfc4005 orelse have_nas(),
Id <- [{D,E}]],
- %% The server uses the client's Origin-State-Id to decide how to
- %% answer.
?util:write_priv(Config, "transport", [LRef | Cs]).
server_apps() ->
@@ -567,9 +563,8 @@ send_ok(Config) ->
Req = ['ACR', {'Accounting-Record-Type', ?EVENT_RECORD},
{'Accounting-Record-Number', 1}],
- #{':name' := 'ACA',
- 'Result-Code' := ?SUCCESS,
- 'Session-Id' := _}
+ ['ACA' | #{'Result-Code' := ?SUCCESS,
+ 'Session-Id' := _}]
= call(Config, Req).
%% Send an accounting ACR that the server answers badly to.
@@ -585,9 +580,8 @@ send_eval(Config) ->
Req = ['ACR', {'Accounting-Record-Type', ?EVENT_RECORD},
{'Accounting-Record-Number', 3}],
- #{':name' := 'ACA',
- 'Result-Code' := ?SUCCESS,
- 'Session-Id' := _}
+ ['ACA' | #{'Result-Code' := ?SUCCESS,
+ 'Session-Id' := _}]
= call(Config, Req).
%% Send an accounting ACR that the server tries to answer with an
@@ -613,8 +607,7 @@ send_protocol_error(Config) ->
send_experimental_result(Config) ->
Req = ['ACR', {'Accounting-Record-Type', ?EVENT_RECORD},
{'Accounting-Record-Number', 5}],
- #{':name' := 'ACA',
- 'Session-Id' := _}
+ ['ACA' | #{'Session-Id' := _}]
= call(Config, Req).
%% Send an ASR with an arbitrary non-mandatory AVP and expect success
@@ -622,11 +615,10 @@ send_experimental_result(Config) ->
send_arbitrary(Config) ->
Req = ['ASR', {'AVP', [#diameter_avp{name = 'Product-Name',
value = "XXX"}]}],
- #{':name' := 'ASA',
- 'Session-Id' := _,
- 'Result-Code' := ?SUCCESS,
- 'AVP' := [#diameter_avp{name = 'Product-Name',
- value = V}]}
+ ['ASA' | #{'Session-Id' := _,
+ 'Result-Code' := ?SUCCESS,
+ 'AVP' := [#diameter_avp{name = 'Product-Name',
+ value = V}]}]
= call(Config, Req),
"XXX" = string(V, Config).
@@ -635,12 +627,11 @@ send_unknown(Config) ->
Req = ['ASR', {'AVP', [#diameter_avp{code = 999,
is_mandatory = false,
data = <<17>>}]}],
- #{':name' := 'ASA',
- 'Session-Id' := _,
- 'Result-Code' := ?SUCCESS,
- 'AVP' := [#diameter_avp{code = 999,
- is_mandatory = false,
- data = <<17>>}]}
+ ['ASA' | #{'Session-Id' := _,
+ 'Result-Code' := ?SUCCESS,
+ 'AVP' := [#diameter_avp{code = 999,
+ is_mandatory = false,
+ data = <<17>>}]}]
= call(Config, Req).
%% Ditto, and point the AVP length past the end of the message. Expect
@@ -652,10 +643,9 @@ send_unknown_short(Config, M, RC) ->
Req = ['ASR', {'AVP', [#diameter_avp{code = 999,
is_mandatory = M,
data = <<17>>}]}],
- #{':name' := 'ASA',
- 'Session-Id' := _,
- 'Result-Code' := RC,
- 'Failed-AVP' := Avps}
+ ['ASA' | #{'Session-Id' := _,
+ 'Result-Code' := RC,
+ 'Failed-AVP' := Avps}]
= call(Config, Req),
[[#diameter_avp{code = 999,
is_mandatory = M,
@@ -667,10 +657,9 @@ send_unknown_mandatory(Config) ->
Req = ['ASR', {'AVP', [#diameter_avp{code = 999,
is_mandatory = true,
data = <<17>>}]}],
- #{':name' := 'ASA',
- 'Session-Id' := _,
- 'Result-Code' := ?AVP_UNSUPPORTED,
- 'Failed-AVP' := Avps}
+ ['ASA' | #{'Session-Id' := _,
+ 'Result-Code' := ?AVP_UNSUPPORTED,
+ 'Failed-AVP' := Avps}]
= call(Config, Req),
[[#diameter_avp{code = 999,
is_mandatory = true,
@@ -688,10 +677,9 @@ send_unexpected_mandatory_decode(Config) ->
Req = ['ASR', {'AVP', [#diameter_avp{code = 27, %% Session-Timeout
is_mandatory = true,
data = <<12:32>>}]}],
- #{':name' := 'ASA',
- 'Session-Id' := _,
- 'Result-Code' := ?AVP_UNSUPPORTED,
- 'Failed-AVP' := Avps}
+ ['ASA' | #{'Session-Id' := _,
+ 'Result-Code' := ?AVP_UNSUPPORTED,
+ 'Failed-AVP' := Avps}]
= call(Config, Req),
[[#diameter_avp{code = 27,
is_mandatory = true,
@@ -707,10 +695,9 @@ send_unexpected_mandatory_decode(Config) ->
send_grouped_error(Config) ->
Req = ['ASR', {'Proxy-Info', [[{'Proxy-Host', "abcd"},
{'Proxy-State', ""}]]}],
- #{':name' := 'ASA',
- 'Session-Id' := _,
- 'Result-Code' := ?INVALID_AVP_LENGTH,
- 'Failed-AVP' := Avps}
+ ['ASA' | #{'Session-Id' := _,
+ 'Result-Code' := ?INVALID_AVP_LENGTH,
+ 'Failed-AVP' := Avps}]
= call(Config, Req),
[[#diameter_avp{name = 'Proxy-Info', value = V}]]
= failed_avps(Avps, Config),
@@ -743,9 +730,8 @@ send_error_bit(Config) ->
%% Send a bad version and check that we get 5011.
send_unsupported_version(Config) ->
Req = ['STR', {'Termination-Cause', ?LOGOUT}],
- #{':name' := 'STA',
- 'Session-Id' := _,
- 'Result-Code' := ?UNSUPPORTED_VERSION}
+ ['STA' | #{'Session-Id' := _,
+ 'Result-Code' := ?UNSUPPORTED_VERSION}]
= call(Config, Req).
%% Send a request containing an AVP length > data size.
@@ -765,12 +751,11 @@ send_zero_avp_length(Config) ->
send_invalid_avp_length(Config) ->
Req = ['STR', {'Termination-Cause', ?LOGOUT}],
- #{':name' := 'STA',
- 'Session-Id' := _,
- 'Result-Code' := ?INVALID_AVP_LENGTH,
- 'Origin-Host' := _,
- 'Origin-Realm' := _,
- 'Failed-AVP' := Avps}
+ ['STA' | #{'Session-Id' := _,
+ 'Result-Code' := ?INVALID_AVP_LENGTH,
+ 'Origin-Host' := _,
+ 'Origin-Realm' := _,
+ 'Failed-AVP' := Avps}]
= call(Config, Req),
[[_]] = failed_avps(Avps, Config).
@@ -787,18 +772,16 @@ send_invalid_reject(Config) ->
send_unexpected_mandatory(Config) ->
Req = ['STR', {'Termination-Cause', ?LOGOUT}],
- #{':name' := 'STA',
- 'Session-Id' := _,
- 'Result-Code' := ?AVP_UNSUPPORTED}
+ ['STA' | #{'Session-Id' := _,
+ 'Result-Code' := ?AVP_UNSUPPORTED}]
= call(Config, Req).
%% Send something long that will be fragmented by TCP.
send_long(Config) ->
Req = ['STR', {'Termination-Cause', ?LOGOUT},
{'User-Name', [binary:copy(<<$X>>, 1 bsl 20)]}],
- #{':name' := 'STA',
- 'Session-Id' := _,
- 'Result-Code' := ?SUCCESS}
+ ['STA' | #{'Session-Id' := _,
+ 'Result-Code' := ?SUCCESS}]
= call(Config, Req).
%% Send something longer than the configure incoming_maxlen.
@@ -841,9 +824,8 @@ send_any_2(Config) ->
send_all_1(Config) ->
Req = ['STR', {'Termination-Cause', ?LOGOUT}],
Realm = lists:foldr(fun(C,A) -> [C,A] end, [], ?REALM),
- #{':name' := 'STA',
- 'Session-Id' := _,
- 'Result-Code' := ?SUCCESS}
+ ['STA' | #{'Session-Id' := _,
+ 'Result-Code' := ?SUCCESS}]
= call(Config, Req, [{filter, {all, [{host, any},
{realm, Realm}]}}]).
send_all_2(Config) ->
@@ -872,9 +854,8 @@ send_detach(Config) ->
Req = ['STR', {'Termination-Cause', ?LOGOUT}],
Ref = make_ref(),
ok = call(Config, Req, [{extra, [{self(), Ref}]}, detach]),
- #{':name' := 'STA',
- 'Session-Id' := _,
- 'Result-Code' := ?SUCCESS}
+ ['STA' | #{'Session-Id' := _,
+ 'Result-Code' := ?SUCCESS}]
= receive {Ref, T} -> T end.
%% Send a request which can't be encoded and expect {error, encode}.
@@ -887,15 +868,13 @@ send_destination_1(Config) ->
= group(Config),
Req = ['STR', {'Termination-Cause', ?LOGOUT},
{'Destination-Host', [?HOST(SN, ?REALM)]}],
- #{':name' := 'STA',
- 'Session-Id' := _,
- 'Result-Code' := ?SUCCESS}
+ ['STA' | #{'Session-Id' := _,
+ 'Result-Code' := ?SUCCESS}]
= call(Config, Req, [{filter, {all, [host, realm]}}]).
send_destination_2(Config) ->
Req = ['STR', {'Termination-Cause', ?LOGOUT}],
- #{':name' := 'STA',
- 'Session-Id' := _,
- 'Result-Code' := ?SUCCESS}
+ ['STA' | #{'Session-Id' := _,
+ 'Result-Code' := ?SUCCESS}]
= call(Config, Req, [{filter, {all, [host, realm]}}]).
%% Send with filtering on and expect failure when specifying an
@@ -959,9 +938,8 @@ send_bad_filter(Config, F) ->
%% Specify multiple filter options and expect them be conjunctive.
send_multiple_filters_1(Config) ->
Fun = fun(#diameter_caps{}) -> true end,
- #{':name' := 'STA',
- 'Session-Id' := _,
- 'Result-Code' := ?SUCCESS}
+ ['STA' | #{'Session-Id' := _,
+ 'Result-Code' := ?SUCCESS}]
= send_multiple_filters(Config, [host, {eval, Fun}]).
send_multiple_filters_2(Config) ->
E = {erlang, is_tuple, []},
@@ -972,9 +950,8 @@ send_multiple_filters_3(Config) ->
E2 = {erlang, is_tuple, []},
E3 = {erlang, is_record, [diameter_caps]},
E4 = [{erlang, is_record, []}, diameter_caps],
- #{':name' := 'STA',
- 'Session-Id' := _,
- 'Result-Code' := ?SUCCESS}
+ ['STA' | #{'Session-Id' := _,
+ 'Result-Code' := ?SUCCESS}]
= send_multiple_filters(Config, [{eval, E} || E <- [E1,E2,E3,E4]]).
send_multiple_filters(Config, Fs) ->
@@ -985,9 +962,8 @@ send_multiple_filters(Config, Fs) ->
%% only the return value from the prepare_request callback being
%% significant.
send_anything(Config) ->
- #{':name' := 'STA',
- 'Session-Id' := _,
- 'Result-Code' := ?SUCCESS}
+ ['STA' | #{'Session-Id' := _,
+ 'Result-Code' := ?SUCCESS}]
= call(Config, anything).
%% ===========================================================================
@@ -1037,12 +1013,11 @@ call(Config, Req, Opts) ->
#group{encoding = Enc,
client_service = CN,
client_dict = Dict0}
- = Group
= group(Config),
diameter:call(CN,
dict(Req, Dict0),
msg(Req, Enc, Dict0),
- [{extra, [{Name, Group}, diameter_lib:now()]} | Opts]).
+ [{extra, [Name, diameter_lib:now()]} | Opts]).
origin({D,E}) ->
4*decode(D) + encode(E);
@@ -1082,32 +1057,37 @@ msg([H|_] = Msg, record = E, diameter_gen_base_rfc6733)
msg([H|T], record, Dict) ->
Dict:'#new-'(Dict:msg2rec(H), T);
-msg([H|T], map, _) ->
- Map = maps:from_list(T),
- Map#{':name' => H};
+msg([H|As], map, _)
+ when is_list(As) ->
+ [H | maps:from_list(As)];
msg(Msg, _, _) ->
Msg.
-to_map(map, #diameter_packet{msg = Msg})
- when is_map(Msg) ->
+to_map(#diameter_packet{msg = [_MsgName | Avps] = Msg},
+ #group{server_decoding = map})
+ when is_map(Avps) ->
Msg;
-to_map(list, #diameter_packet{msg = [MsgName | Avps]}) ->
- maps:put(':name', MsgName, maps:from_list(Avps));
+to_map(#diameter_packet{msg = [MsgName | Avps]},
+ #group{server_decoding = list}) ->
+ [MsgName | maps:from_list(Avps)];
-to_map(record, #diameter_packet{header = H, msg = Rec}) ->
+to_map(#diameter_packet{header = H, msg = Rec},
+ #group{server_decoding = record}) ->
rec_to_map(Rec, dict(H));
%% No record decode: do it ourselves.
-to_map(false, #diameter_packet{header = H,
- msg = false,
- bin = Bin}) ->
+to_map(#diameter_packet{header = H,
+ msg = false,
+ bin = Bin},
+ #group{server_decoding = false,
+ strings = B}) ->
Opts = #{decode_format => map,
- string_decode => false,
+ string_decode => B,
strict_mbit => true,
rfc => 6733},
- #diameter_packet{msg = Msg}
+ #diameter_packet{msg = [_MsgName | _Map] = Msg}
= diameter_codec:decode(dict(H), Opts, Bin),
Msg.
@@ -1123,11 +1103,9 @@ dict(#diameter_header{application_id = Id,
rec_to_map(Rec, Dict) ->
[R | Vs] = Dict:'#get-'(Rec),
- maps:put(':name',
- Dict:rec2msg(R),
- maps:from_list([T || {_,V} = T <- Vs,
- V /= undefined,
- V /= []])).
+ [Dict:rec2msg(R) | maps:from_list([T || {_,V} = T <- Vs,
+ V /= undefined,
+ V /= []])].
appdict(rfc4005) ->
nas4005;
@@ -1166,12 +1144,12 @@ acct(diameter_gen_base_rfc6733) ->
%% Set only values that aren't already.
-set(_, [H|T], Vs) ->
- [H | Vs ++ T];
-
-set(_, Map, Vs)
- when is_map(Map) ->
- maps:merge(maps:from_list(Vs), Map);
+set(_, [N | As], Vs) ->
+ [N | if is_map(As) ->
+ maps:merge(maps:from_list(Vs), As);
+ is_list(As) ->
+ Vs ++ As
+ end];
set(#group{client_dict = Dict0} = _Group, Rec, Vs) ->
Dict = dict(Rec, Dict0),
@@ -1192,26 +1170,26 @@ reset(_, _, _, Rec) ->
%% ===========================================================================
%% diameter callbacks
-%% peer_up/3
+%% peer_up/4
-peer_up(_SvcName, _Peer, State) ->
+peer_up(_SvcName, _Peer, State, _Group) ->
State.
%% peer_down/3
-peer_down(_SvcName, _Peer, State) ->
+peer_down(_SvcName, _Peer, State, _Group) ->
State.
-%% pick_peer/6-7
+%% pick_peer/7-8
-pick_peer(Peers, _, [$C|_], _State, {Name, Group}, _)
+pick_peer(Peers, _, [$C|_], _State, Group, Name, _)
when Name /= send_detach ->
find(Group, Peers).
-pick_peer(_Peers, _, [$C|_], _State, {send_nopeer, _}, _, ?EXTRA) ->
+pick_peer(_Peers, _, [$C|_], _State, _Group, send_nopeer, _, ?EXTRA) ->
false;
-pick_peer(Peers, _, [$C|_], _State, {send_detach, Group}, _, {_,_}) ->
+pick_peer(Peers, _, [$C|_], _State, Group, send_detach, _, {_,_}) ->
find(Group, Peers).
find(#group{encoding = E,
@@ -1227,15 +1205,15 @@ id(Id, {Pid, _Caps}, SvcName) ->
= diameter:service_info(SvcName, Pid),
lists:member({id, Id}, Opts).
-%% prepare_request/5-6
+%% prepare_request/6-7
-prepare_request(_Pkt, [$C|_], {_Ref, _Caps}, {send_discard, _}, _) ->
+prepare_request(_Pkt, [$C|_], {_Ref, _Caps}, _, send_discard, _) ->
{discard, unprepared};
-prepare_request(Pkt, [$C|_], {_Ref, Caps}, {Name, Group}, _) ->
+prepare_request(Pkt, [$C|_], {_Ref, Caps}, Group, Name, _) ->
{send, prepare(Pkt, Caps, Name, Group)}.
-prepare_request(Pkt, [$C|_], {_Ref, Caps}, {send_detach, Group}, _, _) ->
+prepare_request(Pkt, [$C|_], {_Ref, Caps}, Group, send_detach, _, _) ->
{eval_packet, {send, prepare(Pkt, Caps, Group)}, [fun log/2, detach]}.
log(#diameter_packet{bin = Bin} = P, T)
@@ -1446,12 +1424,12 @@ set(N, #diameter_packet{msg = Req}, Caps, Group)
%% name/1
+name([H|#{}]) ->
+ {map, H};
+
name([H|_]) ->
{list, H};
-name(#{} = Map) ->
- {map, maps:get(':name', Map)};
-
name(Rec) ->
try
{record, element(1, Rec)}
@@ -1460,17 +1438,17 @@ name(Rec) ->
false
end.
-%% prepare_retransmit/5
+%% prepare_retransmit/6
-prepare_retransmit(_Pkt, false, _Peer, _Name, _Group) ->
+prepare_retransmit(_Pkt, false, _Peer, _Group, _Name, _) ->
discard.
-%% handle_answer/6-7
+%% handle_answer/7-8
-handle_answer(Pkt, Req, [$C|_], Peer, {Name, Group}, _) ->
+handle_answer(Pkt, Req, [$C|_], Peer, Group, Name, _) ->
answer(Pkt, Req, Peer, Name, Group).
-handle_answer(Pkt, Req, [$C|_], Peer, {send_detach = Name, Group}, _, X) ->
+handle_answer(Pkt, Req, [$C|_], Peer, Group, send_detach = Name, _, X) ->
{Pid, Ref} = X,
Pid ! {Ref, answer(Pkt, Req, Peer, Name, Group)}.
@@ -1503,18 +1481,18 @@ app(Req, _, Dict0) ->
Dict = dict(Req, Dict0),
Dict:id().
-%% handle_error/6
+%% handle_error/7
-handle_error(timeout = Reason, _Req, [$C|_], _Peer, _, Time) ->
+handle_error(timeout = Reason, _Req, [$C|_], _Peer, _, _, Time) ->
Now = diameter_lib:now(),
{Reason, {diameter_lib:timestamp(Time),
diameter_lib:timestamp(Now),
diameter_lib:micro_diff(Now, Time)}};
-handle_error(Reason, _Req, [$C|_], _Peer, _, _Time) ->
+handle_error(Reason, _Req, [$C|_], _Peer, _, _, _Time) ->
{error, Reason}.
-%% handle_request/3
+%% handle_request/4
%% Note that diameter will set Result-Code and Failed-AVPs if
%% #diameter_packet.errors is non-null.
@@ -1522,7 +1500,10 @@ handle_error(Reason, _Req, [$C|_], _Peer, _, _Time) ->
handle_request(#diameter_packet{header = H, avps = As}
= Pkt,
_,
- {_Ref, Caps}) ->
+ {_Ref, Caps},
+ #group{encoding = E,
+ server_decoding = D}
+ = Grp) ->
#diameter_header{end_to_end_id = EI,
hop_by_hop_id = HI}
= H,
@@ -1530,8 +1511,8 @@ handle_request(#diameter_packet{header = H, avps = As}
V = EI bsr B, %% assert
V = HI bsr B, %%
#diameter_caps{origin_state_id = {_,[Id]}} = Caps,
- {D,_} = T = origin(Id),
- wrap(T, H, request(to_map(D, Pkt), [H|As], Caps)).
+ {D,E} = T = origin(Id), %% assert
+ wrap(T, H, request(to_map(Pkt, Grp), [H|As], Caps)).
wrap(Id, H, {Tag, Action, Post}) ->
{Tag, wrap(Id, H, Action), Post};
@@ -1585,8 +1566,7 @@ base_to_nas(Msg, _) ->
%% request/3
%% send_experimental_result
-request(#{':name' := 'ACR',
- 'Accounting-Record-Number' := 5},
+request(['ACR' | #{'Accounting-Record-Number' := 5}],
[Hdr | Avps],
#diameter_caps{origin_host = {OH, _},
origin_realm = {OR, _}}) ->
@@ -1619,16 +1599,14 @@ request(Msg, _Avps, Caps) ->
%% request/2
%% send_nok
-request(#{':name' := 'ACR',
- 'Accounting-Record-Number' := 0},
+request(['ACR' | #{'Accounting-Record-Number' := 0}],
_) ->
{eval_packet, {protocol_error, ?INVALID_AVP_BITS}, [fun log/2, invalid]};
%% send_bad_answer
-request(#{':name' := 'ACR',
- 'Session-Id' := SId,
- 'Accounting-Record-Type' := RT,
- 'Accounting-Record-Number' := 2 = RN},
+request(['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},
@@ -1642,10 +1620,9 @@ request(#{':name' := 'ACR',
msg = Ans}};
%% send_eval
-request(#{':name' := 'ACR',
- 'Session-Id' := SId,
- 'Accounting-Record-Type' := RT,
- 'Accounting-Record-Number' := 3 = RN},
+request(['ACR' | #{'Session-Id' := SId,
+ 'Accounting-Record-Type' := RT,
+ 'Accounting-Record-Number' := 3 = RN}],
#diameter_caps{origin_host = {OH, _},
origin_realm = {OR, _}}) ->
Ans = ['ACA', {'Result-Code', ?SUCCESS},
@@ -1657,10 +1634,9 @@ request(#{':name' := 'ACR',
{eval, {reply, Ans}, {erlang, now, []}};
%% send_ok
-request(#{':name' := 'ACR',
- 'Session-Id' := SId,
- 'Accounting-Record-Type' := RT,
- 'Accounting-Record-Number' := 1 = RN},
+request(['ACR' | #{'Session-Id' := SId,
+ 'Accounting-Record-Type' := RT,
+ 'Accounting-Record-Number' := 1 = RN}],
#diameter_caps{origin_host = {OH, _},
origin_realm = {OR, _}}) ->
{reply, ['ACA', {'Result-Code', ?SUCCESS},
@@ -1671,8 +1647,7 @@ request(#{':name' := 'ACR',
{'Accounting-Record-Number', RN}]};
%% send_protocol_error
-request(#{':name' := 'ACR',
- 'Accounting-Record-Number' := 4},
+request(['ACR' | #{'Accounting-Record-Number' := 4}],
#diameter_caps{origin_host = {OH, _},
origin_realm = {OR, _}}) ->
Ans = ['answer-message', {'Result-Code', ?TOO_BUSY},
@@ -1680,46 +1655,39 @@ request(#{':name' := 'ACR',
{'Origin-Realm', OR}],
{reply, Ans};
-request(#{':name' := 'ASR',
- 'Session-Id' := SId}
- = Req,
+request(['ASR' | #{'Session-Id' := SId} = Avps],
#diameter_caps{origin_host = {OH, _},
origin_realm = {OR, _}}) ->
{reply, ['ASA', {'Result-Code', ?SUCCESS},
{'Session-Id', SId},
{'Origin-Host', OH},
{'Origin-Realm', OR},
- {'AVP', maps:get('AVP', Req, [])}]};
+ {'AVP', maps:get('AVP', Avps, [])}]};
%% send_invalid_reject
-request(#{':name' := 'STR',
- 'Termination-Cause' := ?USER_MOVED},
+request(['STR' | #{'Termination-Cause' := ?USER_MOVED}],
_Caps) ->
{protocol_error, ?TOO_BUSY};
%% send_noreply
-request(#{':name' := 'STR',
- 'Termination-Cause' := T},
+request(['STR' | #{'Termination-Cause' := T}],
_Caps)
when T /= ?LOGOUT ->
discard;
%% send_destination_5
-request(#{':name' := 'STR',
- 'Destination-Realm' := R},
+request(['STR' | #{'Destination-Realm' := R}],
#diameter_caps{origin_realm = {OR, _}})
when R /= undefined, R /= OR ->
{protocol_error, ?REALM_NOT_SERVED};
%% send_destination_6
-request(#{':name' := 'STR',
- 'Destination-Host' := [H]},
+request(['STR' | #{'Destination-Host' := [H]}],
#diameter_caps{origin_host = {OH, _}})
when H /= OH ->
{protocol_error, ?UNABLE_TO_DELIVER};
-request(#{':name' := 'STR',
- 'Session-Id' := SId},
+request(['STR' | #{'Session-Id' := SId}],
#diameter_caps{origin_host = {OH, _},
origin_realm = {OR, _}}) ->
{reply, ['STA', {'Result-Code', ?SUCCESS},
@@ -1728,7 +1696,7 @@ request(#{':name' := 'STR',
{'Origin-Realm', OR}]};
%% send_error/send_timeout
-request(#{':name' := 'RAR'}, _Caps) ->
+request(['RAR' | #{}], _Caps) ->
receive after 2000 -> {protocol_error, ?TOO_BUSY} end.
%% message/3
--
cgit v1.2.3
From e54f92c328c8fb117de88b1171f64358f1e7d3b1 Mon Sep 17 00:00:00 2001
From: Anders Svensson
Date: Sun, 9 Jul 2017 00:38:56 +0200
Subject: Don't take length of AVP lists unnecessarily at encode
Count as AVPs are encoded instead.
---
lib/diameter/src/base/diameter_gen.erl | 64 +++++++++++++++++++++++-----------
1 file changed, 43 insertions(+), 21 deletions(-)
diff --git a/lib/diameter/src/base/diameter_gen.erl b/lib/diameter/src/base/diameter_gen.erl
index 597ec143a8..313be5f215 100644
--- a/lib/diameter/src/base/diameter_gen.erl
+++ b/lib/diameter/src/base/diameter_gen.erl
@@ -104,7 +104,8 @@ enc(_, AvpName, 1, undefined, _, _) ->
?THROW([mandatory_avp_missing, AvpName]);
enc(Name, AvpName, 1, Value, Opts, Mod) ->
- enc(Name, AvpName, [Value], Opts, Mod);
+ H = avp_header(AvpName, Mod),
+ enc1(Name, AvpName, H, Value, Opts, Mod);
enc(_, _, {0,_}, [], _, _) ->
[];
@@ -113,31 +114,47 @@ enc(_, AvpName, _, T, _, _)
when not is_list(T) ->
?THROW([repeated_avp_as_non_list, AvpName, T]);
-enc(_, AvpName, {Min, _}, L, _, _)
- when length(L) < Min ->
- ?THROW([repeated_avp_insufficient_arity, AvpName, Min, L]);
+enc(Name, AvpName, {Min, Max}, Values, Opts, Mod) ->
+ H = avp_header(AvpName, Mod),
+ enc(Name, AvpName, H, Min, 0, Max, Values, Opts, Mod).
-enc(_, AvpName, {_, Max}, L, _, _)
- when Max < length(L) ->
- ?THROW([repeated_avp_excessive_arity, AvpName, Max, L]);
+%% enc/9
-enc(Name, AvpName, _, Values, Opts, Mod) ->
- enc(Name, AvpName, Values, Opts, Mod).
+enc(_, AvpName, _, Min, N, _, [], _, _)
+ when N < Min ->
+ ?THROW([repeated_avp_insufficient_arity, AvpName, Min, N]);
-%% enc/5
+enc(_, _, _, _, _, _, [], _, _) ->
+ [];
-enc(Name, 'AVP', Values, Opts, Mod) ->
- [enc_AVP(Name, A, Opts, Mod) || A <- Values];
+enc(_, AvpName, _, _, N, Max, _, _, _)
+ when Max =< N ->
+ ?THROW([repeated_avp_excessive_arity, AvpName, Max]);
-enc(_, AvpName, Values, Opts, Mod) ->
- enc(AvpName, Values, Opts, Mod).
+enc(Name, AvpName, H, Min, N, Max, [V|Vs], Opts, Mod) ->
+ [enc1(Name, AvpName, H, V, Opts, Mod)
+ | enc(Name, AvpName, H, Min, N+1, Max, Vs, Opts, Mod)].
-%% enc/4
+%% avp_header/2
+
+avp_header('AVP', _) ->
+ false;
+
+avp_header(AvpName, Mod) ->
+ {_,_,_} = Mod:avp_header(AvpName).
+
+%% enc1/6
-enc(AvpName, Values, Opts, Mod) ->
- H = Mod:avp_header(AvpName),
- [diameter_codec:pack_data(H, Mod:avp(encode, V, AvpName, Opts))
- || V <- Values].
+enc1(Name, 'AVP', false, Value, Opts, Mod) ->
+ enc_AVP(Name, Value, Opts, Mod);
+
+enc1(_, AvpName, Hdr, Value, Opts, Mod) ->
+ enc1(AvpName, Hdr, Value, Opts, Mod).
+
+%% enc1/5
+
+enc1(AvpName, {_,_,_} = Hdr, Value, Opts, Mod) ->
+ diameter_codec:pack_data(Hdr, Mod:avp(encode, Value, AvpName, Opts)).
%% enc_AVP/4
@@ -160,16 +177,21 @@ enc_AVP(_, #diameter_avp{name = N, value = V}, _, _)
enc_AVP(Name, #diameter_avp{name = AvpName, value = Data}, Opts, Mod) ->
0 == Mod:avp_arity(Name, AvpName)
orelse ?THROW([known_avp_as_AVP, Name, AvpName, Data]),
- enc(AvpName, [Data], Opts, Mod);
+ enc(AvpName, Data, Opts, Mod);
%% The backdoor ...
enc_AVP(_, {AvpName, Value}, Opts, Mod) ->
- enc(AvpName, [Value], Opts, Mod);
+ enc(AvpName, Value, Opts, Mod);
%% ... and the side door.
enc_AVP(_Name, {_Dict, _AvpName, _Data} = T, Opts, _) ->
diameter_codec:pack_avp(#diameter_avp{data = T}, Opts).
+%% enc/4
+
+enc(AvpName, Value, Opts, Mod) ->
+ enc1(AvpName, Mod:avp_header(AvpName), Value, Opts, Mod).
+
%% ---------------------------------------------------------------------------
%% # decode_avps/3
%% ---------------------------------------------------------------------------
--
cgit v1.2.3
From 9a94d2df5b761685038a5e7f7f0920c6a8c3d451 Mon Sep 17 00:00:00 2001
From: Anders Svensson
Date: Sun, 9 Jul 2017 06:17:25 +0200
Subject: Tweak limiting of testcases in traffic suite
Since the number is now under 50K again. Also make testing of individual
groups or testcases easier.
---
lib/diameter/test/diameter_traffic_SUITE.erl | 74 +++++++++++++++-------------
1 file changed, 39 insertions(+), 35 deletions(-)
diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl
index fae9f86c38..fbd57ca4d4 100644
--- a/lib/diameter/test/diameter_traffic_SUITE.erl
+++ b/lib/diameter/test/diameter_traffic_SUITE.erl
@@ -120,6 +120,11 @@
%% ===========================================================================
+%% 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, length(tc())).
+
-define(util, diameter_util).
-define(A, list_to_atom).
@@ -258,44 +263,40 @@ suite() ->
all() ->
[rfc4005, start, result_codes, {group, traffic}, empty, stop].
+%% Redefine this to run one or more groups for debugging purposes.
+-define(GROUPS, []).
+%-define(GROUPS, [[tcp,rfc6733,record,map,false,false,false,false]]).
+
groups() ->
- [{P, [P], Ts} || Ts <- [tc(tc())], P <- [shuffle, parallel]]
+ Names = names(),
+ [{P, [P], Ts} || Ts <- [tc()], P <- [shuffle, parallel]]
++
- [{?util:name([T,R,E,D,S,ST,SS,CS]),
- [],
- [{group, if S -> shuffle; not S -> parallel end}]}
- || T <- ?TRANSPORTS,
- R <- ?RFCS,
- E <- ?ENCODINGS,
- D <- ?DECODINGS,
- S <- ?STRING_DECODES,
- ST <- ?CALLBACKS,
- SS <- ?SENDERS,
- CS <- ?SENDERS]
+ [{?util:name(N), [], [{group, if S -> shuffle; not S -> parallel end}]}
+ || [_,_,_,_,S|_] = N <- Names]
++
- [{T, [], groups([[T,R,E,D,S,ST,SS,CS]
- || R <- ?RFCS,
- E <- ?ENCODINGS,
- D <- ?DECODINGS,
- S <- ?STRING_DECODES,
- ST <- ?CALLBACKS,
- SS <- ?SENDERS,
- CS <- ?SENDERS,
- SS orelse CS])} %% avoid deadlock
+ [{T, [], [{group, ?util:name(N)} || N <- names(Names, ?GROUPS),
+ T == hd(N)]}
|| T <- ?TRANSPORTS]
++
[{traffic, [], [{group, T} || T <- ?TRANSPORTS]}].
-%groups(_) -> %% debug
-% Name = [tcp,rfc6733,record,map,false,false,false,false],
-% [{group, ?util:name(Name)}];
-groups(Names) ->
- [{group, ?util:name(L)} || L <- Names].
+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].
+
+names(Names, []) ->
+ [N || N <- Names,
+ [CS,SS|_] <- [lists:reverse(N)],
+ SS orelse CS]; %% avoid deadlock
-%tc([N|_]) -> %% debug
-% [N];
-tc(L) ->
- L.
+names(_, Names) ->
+ Names.
%% --------------------
@@ -339,11 +340,7 @@ init_per_group(Name, Config) ->
server_decoding = D,
server_sender = SS,
server_throttle = ST},
- %% Limit the number of testcase, since the number of
- %% groups is large.
- All = ?util:scramble(tc()),
- TCs = lists:sublist(All, rand:uniform(32)),
- [{group, G}, {runlist, TCs} | Config];
+ [{group, G}, {runlist, select()} | Config];
_ ->
Config
end.
@@ -357,6 +354,13 @@ end_per_group(Name, Config)
end_per_group(_, _) ->
ok.
+select() ->
+ try rand:uniform(?LIMIT) of
+ N -> lists:sublist(?util:scramble(tc()), max(N,5))
+ catch
+ error:_ -> ?LIMIT
+ end.
+
%% --------------------
%% Skip testcases that can reasonably fail under SCTP.
--
cgit v1.2.3
From dec19d6f572a564502fb81c8f1ada5a470429d97 Mon Sep 17 00:00:00 2001
From: Anders Svensson
Date: Mon, 10 Jul 2017 14:54:28 +0200
Subject: Test decode_format record_from_map in traffic suite
---
lib/diameter/test/diameter_traffic_SUITE.erl | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl
index fbd57ca4d4..fb69cd831e 100644
--- a/lib/diameter/test/diameter_traffic_SUITE.erl
+++ b/lib/diameter/test/diameter_traffic_SUITE.erl
@@ -123,7 +123,7 @@
%% 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, length(tc())).
+-define(LIMIT, 42).
-define(util, diameter_util).
@@ -148,7 +148,7 @@
-define(ENCODINGS, [list, record, map]).
%% How to decode incoming messages.
--define(DECODINGS, [record, false, map, list]).
+-define(DECODINGS, [record, false, map, list, record_from_map]).
%% Which dictionary to use in the clients.
-define(RFCS, [rfc3588, rfc6733, rfc4005]).
@@ -1036,10 +1036,12 @@ decode(record) -> 0;
decode(list) -> 1;
decode(map) -> 2;
decode(false) -> 3;
+decode(record_from_map) -> 4;
decode(0) -> record;
decode(1) -> list;
decode(2) -> map;
-decode(3) -> false.
+decode(3) -> false;
+decode(4) -> record_from_map.
encode(record) -> 0;
encode(list) -> 1;
@@ -1078,7 +1080,9 @@ to_map(#diameter_packet{msg = [MsgName | Avps]},
[MsgName | maps:from_list(Avps)];
to_map(#diameter_packet{header = H, msg = Rec},
- #group{server_decoding = record}) ->
+ #group{server_decoding = D})
+ when D == record;
+ D == record_from_map ->
rec_to_map(Rec, dict(H));
%% No record decode: do it ourselves.
--
cgit v1.2.3
From 246a5d8611e258119fc6bdc6c52772539c8b09ca Mon Sep 17 00:00:00 2001
From: Anders Svensson
Date: Mon, 10 Jul 2017 20:32:02 +0200
Subject: Don't count AVPs unnecessarily at encode
Stop counting when there can be no arity errors.
---
lib/diameter/src/base/diameter_gen.erl | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/lib/diameter/src/base/diameter_gen.erl b/lib/diameter/src/base/diameter_gen.erl
index 313be5f215..a7dc3aaec3 100644
--- a/lib/diameter/src/base/diameter_gen.erl
+++ b/lib/diameter/src/base/diameter_gen.erl
@@ -127,6 +127,10 @@ enc(_, AvpName, _, Min, N, _, [], _, _)
enc(_, _, _, _, _, _, [], _, _) ->
[];
+enc(Name, AvpName, H, Min, N, '*', Vs, Opts, Mod)
+ when Min =< N ->
+ [enc1(Name, AvpName, H, V, Opts, Mod) || V <- Vs];
+
enc(_, AvpName, _, _, N, Max, _, _, _)
when Max =< N ->
?THROW([repeated_avp_excessive_arity, AvpName, Max]);
--
cgit v1.2.3
From 97256c5e098f36ee3459db768775c951e87ca717 Mon Sep 17 00:00:00 2001
From: Anders Svensson
Date: Mon, 17 Jul 2017 08:58:00 +0200
Subject: Increase init_per_suite timetrap in traffic suite
Compiling dictionaries is relatively slow, resulting in timeouts on some
hosts.
---
lib/diameter/test/diameter_traffic_SUITE.erl | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl
index fb69cd831e..d676614084 100644
--- a/lib/diameter/test/diameter_traffic_SUITE.erl
+++ b/lib/diameter/test/diameter_traffic_SUITE.erl
@@ -27,6 +27,7 @@
-export([suite/0,
all/0,
groups/0,
+ init_per_suite/0,
init_per_suite/1,
end_per_suite/1,
init_per_group/2,
@@ -300,6 +301,9 @@ names(_, Names) ->
%% --------------------
+init_per_suite() ->
+ [{timetrap, {seconds, 60}}].
+
init_per_suite(Config) ->
[{rfc4005, compile_and_load()}, {sctp, ?util:have_sctp()} | Config].
--
cgit v1.2.3
From baa65db0f00c84c7248d2401272569f1daf2e2b9 Mon Sep 17 00:00:00 2001
From: Anders Svensson
Date: Mon, 17 Jul 2017 11:14:32 +0200
Subject: Don't search forms unnecessarily in diameter_exprecs parse transform
The forms being extracted are in the head of the split.
---
lib/diameter/src/compiler/diameter_exprecs.erl | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/diameter/src/compiler/diameter_exprecs.erl b/lib/diameter/src/compiler/diameter_exprecs.erl
index 9a0cb6baf2..143dede037 100644
--- a/lib/diameter/src/compiler/diameter_exprecs.erl
+++ b/lib/diameter/src/compiler/diameter_exprecs.erl
@@ -110,9 +110,9 @@
%% parse_transform/2
parse_transform(Forms, _Options) ->
- Rs = [R || {attribute, _, record, R} <- Forms],
- Es = lists:append([E || {attribute, _, export_records, E} <- Forms]),
{H,T} = lists:splitwith(fun is_head/1, Forms),
+ Rs = [R || {attribute, _, record, R} <- H],
+ Es = lists:append([E || {attribute, _, export_records, E} <- H]),
H ++ [a_export(Es) | f_accessors(Es, Rs)] ++ T.
is_head(T) ->
--
cgit v1.2.3
From fc718fb2a7f0871930fb2553ae02875a106c414d Mon Sep 17 00:00:00 2001
From: Anders Svensson
Date: Mon, 17 Jul 2017 11:40:34 +0200
Subject: Add diameter_util:eprof/1 for test
Wrapping it around diameter_traffic_SUITE:compile_and_load/0 shows that
it's not diameter that's expensive. See below.
****** Process <0.103.0> -- 1.11 % of profiled time ***
FUNCTION CALLS % TIME [uS / CALLS]
-------- ----- ------- ---- [----------]
lists:append/1 3 0.00 0 [ 0.00]
lists:usort/1 1 0.00 0 [ 0.00]
lists:rmerge3_21_3/6 5 0.00 0 [ 0.00]
lists:merge2_1/4 4 0.00 0 [ 0.00]
lists:ukeysplit_1_1/10 2 0.00 0 [ 0.00]
lists:ukeymergel/3 1 0.00 0 [ 0.00]
lists:rukeymergel/3 2 0.00 0 [ 0.00]
lists:rukeymerge3_1/11 3 0.00 0 [ 0.00]
lists:rukeymerge2_1/6 1 0.00 0 [ 0.00]
beam_lib:chunks/2 1 0.00 0 [ 0.00]
beam_lib:read_chunk_data/2 1 0.00 0 [ 0.00]
beam_lib:read_chunk_data/3 1 0.00 0 [ 0.00]
beam_lib:check_chunks/5 2 0.00 0 [ 0.00]
beam_lib:scan_beam/4 1 0.00 0 [ 0.00]
beam_lib:scan_beam1/2 1 0.00 0 [ 0.00]
beam_lib:scan_beam2/2 1 0.00 0 [ 0.00]
beam_lib:get_atom_data/8 1 0.00 0 [ 0.00]
beam_lib:get_chunk/4 2 0.00 0 [ 0.00]
beam_lib:chunks_to_data/7 2 0.00 0 [ 0.00]
beam_lib:extract_atom/2 1 0.00 0 [ 0.00]
beam_lib:open_file/1 1 0.00 0 [ 0.00]
beam_lib:beam_filename/1 1 0.00 0 [ 0.00]
beam_lib:'-read_chunk_data/3-after$^0/0-0-'/1 1 0.00 0 [ 0.00]
diameter_dict_scanner:scan/1 2 0.00 0 [ 0.00]
diameter_codegen:from_dict/4 1 0.00 0 [ 0.00]
diameter_codegen:mod/2 1 0.00 0 [ 0.00]
diameter_codegen:maybe_write/5 1 0.00 0 [ 0.00]
diameter_codegen:report/2 3 0.00 0 [ 0.00]
diameter_codegen:report/3 3 0.00 0 [ 0.00]
diameter_codegen:putr/2 1 0.00 0 [ 0.00]
diameter_codegen:eraser/1 1 0.00 0 [ 0.00]
diameter_codegen:gen/3 1 0.00 0 [ 0.00]
diameter_codegen:erl_forms/2 1 0.00 0 [ 0.00]
diameter_codegen:make_hrl_forms/1 1 0.00 0 [ 0.00]
diameter_codegen:make_record_forms/1 1 0.00 0 [ 0.00]
diameter_codegen:grp_proj/1 7 0.00 0 [ 0.00]
diameter_codegen:f_name/1 1 0.00 0 [ 0.00]
diameter_codegen:f_id/1 1 0.00 0 [ 0.00]
diameter_codegen:c_id/1 1 0.00 0 [ 0.00]
diameter_codegen:f_vendor_id/1 1 0.00 0 [ 0.00]
diameter_codegen:b_vendor_id/1 1 0.00 0 [ 0.00]
diameter_codegen:f_vendor_name/1 1 0.00 0 [ 0.00]
diameter_codegen:b_vendor_name/1 1 0.00 0 [ 0.00]
diameter_codegen:f_msg_name/1 1 0.00 0 [ 0.00]
diameter_codegen:msg_name/1 1 0.00 0 [ 0.00]
diameter_codegen:c_msg_name/1 5 0.00 0 [ 0.00]
diameter_codegen:f_msg2rec/1 1 0.00 0 [ 0.00]
diameter_codegen:msg2rec/1 1 0.00 0 [ 0.00]
diameter_codegen:f_rec2msg/1 1 0.00 0 [ 0.00]
diameter_codegen:rec2msg/1 1 0.00 0 [ 0.00]
diameter_codegen:f_name2rec/1 1 0.00 0 [ 0.00]
diameter_codegen:name2rec/1 1 0.00 0 [ 0.00]
diameter_codegen:avps/1 6 0.00 0 [ 0.00]
diameter_codegen:c_imported_avp_name/2 1 0.00 0 [ 0.00]
diameter_codegen:f_avp_arity_2/1 1 0.00 0 [ 0.00]
diameter_codegen:avp_arity/1 1 0.00 0 [ 0.00]
diameter_codegen:f_avp/1 1 0.00 0 [ 0.00]
diameter_codegen:avp/1 1 0.00 0 [ 0.00]
diameter_codegen:types/1 1 0.00 0 [ 0.00]
diameter_codegen:avp/4 1 0.00 0 [ 0.00]
diameter_codegen:cs_imported_avp/3 1 0.00 0 [ 0.00]
diameter_codegen:f_enumerated_avp/1 1 0.00 0 [ 0.00]
diameter_codegen:enumerated_avp/1 1 0.00 0 [ 0.00]
diameter_codegen:enumerated_avp/3 1 0.00 0 [ 0.00]
diameter_codegen:f_msg_header/1 1 0.00 0 [ 0.00]
diameter_codegen:msg_header/1 1 0.00 0 [ 0.00]
diameter_codegen:msg_header/2 1 0.00 0 [ 0.00]
diameter_codegen:f_avp_header/1 1 0.00 0 [ 0.00]
diameter_codegen:avp_header/1 1 0.00 0 [ 0.00]
diameter_codegen:f_empty_value/1 1 0.00 0 [ 0.00]
diameter_codegen:empty_value/1 1 0.00 0 [ 0.00]
diameter_codegen:f_dict/1 1 0.00 0 [ 0.00]
diameter_codegen:to_upper/1 1 0.00 0 [ 0.00]
diameter_codegen:tu/1 4 0.00 0 [ 0.00]
diameter_codegen:preprocess/2 1 0.00 0 [ 0.00]
diameter_codegen:pp/2 1 0.00 0 [ 0.00]
diameter_codegen:abstract_code/1 1 0.00 0 [ 0.00]
diameter_codegen:'-empty_value/1-fun-1-'/1 1 0.00 0 [ 0.00]
diameter_codegen:'-empty_value/1-fun-0-'/1 1 0.00 0 [ 0.00]
diameter_codegen:'-f_avp_header/1-lc$^0/1-0-'/1 2 0.00 0 [ 0.00]
diameter_codegen:'-f_msg_header/1-lc$^0/1-0-'/1 2 0.00 0 [ 0.00]
diameter_codegen:'-enumerated_avp/1-fun-0-'/2 1 0.00 0 [ 0.00]
diameter_codegen:'-avp/4-fun-4-'/3 1 0.00 0 [ 0.00]
diameter_codegen:'-avp/4-fun-0-'/1 1 0.00 0 [ 0.00]
diameter_codegen:'-avp_arity/1-fun-0-'/1 1 0.00 0 [ 0.00]
diameter_codegen:'-avp_arities/1-fun-0-'/1 1 0.00 0 [ 0.00]
diameter_codegen:'-f_avp_arity_1/1-lc$^0/1-0-'/1 2 0.00 0 [ 0.00]
diameter_codegen:'-avp_name/1-fun-0-'/2 1 0.00 0 [ 0.00]
diameter_codegen:'-name2rec/1-fun-0-'/1 1 0.00 0 [ 0.00]
diameter_codegen:'-rec2msg/1-lc$^0/1-0-'/1 2 0.00 0 [ 0.00]
diameter_codegen:'-msg2rec/1-lc$^0/1-0-'/1 2 0.00 0 [ 0.00]
diameter_codegen:'-make_record_forms/1-lc$^2/1-0-'/2 2 0.00 0 [ 0.00]
diameter_codegen:'-make_record_forms/1-fun-1-'/1 2 0.00 0 [ 0.00]
diameter_codegen:'-make_hrl_forms/1-fun-0-'/1 1 0.00 0 [ 0.00]
diameter_codegen:'-from_dict/4-after$^0/0-0-'/0 1 0.00 0 [ 0.00]
filename:dirname/1 1 0.00 0 [ 0.00]
code:is_loaded/1 1 0.00 0 [ 0.00]
code:get_object_code/1 1 0.00 0 [ 0.00]
code:lib_dir/1 1 0.00 0 [ 0.00]
code:add_pathsa/1 1 0.00 0 [ 0.00]
code:which/1 1 0.00 0 [ 0.00]
file:read_file_info/1 2 0.00 0 [ 0.00]
file:read_file/1 1 0.00 0 [ 0.00]
file:call/2 3 0.00 0 [ 0.00]
file:check_and_call/2 3 0.00 0 [ 0.00]
dict:new/0 1 0.00 0 [ 0.00]
dict:fetch/2 2 0.00 0 [ 0.00]
dict:fold/3 3 0.00 0 [ 0.00]
dict:fold_dict/3 3 0.00 0 [ 0.00]
dict:mk_seg/1 1 0.00 0 [ 0.00]
diameter_make:default/1 1 0.00 0 [ 0.00]
diameter_make:def/2 1 0.00 0 [ 0.00]
diameter_make:modes/1 2 0.00 0 [ 0.00]
diameter_make:identify/1 1 0.00 0 [ 0.00]
diameter_make:make/3 1 0.00 0 [ 0.00]
diameter_make:ok/1 1 0.00 0 [ 0.00]
diameter_make:make/4 1 0.00 0 [ 0.00]
diameter_make:'-make/3-fun-0-'/5 1 0.00 0 [ 0.00]
diameter_traffic_SUITE:here/0 1 0.00 0 [ 0.00]
diameter_traffic_SUITE:'-compile_and_load/0-lc$^1/1-2-'/2 4 0.00 0 [ 0.00]
diameter_dict_util:parse/2 1 0.00 0 [ 0.00]
diameter_dict_util:do_parse/2 1 0.00 0 [ 0.00]
diameter_dict_util:read/1 1 0.00 0 [ 0.00]
diameter_dict_util:make_dict/2 1 0.00 0 [ 0.00]
diameter_dict_util:make_orddict/1 1 0.00 0 [ 0.00]
diameter_dict_util:make_dict/1 1 0.00 0 [ 0.00]
diameter_dict_util:reset/2 1 0.00 0 [ 0.00]
diameter_dict_util:reset/3 3 0.00 0 [ 0.00]
diameter_dict_util:opt/2 3 0.00 0 [ 0.00]
diameter_dict_util:reinherit/3 1 0.00 0 [ 0.00]
diameter_dict_util:pass1/1 1 0.00 0 [ 0.00]
diameter_dict_util:no_messages_without_id/1 1 0.00 0 [ 0.00]
diameter_dict_util:vendor_id_mismatch/6 2 0.00 0 [ 0.00]
diameter_dict_util:grouped_flags/4 2 0.00 0 [ 0.00]
diameter_dict_util:pass2/1 1 0.00 0 [ 0.00]
diameter_dict_util:p2/3 1 0.00 0 [ 0.00]
diameter_dict_util:pass3/2 1 0.00 0 [ 0.00]
diameter_dict_util:insert_codes/1 1 0.00 0 [ 0.00]
diameter_dict_util:import_avps/2 1 0.00 0 [ 0.00]
diameter_dict_util:explode_imports/2 1 0.00 0 [ 0.00]
diameter_dict_util:import_groups/1 1 0.00 0 [ 0.00]
diameter_dict_util:import_enums/1 1 0.00 0 [ 0.00]
diameter_dict_util:import/2 2 0.00 0 [ 0.00]
diameter_dict_util:import_key/2 2 0.00 0 [ 0.00]
diameter_dict_util:inherit/2 1 0.00 0 [ 0.00]
diameter_dict_util:inherit_avps/2 1 0.00 0 [ 0.00]
diameter_dict_util:find_avps/2 1 0.00 0 [ 0.00]
diameter_dict_util:avps_from_module/1 1 0.00 0 [ 0.00]
diameter_dict_util:examine/1 1 0.00 0 [ 0.00]
diameter_dict_util:putr/2 1 0.00 0 [ 0.00]
diameter_dict_util:eraser/1 1 0.00 0 [ 0.00]
diameter_dict_util:flatmap/2 2 0.00 0 [ 0.00]
diameter_dict_util:'-flatmap/2-fun-0-'/2 2 0.00 0 [ 0.00]
diameter_dict_util:'-inherit/2-fun-1-'/2 1 0.00 0 [ 0.00]
diameter_dict_util:'-import/2-fun-0-'/2 2 0.00 0 [ 0.00]
diameter_dict_util:'-import_avps/2-fun-0-'/2 1 0.00 0 [ 0.00]
diameter_dict_util:'-import_avps/2-fun-2-'/1 1 0.00 0 [ 0.00]
diameter_dict_util:'-pass2/1-fun-1-'/2 1 0.00 0 [ 0.00]
diameter_dict_util:'-pass2/1-fun-0-'/3 1 0.00 0 [ 0.00]
diameter_dict_util:'-opt/2-lc$^1/1-0-'/3 2 0.00 0 [ 0.00]
diameter_dict_util:'-reset/3-fun-1-'/2 3 0.00 0 [ 0.00]
diameter_dict_util:'-reset/2-fun-0-'/3 3 0.00 0 [ 0.00]
diameter_dict_util:'-do_parse/2-fun-0-'/1 1 0.00 0 [ 0.00]
diameter_dict_util:'-parse/2-after$^0/0-0-'/0 1 0.00 0 [ 0.00]
erl_abstract_code:debug_info/4 1 0.00 0 [ 0.00]
compile:env_default_opts/0 1 0.00 0 [ 0.00]
compile:do_compile/2 1 0.00 0 [ 0.00]
compile:expand_opts/1 1 0.00 0 [ 0.00]
compile:expand_opt/2 3 0.00 0 [ 0.00]
compile:'-expand_opts/1-anonymous-0-'/2 3 0.00 0 [ 0.00]
diameter_dict_parser:parse/1 1 0.00 0 [ 0.00]
diameter_dict_parser:yeccpars0/5 1 0.00 0 [ 0.00]
diameter_dict_parser:yeccpars1/5 1 0.00 0 [ 0.00]
diameter_dict_parser:yeccpars2_0/7 1 0.00 0 [ 0.00]
diameter_dict_parser:yeccpars2_1/7 1 0.00 0 [ 0.00]
diameter_dict_parser:yeccpars2_3/7 1 0.00 0 [ 0.00]
diameter_dict_parser:yeccpars2_4/7 1 0.00 0 [ 0.00]
diameter_dict_parser:yeccpars2_10/7 1 0.00 0 [ 0.00]
diameter_dict_parser:yeccpars2_11/7 1 0.00 0 [ 0.00]
diameter_dict_parser:yeccpars2_13/7 1 0.00 0 [ 0.00]
diameter_dict_parser:yeccpars2_22/7 1 0.00 0 [ 0.00]
diameter_dict_parser:yeccpars2_76/7 5 0.00 0 [ 0.00]
diameter_dict_parser:yeccpars2_82/7 1 0.00 0 [ 0.00]
diameter_dict_parser:yeccpars2_83/7 1 0.00 0 [ 0.00]
diameter_dict_parser:yeccpars2_84/7 1 0.00 0 [ 0.00]
diameter_dict_parser:yeccpars2_86/7 1 0.00 0 [ 0.00]
diameter_dict_parser:yeccpars2_88/7 1 0.00 0 [ 0.00]
diameter_dict_parser:yeccpars2_89/7 2 0.00 0 [ 0.00]
diameter_dict_parser:yeccpars2_90/7 1 0.00 0 [ 0.00]
diameter_dict_parser:yeccpars2_91/7 2 0.00 0 [ 0.00]
diameter_dict_parser:yeccpars2_92/7 2 0.00 0 [ 0.00]
diameter_dict_parser:yeccpars2_93/7 2 0.00 0 [ 0.00]
diameter_dict_parser:yeccpars2_94/7 2 0.00 0 [ 0.00]
diameter_dict_parser:yeccpars2_95/7 2 0.00 0 [ 0.00]
diameter_dict_parser:yeccpars2_96/7 2 0.00 0 [ 0.00]
diameter_dict_parser:yeccpars2_97/7 2 0.00 0 [ 0.00]
diameter_dict_parser:yeccpars2_99/7 2 0.00 0 [ 0.00]
diameter_dict_parser:yeccpars2_100/7 2 0.00 0 [ 0.00]
diameter_dict_parser:yeccpars2_101/7 2 0.00 0 [ 0.00]
diameter_dict_parser:yeccpars2_102/7 2 0.00 0 [ 0.00]
diameter_dict_parser:yeccpars2_103/7 2 0.00 0 [ 0.00]
diameter_dict_parser:yeccpars2_105/7 2 0.00 0 [ 0.00]
diameter_dict_parser:yeccpars2_106/7 2 0.00 0 [ 0.00]
diameter_dict_parser:yeccpars2_122/7 1 0.00 0 [ 0.00]
diameter_dict_parser:yeccpars2_130/7 2 0.00 0 [ 0.00]
diameter_dict_parser:yeccgoto_avp_code/7 2 0.00 0 [ 0.00]
diameter_dict_parser:yeccgoto_avp_header/7 2 0.00 0 [ 0.00]
diameter_dict_parser:yeccgoto_avp_header_tok/7 2 0.00 0 [ 0.00]
diameter_dict_parser:yeccgoto_avp_names/7 1 0.00 0 [ 0.00]
diameter_dict_parser:yeccgoto_dictionary/7 1 0.00 0 [ 0.00]
diameter_dict_parser:yeccgoto_group_def/7 2 0.00 0 [ 0.00]
diameter_dict_parser:yeccgoto_group_defs/7 2 0.00 0 [ 0.00]
diameter_dict_parser:yeccgoto_module/7 1 0.00 0 [ 0.00]
file:native_name_encoding/0 3 0.00 0 [ 0.00]
erlang:binary_to_atom/2 1 0.00 0 [ 0.00]
erlang:put/2 2 0.00 0 [ 0.00]
gen:'-call/4-fun-0-'/4 5 0.00 1 [ 0.20]
diameter_util:eprof/1 1 0.00 1 [ 1.00]
lists:sort/1 2 0.00 1 [ 0.50]
lists:ukeysort/2 2 0.00 1 [ 0.50]
lists:foldr/3 4 0.00 1 [ 0.25]
lists:mergel/2 5 0.00 1 [ 0.20]
lists:rmergel/2 8 0.00 1 [ 0.13]
lists:merge3_12_3/6 7 0.00 1 [ 0.14]
lists:merge3_21_3/6 12 0.00 1 [ 0.08]
lists:rmerge3_12_3/6 7 0.00 1 [ 0.14]
lists:merge2_2/5 6 0.00 1 [ 0.17]
lists:ukeysplit_1/8 6 0.00 1 [ 0.17]
lists:rukeymerge3_2/11 5 0.00 1 [ 0.20]
beam_lib:scan_beam/5 12 0.00 1 [ 0.08]
beam_lib:chunk_to_data/6 1 0.00 1 [ 1.00]
code_server:call/1 5 0.00 1 [ 0.20]
diameter_codegen:getr/1 3 0.00 1 [ 0.33]
diameter_codegen:msg_proj/1 10 0.00 1 [ 0.10]
diameter_codegen:a_record/3 3 0.00 1 [ 0.33]
diameter_codegen:c_msg2rec/2 10 0.00 1 [ 0.10]
diameter_codegen:c_rec2msg/2 10 0.00 1 [ 0.10]
diameter_codegen:f_avp_name/1 1 0.00 1 [ 1.00]
diameter_codegen:avp_name/1 1 0.00 1 [ 1.00]
diameter_codegen:vendor_id_map/1 2 0.00 1 [ 0.50]
diameter_codegen:f_avp_arity_1/1 1 0.00 1 [ 1.00]
diameter_codegen:avp_arities/1 1 0.00 1 [ 1.00]
diameter_codegen:cs_enumerated_avp/3 9 0.00 1 [ 0.11]
diameter_codegen:c_msg_header/4 10 0.00 1 [ 0.10]
diameter_codegen:emf/2 15 0.00 1 [ 0.07]
diameter_codegen:prefix/1 4 0.00 1 [ 0.25]
diameter_codegen:files/2 6 0.00 1 [ 0.17]
diameter_codegen:'-to_upper/1-fun-0-'/1 4 0.00 1 [ 0.25]
diameter_codegen:'-f_enumerated_avp/1-lc$^0/1-0-'/1 4 0.00 1 [ 0.25]
diameter_codegen:'-vendor_id_map/1-fun-0-'/1 4 0.00 1 [ 0.25]
diameter_codegen:'-name2rec/1-fun-1-'/2 7 0.00 1 [ 0.14]
diameter_codegen:'-msg_name/1-fun-0-'/1 5 0.00 1 [ 0.20]
diameter_codegen:'-make_record_forms/1-fun-3-'/1 5 0.00 1 [ 0.20]
filename:skip_prefix/2 7 0.00 1 [ 0.14]
filename:maybe_remove_dirsep/2 9 0.00 1 [ 0.11]
filename:unix_pathtype/1 7 0.00 1 [ 0.14]
code:call/1 5 0.00 1 [ 0.20]
file:file_name/1 3 0.00 1 [ 0.33]
file:check_args/1 6 0.00 1 [ 0.17]
dict:fetch_val/2 6 0.00 1 [ 0.17]
dict:expand_segs/2 4 0.00 1 [ 0.25]
diameter_gen_base_rfc3588:dict/0 3 0.00 1 [ 0.33]
diameter_make:codec/2 1 0.00 1 [ 1.00]
diameter_make:parse/2 1 0.00 1 [ 1.00]
diameter_make:is_mode/1 10 0.00 1 [ 0.10]
diameter_traffic_SUITE:'-compile_and_load/0-lc$^0/1-1-'/1 3 0.00 1 [ 0.33]
diameter_traffic_SUITE:'-compile_and_load/0-lc$^2/1-3-'/4 4 0.00 1 [ 0.25]
orddict:from_list/1 2 0.00 1 [ 0.50]
diameter_dict_util:post/2 5 0.00 1 [ 0.20]
diameter_dict_util:mk_code/2 5 0.00 1 [ 0.20]
diameter_dict_util:'-inherit/2-lc$^0/1-0-'/1 6 0.00 1 [ 0.17]
diameter_dict_util:'-pass1/1-fun-1-'/2 11 0.00 1 [ 0.09]
diameter_dict_util:'-opt/2-fun-0-'/1 7 0.00 1 [ 0.14]
erlang:spawn_monitor/1 1 0.00 1 [ 1.00]
compile:forms/2 1 0.00 1 [ 1.00]
diameter_dict_parser:yeccpars2_24/7 10 0.00 1 [ 0.10]
diameter_dict_parser:yeccpars2_25/7 10 0.00 1 [ 0.10]
diameter_dict_parser:yeccpars2_28/7 10 0.00 1 [ 0.10]
diameter_dict_parser:yeccpars2_30/7 10 0.00 1 [ 0.10]
diameter_dict_parser:yeccpars2_53/7 11 0.00 1 [ 0.09]
diameter_dict_parser:yeccpars2_59/7 10 0.00 1 [ 0.10]
diameter_dict_parser:yeccpars2_60/7 10 0.00 1 [ 0.10]
diameter_dict_parser:yeccpars2_64/7 10 0.00 1 [ 0.10]
diameter_dict_parser:yeccpars2_66/7 10 0.00 1 [ 0.10]
diameter_dict_parser:yeccpars2_68/7 10 0.00 1 [ 0.10]
diameter_dict_parser:yeccpars2_69/7 10 0.00 1 [ 0.10]
diameter_dict_parser:yeccpars2_71/7 10 0.00 1 [ 0.10]
diameter_dict_parser:yeccpars2_72/7 10 0.00 1 [ 0.10]
diameter_dict_parser:yeccpars2_73/7 15 0.00 1 [ 0.07]
diameter_dict_parser:yeccpars2_75/7 10 0.00 1 [ 0.10]
diameter_dict_parser:yeccpars2_78/7 10 0.00 1 [ 0.10]
diameter_dict_parser:yeccpars2_80/7 10 0.00 1 [ 0.10]
diameter_dict_parser:yeccpars2_81/7 10 0.00 1 [ 0.10]
diameter_dict_parser:yeccpars2_107/7 14 0.00 1 [ 0.07]
diameter_dict_parser:yeccgoto_bit/7 15 0.00 1 [ 0.07]
diameter_dict_parser:yeccgoto_bits/7 15 0.00 1 [ 0.07]
diameter_dict_parser:yeccgoto_command_def/7 10 0.00 1 [ 0.10]
diameter_dict_parser:yeccgoto_command_id/7 10 0.00 1 [ 0.10]
diameter_dict_parser:yeccgoto_header/7 10 0.00 1 [ 0.10]
diameter_dict_parser:yeccgoto_header_tok/7 10 0.00 1 [ 0.10]
diameter_dict_parser:yeccgoto_message_defs/7 10 0.00 1 [ 0.10]
erlang:erase/1 2 0.00 1 [ 0.50]
gen:do_call/4 5 0.00 2 [ 0.40]
lists:seq_loop/3 9 0.00 2 [ 0.22]
beam_lib:get_data/8 11 0.00 2 [ 0.18]
diameter_codegen:a_record/2 17 0.00 2 [ 0.12]
diameter_codegen:c_name2rec/2 17 0.00 2 [ 0.12]
diameter_codegen:c_avp_arities/1 17 0.00 2 [ 0.12]
diameter_codegen:c_avp_arity/1 18 0.00 2 [ 0.11]
diameter_codegen:c_avp_arity/2 17 0.00 2 [ 0.12]
diameter_codegen:cs_enumerated_avp/1 14 0.00 2 [ 0.14]
diameter_codegen:encode_msg_flags/1 10 0.00 2 [ 0.20]
diameter_codegen:'-include/2-lc$^0/1-0-'/2 12 0.00 2 [ 0.17]
diameter_codegen:'-msg_header/2-fun-0-'/2 10 0.00 2 [ 0.20]
diameter_codegen:'-enumerated_avp/3-fun-0-'/3 9 0.00 2 [ 0.22]
diameter_codegen:'-rec2msg/1-fun-1-'/2 10 0.00 2 [ 0.20]
diameter_codegen:'-msg2rec/1-fun-1-'/2 10 0.00 2 [ 0.20]
diameter_codegen:'-make_record_forms/1-fun-0-'/1 10 0.00 2 [ 0.20]
filename:basename/1 7 0.00 2 [ 0.29]
filename:join/1 9 0.00 2 [ 0.22]
filename:join/2 7 0.00 2 [ 0.29]
filename:pathtype/1 7 0.00 2 [ 0.29]
filename:major_os_type/0 9 0.00 2 [ 0.22]
code:load_binary/3 1 0.00 2 [ 2.00]
diameter_make:'-modes/1-fun-0-'/1 10 0.00 2 [ 0.20]
diameter_dict_util:do/2 3 0.00 2 [ 0.67]
diameter_dict_util:make/3 18 0.00 2 [ 0.11]
diameter_dict_util:opt/1 12 0.00 2 [ 0.17]
diameter_dict_util:report/3 21 0.00 2 [ 0.10]
diameter_dict_util:application_id_mismatch/3 10 0.00 2 [ 0.20]
diameter_dict_util:dict/1 3 0.00 2 [ 0.67]
diameter_dict_util:'-explode/3-fun-0-'/4 15 0.00 2 [ 0.13]
diameter_dict_util:'-pass1/1-fun-0-'/3 19 0.00 2 [ 0.11]
diameter_dict_util:'-make_dict/1-fun-0-'/2 19 0.00 2 [ 0.11]
diameter_dict_util:'-make/2-fun-0-'/3 18 0.00 2 [ 0.11]
diameter_dict_util:'-make_orddict/1-lc$^0/1-0-'/1 10 0.00 2 [ 0.20]
diameter_dict_parser:yeccpars2_2/7 19 0.00 2 [ 0.11]
diameter_dict_parser:yeccpars2_32/7 10 0.00 2 [ 0.20]
diameter_dict_parser:yeccpars2_65/7 10 0.00 2 [ 0.20]
diameter_dict_parser:yeccpars2_70/7 10 0.00 2 [ 0.20]
diameter_dict_parser:yeccpars2_74/7 15 0.00 2 [ 0.13]
diameter_dict_parser:yeccpars2_77/7 15 0.00 2 [ 0.13]
diameter_dict_parser:yeccpars2_109/7 14 0.00 2 [ 0.14]
diameter_dict_parser:yeccpars2_131/7 19 0.00 2 [ 0.11]
diameter_dict_parser:yeccgoto_section/7 19 0.00 2 [ 0.11]
diameter_dict_parser:yeccgoto_sections/7 19 0.00 2 [ 0.11]
os:getenv/1 1 0.00 2 [ 2.00]
ets:delete/1 1 0.00 2 [ 2.00]
ets:new/2 1 0.00 2 [ 2.00]
gen:do_for_proc/2 5 0.01 3 [ 0.60]
beam_lib:del_chunk/2 11 0.01 3 [ 0.27]
diameter_codegen:filter/1 23 0.01 3 [ 0.13]
diameter_codegen:'-empty_value/1-lc$^2/1-0-'/2 15 0.01 3 [ 0.20]
diameter_codegen:'-encode_msg_flags/1-fun-0-'/2 15 0.01 3 [ 0.20]
diameter_codegen:'-enumerated_avp/1-fun-1-'/1 14 0.01 3 [ 0.21]
diameter_codegen:'-f_avp/1-lc$^0/1-0-'/1 5 0.01 3 [ 0.60]
diameter_codegen:'-make_hrl_forms/1-fun-1-'/1 17 0.01 3 [ 0.18]
filename:separators/0 8 0.01 3 [ 0.38]
filename:flatten/1 8 0.01 3 [ 0.38]
dict:append/3 28 0.01 3 [ 0.11]
diameter_traffic_SUITE:'-compile_and_load/0-after$^3/0-0-'/0 1 0.01 3 [ 3.00]
diameter_dict_util:make_body/1 12 0.01 3 [ 0.25]
diameter_dict_util:section/2 19 0.01 3 [ 0.16]
diameter_dict_util:explode_avps/4 12 0.01 3 [ 0.25]
diameter_dict_util:'-reset/3-lc$^0/1-0-'/2 18 0.01 3 [ 0.17]
diameter_dict_util:'-mk/2-fun-0-'/1 15 0.01 3 [ 0.20]
gen_server:call/3 5 0.01 3 [ 0.60]
lists:seq/2 7 0.01 4 [ 0.57]
lists:merge3_2/6 23 0.01 4 [ 0.17]
lists:rmerge3_2/6 20 0.01 4 [ 0.20]
diameter_dict_scanner:'-split/1-fun-4-'/1 20 0.01 4 [ 0.20]
diameter_codegen:c_avp_arities/2 17 0.01 4 [ 0.24]
diameter_codegen:c_empty_value/1 29 0.01 4 [ 0.14]
diameter_codegen:'-c_avp_arity/1-fun-0-'/1 17 0.01 4 [ 0.24]
diameter_codegen:'-a_record/3-fun-0-'/3 17 0.01 4 [ 0.24]
orddict:fetch/2 25 0.01 4 [ 0.16]
diameter_dict_util:make/2 12 0.01 4 [ 0.33]
diameter_dict_util:p1/3 19 0.01 4 [ 0.21]
diameter_dict_util:is_enumerated_avp/3 14 0.01 4 [ 0.29]
diameter_dict_util:choose/3 24 0.01 4 [ 0.17]
diameter_dict_util:'-import_key/2-fun-0-'/2 14 0.01 4 [ 0.29]
lists:merge3_1/6 28 0.01 5 [ 0.18]
lists:rmerge3_1/6 22 0.01 5 [ 0.23]
diameter_codegen:c_imported_avp/2 44 0.01 5 [ 0.11]
diameter_codegen:include/2 42 0.01 5 [ 0.12]
diameter_codegen:'-include/2-fun-1-'/1 23 0.01 5 [ 0.22]
diameter_codegen:'-avp_arities/1-fun-1-'/1 17 0.01 5 [ 0.29]
diameter_dict_util:'-explode_imports/2-fun-0-'/4 50 0.01 5 [ 0.10]
diameter_dict_parser:yeccpars2_52/7 51 0.01 5 [ 0.10]
gen:call/4 5 0.01 6 [ 1.20]
lists:delete/2 31 0.01 6 [ 0.19]
lists:rmerge2_1/4 43 0.01 6 [ 0.14]
diameter_codegen:c_imported_avp_header/3 50 0.01 6 [ 0.12]
diameter_codegen:rec_name/2 27 0.01 6 [ 0.22]
diameter_codegen:'-empty_value/1-fun-3-'/1 29 0.01 6 [ 0.21]
dict:'-append/3-fun-0-'/3 28 0.01 6 [ 0.21]
diameter_dict_util:report/2 21 0.01 6 [ 0.29]
erlang:whereis/1 5 0.01 6 [ 1.20]
erlang:atom_to_list/1 28 0.01 6 [ 0.21]
lists:split_1_1/6 34 0.01 7 [ 0.21]
lists:rmerge2_2/5 54 0.01 7 [ 0.13]
beam_lib:pread/3 15 0.01 7 [ 0.47]
diameter_codegen:imported_avp/3 50 0.01 7 [ 0.14]
dict:fold_segs/4 51 0.01 7 [ 0.14]
diameter_dict_util:xi/4 50 0.01 7 [ 0.14]
diameter_dict_util:getr/1 21 0.01 7 [ 0.33]
diameter_dict_parser:yeccpars2_54/7 51 0.01 7 [ 0.14]
erlang:send/3 5 0.01 7 [ 1.40]
diameter_codegen:get_value/2 33 0.02 8 [ 0.24]
os:type/0 24 0.02 8 [ 0.33]
diameter_dict_scanner:section/1 19 0.02 9 [ 0.47]
diameter_codegen:eaf/2 80 0.02 9 [ 0.11]
diameter_codegen:'-pp/2-fun-0-'/2 42 0.02 9 [ 0.21]
filename:dirname/4 63 0.02 9 [ 0.14]
diameter_dict_util:'-p2/3-fun-0-'/2 82 0.02 9 [ 0.11]
diameter_dict_parser:yeccpars2_41/7 77 0.02 9 [ 0.12]
diameter_dict_parser:yeccpars2_45/7 77 0.02 9 [ 0.12]
diameter_dict_parser:yeccpars2_121/7 82 0.02 9 [ 0.11]
diameter_dict_parser:yeccpars2_123/7 82 0.02 9 [ 0.11]
diameter_dict_parser:yeccpars2_126/7 82 0.02 9 [ 0.11]
diameter_dict_parser:yeccpars2_128/7 80 0.02 9 [ 0.11]
diameter_dict_parser:yeccgoto_avp_defs/7 82 0.02 9 [ 0.11]
diameter_dict_parser:yeccgoto_avp_flags/7 82 0.02 9 [ 0.11]
diameter_dict_parser:yeccgoto_avp_type/7 82 0.02 9 [ 0.11]
diameter_dict_parser:yeccgoto_qual/7 77 0.02 9 [ 0.12]
erlang:system_info/1 24 0.02 9 [ 0.38]
diameter_codegen:c_avp_header/3 83 0.02 10 [ 0.12]
diameter_dict_util:'-import_avps/2-lc$^1/1-0-'/1 51 0.02 10 [ 0.20]
diameter_dict_util:'-p1/3-fun-2-'/3 94 0.02 10 [ 0.11]
diameter_dict_parser:yeccpars2_63/7 77 0.02 10 [ 0.13]
diameter_dict_parser:yeccpars2_124/7 82 0.02 10 [ 0.12]
diameter_dict_parser:yeccpars2_127/7 82 0.02 10 [ 0.12]
diameter_dict_parser:yeccgoto_avp_def/7 82 0.02 10 [ 0.12]
diameter_codegen:'-files/2-fun-0-'/1 50 0.02 11 [ 0.22]
diameter_codegen:'-c_avp_header/3-fun-0-'/3 50 0.02 11 [ 0.22]
diameter_codegen:'-cs_imported_avp/3-fun-0-'/2 50 0.02 11 [ 0.22]
diameter_codegen:'-cs_imported_avp/3-fun-1-'/3 50 0.02 11 [ 0.22]
diameter_codegen:'-avp/4-fun-1-'/2 50 0.02 11 [ 0.22]
orddict:reverse_pairs/2 93 0.02 11 [ 0.12]
diameter_dict_util:vendor/1 82 0.02 11 [ 0.13]
diameter_dict_util:foldl/3 59 0.02 11 [ 0.19]
diameter_dict_util:'-find_avps/2-lc$^0/1-0-'/1 51 0.02 11 [ 0.22]
diameter_dict_util:'-make/3-fun-0-'/3 94 0.02 11 [ 0.12]
diameter_codegen:'-c_imported_avp_name/2-fun-0-'/3 50 0.02 12 [ 0.24]
diameter_dict_parser:yeccpars2_6/7 107 0.02 12 [ 0.11]
diameter_dict_parser:yeccpars2_129/7 82 0.02 12 [ 0.15]
erlang:demonitor/2 10 0.02 12 [ 1.20]
proplists:get_value/2 53 0.03 13 [ 0.25]
erlang:'--'/2 83 0.03 13 [ 0.16]
diameter_codegen:not_in/2 132 0.03 14 [ 0.11]
diameter_codegen:c_base_avp/1 88 0.03 14 [ 0.16]
diameter_dict_util:explode/3 94 0.03 14 [ 0.15]
diameter_dict_parser:yeccpars2_108/7 131 0.03 14 [ 0.11]
diameter_dict_util:'-p1/3-fun-1-'/4 131 0.03 15 [ 0.11]
diameter_dict_parser:yeccpars2_110/7 131 0.03 15 [ 0.11]
diameter_dict_parser:yeccgoto_enum_def/7 131 0.03 15 [ 0.11]
diameter_dict_parser:yeccgoto_enum_defs/7 131 0.03 15 [ 0.11]
diameter_codegen:c_avp_name_/3 132 0.03 16 [ 0.12]
diameter_codegen:c_enumerated_avp/2 131 0.03 16 [ 0.12]
diameter_dict_util:qual/2 77 0.03 16 [ 0.21]
diameter_dict_parser:yeccpars2_111/7 131 0.03 16 [ 0.12]
lists:ukeysplit_2/5 81 0.04 17 [ 0.21]
diameter_codegen:c_avp_name/3 132 0.04 17 [ 0.13]
diameter_dict_util:explode_avps/2 82 0.04 17 [ 0.21]
diameter_dict_parser:yeccpars2_112/7 131 0.04 17 [ 0.13]
diameter_codegen:'-encode_avp_flags/1-fun-0-'/2 80 0.04 18 [ 0.23]
diameter_codegen:'-avp/4-fun-5-'/2 82 0.04 18 [ 0.22]
diameter_codegen:'-types/1-fun-0-'/1 82 0.04 18 [ 0.22]
dict:append_bkt/3 85 0.04 18 [ 0.21]
diameter_make:is_path/1 136 0.04 18 [ 0.13]
lists:split_1/5 96 0.04 19 [ 0.20]
diameter_codegen:'-avp_header/1-fun-0-'/3 83 0.04 19 [ 0.23]
diameter_codegen:'-avp/4-fun-6-'/1 82 0.04 19 [ 0.23]
diameter_codegen:'-avp_name/1-fun-1-'/3 82 0.04 19 [ 0.23]
diameter_dict_util:explode2/4 131 0.04 19 [ 0.15]
diameter_codegen:encode_avp_flags/1 82 0.04 20 [ 0.24]
diameter_dict_util:vendor_id/2 82 0.04 20 [ 0.24]
diameter_dict_util:'-avp_flags_valid/3-fun-0-'/1 80 0.04 20 [ 0.25]
diameter_dict_util:avp_type_known/3 82 0.04 21 [ 0.26]
diameter_dict_util:avp_vendor_id/4 82 0.04 21 [ 0.26]
orddict:find/2 156 0.05 22 [ 0.14]
diameter_dict_util:avp_flags_valid/3 82 0.05 22 [ 0.27]
lists:filter/2 86 0.05 23 [ 0.27]
diameter_codegen:v/4 214 0.05 23 [ 0.11]
lists:keymember/3 56 0.05 23 [ 0.41]
diameter_dict_scanner:'-split/1-fun-1-'/1 109 0.05 24 [ 0.22]
erlang:monitor/2 10 0.05 24 [ 2.40]
filename:basename1/3 251 0.06 28 [ 0.11]
diameter_dict_util:mk/2 109 0.06 28 [ 0.26]
diameter_codegen:'-cs_enumerated_avp/1-fun-0-'/2 131 0.06 30 [ 0.23]
diameter_dict_util:'-mk/2-fun-1-'/1 131 0.06 30 [ 0.23]
erlang:list_to_integer/1 226 0.07 32 [ 0.14]
diameter_dict_parser:yeccpars2_57/7 314 0.07 34 [ 0.11]
diameter_dict_parser:yeccpars2_43/7 298 0.08 38 [ 0.13]
diameter_dict_parser:yeccpars2_51/7 354 0.08 40 [ 0.11]
diameter_dict_parser:yeccgoto_avps/7 375 0.08 40 [ 0.11]
erlang:bitstring_to_list/1 284 0.08 40 [ 0.14]
dict:maybe_expand_segs/1 152 0.09 41 [ 0.27]
diameter_dict_parser:yeccpars2_47/7 365 0.09 41 [ 0.11]
diameter_dict_util:delim/2 375 0.09 42 [ 0.11]
diameter_dict_parser:yeccpars2_50/7 364 0.09 43 [ 0.12]
diameter_dict_parser:yeccpars2_58/7 314 0.09 43 [ 0.14]
diameter_dict_parser:yeccgoto_avp_name/7 365 0.09 43 [ 0.12]
diameter_codegen:field/1 385 0.09 44 [ 0.11]
diameter_dict_parser:yeccgoto_avp/7 375 0.09 44 [ 0.12]
diameter_dict_parser:yeccgoto_avp_spec/7 364 0.09 44 [ 0.12]
diameter_codegen:c_arity/2 385 0.09 45 [ 0.12]
file:file_name_1/2 196 0.09 45 [ 0.23]
diameter_dict_util:avp/1 375 0.09 45 [ 0.12]
diameter_dict_parser:yeccpars2_23/7 374 0.09 45 [ 0.12]
diameter_dict_parser:yeccgoto_avp_ref/7 375 0.09 45 [ 0.12]
diameter_dict_parser:yeccgoto_diameter_name/7 374 0.09 45 [ 0.12]
diameter_dict_parser:yeccpars2_44/7 375 0.10 46 [ 0.12]
diameter_dict_parser:yeccpars2_62/7 375 0.10 47 [ 0.13]
diameter_codegen:'-c_avp_arities/2-lc$^0/1-0-'/1 402 0.10 50 [ 0.12]
diameter_dict_util:is_uint32/2 228 0.11 51 [ 0.22]
lists:'-filter/2-lc$^0/1-0-'/2 308 0.11 52 [ 0.17]
diameter_dict_util:avp/2 375 0.11 52 [ 0.14]
diameter_codegen:vid/4 214 0.11 54 [ 0.25]
diameter_codegen:arity/2 243 0.11 55 [ 0.23]
diameter_dict_scanner:read_int/1 226 0.12 59 [ 0.26]
diameter_dict_util:type/1 164 0.13 61 [ 0.37]
filename:join1/4 476 0.14 66 [ 0.14]
erlang:list_to_tuple/1 541 0.14 67 [ 0.12]
filename:do_flatten/2 314 0.15 70 [ 0.22]
diameter_dict_util:xa/5 422 0.15 72 [ 0.17]
lists:member/2 554 0.16 75 [ 0.14]
diameter_dict_util:key/1 131 0.16 76 [ 0.58]
diameter_dict_util:'-make_body/1-fun-0-'/1 375 0.17 80 [ 0.21]
diameter_dict_util:avp_is_defined/3 364 0.17 83 [ 0.23]
diameter_dict_util:make_code/3 734 0.17 84 [ 0.11]
diameter_codegen:'-a_record/2-fun-0-'/1 385 0.18 86 [ 0.22]
diameter_dict_util:mo/3 838 0.18 86 [ 0.10]
diameter_dict_parser:yeccpars2_19/7 766 0.18 89 [ 0.12]
diameter_codegen:'-c_avp_arity/2-fun-0-'/2 385 0.19 90 [ 0.23]
diameter_dict_scanner:'-split/1-fun-2-'/1 395 0.19 91 [ 0.23]
lists:flatmap/2 396 0.20 95 [ 0.24]
dict:put_bucket_s/3 304 0.20 95 [ 0.31]
diameter_dict_parser:yeccgoto_ident/7 766 0.20 96 [ 0.13]
dict:store/3 829 0.21 101 [ 0.12]
dict:maybe_expand/2 857 0.21 101 [ 0.12]
dict:fold_seg/4 816 0.22 106 [ 0.13]
erlang:'++'/2 762 0.23 110 [ 0.14]
lists:foldl/3 842 0.23 112 [ 0.13]
diameter_dict_util:eval/1 845 0.24 115 [ 0.14]
dict:maybe_expand_aux/2 857 0.25 122 [ 0.14]
diameter_dict_util:x/3 838 0.27 128 [ 0.15]
diameter_codegen:'-c_avp_arities/2-lc$^1/1-1-'/2 770 0.27 129 [ 0.17]
diameter_dict_util:'-foldl/3-fun-0-'/3 543 0.27 132 [ 0.24]
diameter_dict_util:'-insert_codes/1-fun-0-'/3 734 0.32 152 [ 0.21]
diameter_dict_util:find/2 561 0.32 155 [ 0.28]
erl_parse:not_string/4 1467 0.32 155 [ 0.11]
diameter_dict_util:'-make_orddict/1-fun-1-'/3 838 0.36 175 [ 0.21]
diameter_dict_util:store_new/5 821 0.37 177 [ 0.22]
erlang:binary_to_list/1 12 0.37 180 [ 15.00]
diameter_dict_util:'-examine/1-fun-0-'/4 838 0.38 183 [ 0.22]
erlang:make_fun/3 1046 0.38 185 [ 0.18]
dict:'-store/3-fun-0-'/3 829 0.42 200 [ 0.24]
erlang:binary_to_term/1 1 0.44 214 [ 214.00]
epp:default_encoding/0 1044 0.47 226 [ 0.22]
diameter_dict_parser:yeccpars2/7 1954 0.47 227 [ 0.12]
diameter_dict_scanner:is_digit/1 2119 0.49 235 [ 0.11]
lists:dropwhile/2 1847 0.51 244 [ 0.13]
erl_parse:enc_func/1 1044 0.51 244 [ 0.23]
diameter_dict_parser:yeccpars1/7 1953 0.51 245 [ 0.13]
lists:reverse/2 1594 0.52 249 [ 0.16]
diameter_dict_scanner:splitwith/2 1040 0.52 251 [ 0.24]
lists:splitwith/2 1067 0.54 258 [ 0.24]
dict:on_bucket/3 857 0.54 259 [ 0.30]
dict:get_bucket_s/2 1538 0.54 261 [ 0.17]
dict:rehash/4 1206 0.58 280 [ 0.23]
erlang:tuple_to_list/1 2311 0.62 297 [ 0.13]
erl_parse:'-abstract/3-lc$^0/1-0-'/2 1420 0.64 309 [ 0.22]
diameter_dict_scanner:scan/2 2695 0.65 315 [ 0.12]
diameter_dict_scanner:word/1 814 0.66 318 [ 0.39]
dict:get_bucket/2 1386 0.68 325 [ 0.23]
dict:find/2 1384 0.68 326 [ 0.24]
erl_parse:abstract/2 1044 0.68 326 [ 0.31]
erl_parse:abstract_byte/2 1136 0.69 331 [ 0.29]
diameter_codegen:avp_info/1 1398 0.83 400 [ 0.29]
lists:map/2 1900 0.89 428 [ 0.23]
diameter_dict_scanner:is_eol_ch/1 1847 0.91 440 [ 0.24]
diameter_dict_scanner:'-split/1-fun-0-'/1 1847 0.93 446 [ 0.24]
diameter_dict_scanner:tok/2 1953 0.93 449 [ 0.23]
dict:fold_bucket/3 3178 1.00 483 [ 0.15]
lists:reverse/1 2080 1.04 499 [ 0.24]
dict:get_slot/2 2243 1.18 568 [ 0.25]
diameter_dict_scanner:acc/3 2694 1.28 618 [ 0.23]
diameter_codegen:remod/2 2872 1.32 633 [ 0.22]
proplists:get_value/3 3492 1.39 668 [ 0.19]
diameter_codegen:'-remod/2-lc$^0/1-0-'/2 3058 1.41 677 [ 0.22]
erl_anno:new_location/1 7098 1.51 728 [ 0.10]
erlang:spawn_opt/1 1 1.52 731 [ 731.00]
orddict:store/3 3559 1.74 837 [ 0.24]
erlang:setelement/3 3892 1.78 856 [ 0.22]
diameter_dict_scanner:is_upper/1 4100 1.83 882 [ 0.22]
erlang:phash/2 3297 1.95 940 [ 0.29]
dict:find_val/2 7390 2.16 1041 [ 0.14]
dict:store_bkt_val/3 4859 2.32 1114 [ 0.23]
diameter_dict_scanner:is_name_ch/1 9714 2.32 1116 [ 0.11]
lists:splitwith/3 9792 2.53 1216 [ 0.12]
erl_parse:abstract_tuple_list/3 5646 2.72 1311 [ 0.23]
erlang:list_to_atom/1 3609 2.76 1327 [ 0.37]
erl_anno:new/1 7098 3.44 1653 [ 0.23]
erl_parse:abstract_list/4 13813 3.77 1814 [ 0.13]
erl_parse:abstract/3 7851 3.82 1840 [ 0.23]
diameter_dict_scanner:'-split/1-fun-3-'/1 9210 4.24 2040 [ 0.22]
diameter_dict_scanner:is_lower/1 9714 4.43 2133 [ 0.22]
diameter_dict_scanner:is_alphanum/1 9714 4.50 2164 [ 0.22]
diameter_codegen:is_printable_ascii/1 11352 5.25 2525 [ 0.22]
diameter_dict_scanner:split/1 13351 5.39 2593 [ 0.19]
------------------------------------------------------------ ------ ------- ----- [----------]
Total: 246336 100.00% 48114 [ 0.20]
****** Process <0.107.0> -- 98.89 % of profiled time ***
FUNCTION CALLS % TIME [uS / CALLS]
-------- ----- ------- ---- [----------]
sys_core_bsm:module/2 1 0.00 0 [ 0.00]
sys_core_bsm:bsm_an_2/4 1 0.00 0 [ 0.00]
sys_core_bsm:bsm_an_3/4 1 0.00 0 [ 0.00]
sys_core_bsm:bsm_nonempty/2 1 0.00 0 [ 0.00]
sys_core_bsm:bsm_ensure_no_partition/2 1 0.00 0 [ 0.00]
sys_core_bsm:bsm_ensure_no_partition_1/3 1 0.00 0 [ 0.00]
erl_internal:add_predefined_functions/1 1 0.00 0 [ 0.00]
erl_internal:predefined_functions/1 1 0.00 0 [ 0.00]
erl_internal:get_optional_callbacks/1 1 0.00 0 [ 0.00]
erl_internal:module_predef_func_beh_info/2 1 0.00 0 [ 0.00]
erl_internal:module_predef_funcs_mod_info/1 1 0.00 0 [ 0.00]
v3_core:expr_map/4 3 0.00 0 [ 0.00]
v3_core:badmap_term/2 3 0.00 0 [ 0.00]
v3_life:module/2 1 0.00 0 [ 0.00]
v3_life:'-literal/2-lc$^0/1-1-'/2 3 0.00 0 [ 0.00]
beam_record:module/2 1 0.00 0 [ 0.00]
sys_core_fold:module/2 1 0.00 0 [ 0.00]
sets:from_list/1 1 0.00 0 [ 0.00]
sets:mk_seg/1 2 0.00 0 [ 0.00]
lists:nth/2 3 0.00 0 [ 0.00]
lists:sort/2 1 0.00 0 [ 0.00]
lists:rukeymerge3_2/11 2 0.00 0 [ 0.00]
lists:rukeymerge3_21_3/11 3 0.00 0 [ 0.00]
lists:ukeymerge2_1/7 3 0.00 0 [ 0.00]
diameter_exprecs:parse_transform/2 1 0.00 0 [ 0.00]
diameter_exprecs:a_export/1 1 0.00 0 [ 0.00]
diameter_exprecs:f_accessors/2 1 0.00 0 [ 0.00]
diameter_exprecs:'#info-/1'/0 1 0.00 0 [ 0.00]
diameter_exprecs:'#info-/2'/1 1 0.00 0 [ 0.00]
diameter_exprecs:'#new-/1'/1 1 0.00 0 [ 0.00]
diameter_exprecs:'#new-/2'/1 1 0.00 0 [ 0.00]
diameter_exprecs:'#get-/1'/1 1 0.00 0 [ 0.00]
diameter_exprecs:'#get-/2'/1 1 0.00 0 [ 0.00]
diameter_exprecs:'#set-/2'/1 1 0.00 0 [ 0.00]
diameter_exprecs:'-#set-/2/1-lc$^0/1-0-'/1 3 0.00 0 [ 0.00]
diameter_exprecs:'-#get-/2/1-lc$^0/1-0-'/1 3 0.00 0 [ 0.00]
diameter_exprecs:'-#get-/1/1-lc$^0/1-0-'/1 2 0.00 0 [ 0.00]
diameter_exprecs:'-#new-/2/1-lc$^0/1-0-'/1 3 0.00 0 [ 0.00]
diameter_exprecs:'-#new-/1/1-lc$^0/1-0-'/1 2 0.00 0 [ 0.00]
diameter_exprecs:'-#info-/2/1-lc$^0/1-0-'/1 3 0.00 0 [ 0.00]
zlib:open/0 1 0.00 0 [ 0.00]
zlib:close/1 1 0.00 0 [ 0.00]
zlib:deflateInit/2 1 0.00 0 [ 0.00]
zlib:deflate/3 1 0.00 0 [ 0.00]
zlib:deflateEnd/1 1 0.00 0 [ 0.00]
zlib:compress/1 1 0.00 0 [ 0.00]
zlib:collect/1 1 0.00 0 [ 0.00]
zlib:arg_flush/1 1 0.00 0 [ 0.00]
zlib:arg_level/1 1 0.00 0 [ 0.00]
zlib:reverse/1 1 0.00 0 [ 0.00]
zlib:reverse/2 3 0.00 0 [ 0.00]
zlib:'-compress/1-after$^0/0-0-'/1 1 0.00 0 [ 0.00]
code_server:call/1 1 0.00 0 [ 0.00]
beam_peep:module/2 1 0.00 0 [ 0.00]
beam_jump:module/2 1 0.00 0 [ 0.00]
beam_flatten:module/2 1 0.00 0 [ 0.00]
v3_codegen:functions/2 1 0.00 0 [ 0.00]
v3_codegen:'-set_cg/6-anonymous-2-'/2 3 0.00 0 [ 0.00]
v3_kernel:module/2 1 0.00 0 [ 0.00]
v3_kernel:expr_map/5 3 0.00 0 [ 0.00]
v3_kernel:map_group_pairs/5 3 0.00 0 [ 0.00]
v3_kernel:'-map_split_pairs_1/5-anonymous-0-'/1 3 0.00 0 [ 0.00]
v3_kernel:'-map_split_pairs/5-anonymous-1-'/3 3 0.00 0 [ 0.00]
beam_z:module/2 1 0.00 0 [ 0.00]
filename:skip_prefix/2 1 0.00 0 [ 0.00]
filename:basename/2 1 0.00 0 [ 0.00]
filename:basename/4 1 0.00 0 [ 0.00]
filename:dirname/1 1 0.00 0 [ 0.00]
filename:dirname/4 1 0.00 0 [ 0.00]
filename:separators/0 2 0.00 0 [ 0.00]
filename:do_flatten/2 3 0.00 0 [ 0.00]
beam_receive:module/2 1 0.00 0 [ 0.00]
code:ensure_loaded/1 1 0.00 0 [ 0.00]
code:call/1 1 0.00 0 [ 0.00]
dict:fetch_keys/1 1 0.00 0 [ 0.00]
dict:'-to_list/1-fun-0-'/3 3 0.00 0 [ 0.00]
os:type/0 2 0.00 0 [ 0.00]
beam_opcodes:format_number/0 1 0.00 0 [ 0.00]
beam_validator:validate/2 1 0.00 0 [ 0.00]
beam_validator:verify_put_map/6 3 0.00 0 [ 0.00]
beam_validator:assert_unique_map_keys/1 3 0.00 0 [ 0.00]
beam_bsm:module/2 1 0.00 0 [ 0.00]
beam_asm:module/5 1 0.00 0 [ 0.00]
beam_asm:assemble/5 1 0.00 0 [ 0.00]
beam_asm:on_load/2 1 0.00 0 [ 0.00]
beam_asm:build_file/9 1 0.00 0 [ 0.00]
beam_asm:finalize_fun_table/2 1 0.00 0 [ 0.00]
beam_asm:build_form/2 1 0.00 0 [ 0.00]
beam_asm:flatten_exports/1 2 0.00 0 [ 0.00]
beam_asm:flatten_imports/1 1 0.00 0 [ 0.00]
beam_asm:build_attributes/4 1 0.00 0 [ 0.00]
beam_asm:build_line_table/1 1 0.00 0 [ 0.00]
beam_asm:set_vsn_attribute/2 1 0.00 0 [ 0.00]
beam_asm:'-build_line_table/1-lbc$^1/2-1-'/2 2 0.00 0 [ 0.00]
beam_asm:'-build_line_table/1-lc$^0/1-0-'/1 1 0.00 0 [ 0.00]
beam_asm:'-build_file/9-lc$^1/1-1-'/1 2 0.00 0 [ 0.00]
beam_block:module/2 1 0.00 0 [ 0.00]
unicode:characters_to_binary/1 1 0.00 0 [ 0.00]
beam_dict:new/0 1 0.00 0 [ 0.00]
beam_dict:atom_table/2 1 0.00 0 [ 0.00]
beam_dict:string_table/1 1 0.00 0 [ 0.00]
beam_dict:lambda_table/1 1 0.00 0 [ 0.00]
beam_dict:line_table/1 1 0.00 0 [ 0.00]
beam_dict:'-line_table/1-lc$^0/1-0-'/1 3 0.00 0 [ 0.00]
orddict:to_list/1 3 0.00 0 [ 0.00]
erl_lint:value_option/7 1 0.00 0 [ 0.00]
erl_lint:module/3 1 0.00 0 [ 0.00]
erl_lint:compiler_options/1 1 0.00 0 [ 0.00]
erl_lint:start/2 1 0.00 0 [ 0.00]
erl_lint:return_status/1 1 0.00 0 [ 0.00]
erl_lint:pack_errors/1 1 0.00 0 [ 0.00]
erl_lint:pack_warnings/1 2 0.00 0 [ 0.00]
erl_lint:forms/2 1 0.00 0 [ 0.00]
erl_lint:includes_qlc_hrl/2 1 0.00 0 [ 0.00]
erl_lint:eval_file_attribute/2 1 0.00 0 [ 0.00]
erl_lint:start_state/2 1 0.00 0 [ 0.00]
erl_lint:eof/2 1 0.00 0 [ 0.00]
erl_lint:bif_clashes/2 1 0.00 0 [ 0.00]
erl_lint:not_deprecated/2 1 0.00 0 [ 0.00]
erl_lint:disallowed_compile_flags/2 1 0.00 0 [ 0.00]
erl_lint:post_traversal_check/2 1 0.00 0 [ 0.00]
erl_lint:check_behaviour/1 1 0.00 0 [ 0.00]
erl_lint:behaviour_check/2 1 0.00 0 [ 0.00]
erl_lint:all_behaviour_callbacks/3 1 0.00 0 [ 0.00]
erl_lint:behaviour_missing_callbacks/2 1 0.00 0 [ 0.00]
erl_lint:behaviour_conflicting/2 1 0.00 0 [ 0.00]
erl_lint:behaviour_add_conflicts/2 1 0.00 0 [ 0.00]
erl_lint:check_deprecated/2 1 0.00 0 [ 0.00]
erl_lint:check_imports/2 1 0.00 0 [ 0.00]
erl_lint:check_inlines/2 1 0.00 0 [ 0.00]
erl_lint:check_unused_functions/2 1 0.00 0 [ 0.00]
erl_lint:check_undefined_functions/1 1 0.00 0 [ 0.00]
erl_lint:check_undefined_types/1 1 0.00 0 [ 0.00]
erl_lint:check_bif_clashes/2 1 0.00 0 [ 0.00]
erl_lint:check_option_functions/4 3 0.00 0 [ 0.00]
erl_lint:nowarn_function/2 1 0.00 0 [ 0.00]
erl_lint:func_line_warning/3 1 0.00 0 [ 0.00]
erl_lint:func_line_error/3 3 0.00 0 [ 0.00]
erl_lint:check_untyped_records/2 1 0.00 0 [ 0.00]
erl_lint:check_unused_records/2 1 0.00 0 [ 0.00]
erl_lint:check_callback_information/1 1 0.00 0 [ 0.00]
erl_lint:export/3 2 0.00 0 [ 0.00]
erl_lint:exports/1 1 0.00 0 [ 0.00]
erl_lint:check_on_load/1 1 0.00 0 [ 0.00]
erl_lint:check_specs_without_function/1 1 0.00 0 [ 0.00]
erl_lint:check_functions_without_spec/2 1 0.00 0 [ 0.00]
erl_lint:check_unused_types/2 1 0.00 0 [ 0.00]
erl_lint:check_local_opaque_types/1 1 0.00 0 [ 0.00]
erl_lint:check_dialyzer_attribute/2 1 0.00 0 [ 0.00]
erl_lint:merge_state/2 1 0.00 0 [ 0.00]
erl_lint:local_functions/1 1 0.00 0 [ 0.00]
erl_lint:auto_import_suppressed/1 1 0.00 0 [ 0.00]
erl_lint:'-auto_import_suppressed/1-lc$^1/1-1-'/1 1 0.00 0 [ 0.00]
erl_lint:'-auto_import_suppressed/1-lc$^0/1-0-'/1 6 0.00 0 [ 0.00]
erl_lint:'-vtmerge_pat/2-fun-0-'/3 1 0.00 0 [ 0.00]
erl_lint:'-expr/3-fun-1-'/3 3 0.00 0 [ 0.00]
erl_lint:'-nowarn_function/2-lc$^0/1-0-'/2 6 0.00 0 [ 0.00]
erl_lint:'-check_option_functions/4-lc$^4/1-4-'/2 3 0.00 0 [ 0.00]
erl_lint:'-check_option_functions/4-lc$^1/1-1-'/4 6 0.00 0 [ 0.00]
erl_lint:'-check_undefined_types/1-lc$^0/1-0-'/3 1 0.00 0 [ 0.00]
erl_lint:'-behaviour_check/2-lc$^2/1-1-'/2 1 0.00 0 [ 0.00]
erl_lint:'-not_deprecated/2-lc$^5/1-5-'/1 1 0.00 0 [ 0.00]
erl_lint:'-not_deprecated/2-lc$^4/1-4-'/1 1 0.00 0 [ 0.00]
erl_lint:'-not_deprecated/2-lc$^3/1-3-'/1 1 0.00 0 [ 0.00]
erl_lint:'-not_deprecated/2-lc$^1/1-1-'/3 2 0.00 0 [ 0.00]
erl_lint:'-pack_warnings/1-lc$^0/1-2-'/1 2 0.00 0 [ 0.00]
erl_lint:'-pack_warnings/1-lc$^1/1-0-'/2 2 0.00 0 [ 0.00]
erl_expand_records:module/2 1 0.00 0 [ 0.00]
erl_expand_records:compiler_options/1 1 0.00 0 [ 0.00]
erl_expand_records:init_calltype/1 1 0.00 0 [ 0.00]
erl_expand_records:record_match/6 2 0.00 0 [ 0.00]
sofs:from_external/2 1 0.00 0 [ 0.00]
sofs:set/2 1 0.00 0 [ 0.00]
sofs:converse/1 1 0.00 0 [ 0.00]
sofs:drestriction/2 1 0.00 0 [ 0.00]
sofs:drestriction/3 1 0.00 0 [ 0.00]
sofs:family_to_relation/1 1 0.00 0 [ 0.00]
sofs:family_specification/2 1 0.00 0 [ 0.00]
sofs:is_element_type/1 1 0.00 0 [ 0.00]
sofs:rel_type/3 1 0.00 0 [ 0.00]
sofs:relprod/2 1 0.00 0 [ 0.00]
sofs:relprod1/2 1 0.00 0 [ 0.00]
sofs:converse/2 1 0.00 0 [ 0.00]
sofs:restrict/2 1 0.00 0 [ 0.00]
sofs:family2rel/2 1 0.00 0 [ 0.00]
sofs:fam_spec/4 1 0.00 0 [ 0.00]
beam_a:module/2 1 0.00 0 [ 0.00]
beam_trim:module/2 1 0.00 0 [ 0.00]
sys_core_dsetel:module/2 1 0.00 0 [ 0.00]
sys_core_dsetel:visit_module/1 1 0.00 0 [ 0.00]
cerl:module_name/1 1 0.00 0 [ 0.00]
cerl:map_es/1 3 0.00 0 [ 0.00]
cerl:map_arg/1 3 0.00 0 [ 0.00]
cerl:update_c_map/3 3 0.00 0 [ 0.00]
cerl:map_pair_key/1 3 0.00 0 [ 0.00]
cerl:map_pair_val/1 3 0.00 0 [ 0.00]
cerl:map_pair_op/1 3 0.00 0 [ 0.00]
cerl:ann_c_map_pair/4 3 0.00 0 [ 0.00]
cerl:update_c_map_pair/4 3 0.00 0 [ 0.00]
cerl:is_c_fname/1 3 0.00 0 [ 0.00]
erlang:open_port/2 1 0.00 0 [ 0.00]
erlang:port_command/2 1 0.00 0 [ 0.00]
erlang:port_close/1 1 0.00 0 [ 0.00]
erl_parse:new_anno/1 2 0.00 0 [ 0.00]
compile:expand_opts/1 1 0.00 0 [ 0.00]
compile:expand_opt/2 5 0.00 0 [ 0.00]
compile:internal/2 1 0.00 0 [ 0.00]
compile:build_compile/1 1 0.00 0 [ 0.00]
compile:internal_comp/5 1 0.00 0 [ 0.00]
compile:comp_ret_ok/2 1 0.00 0 [ 0.00]
compile:werror/1 1 0.00 0 [ 0.00]
compile:messages_per_file/1 1 0.00 0 [ 0.00]
compile:mpf/1 2 0.00 0 [ 0.00]
compile:passes/2 1 0.00 0 [ 0.00]
compile:fix_first_pass/1 1 0.00 0 [ 0.00]
compile:standard_passes/0 1 0.00 0 [ 0.00]
compile:core_passes/0 1 0.00 0 [ 0.00]
compile:kernel_passes/0 1 0.00 0 [ 0.00]
compile:transform_module/2 1 0.00 0 [ 0.00]
compile:foldl_transform/3 2 0.00 0 [ 0.00]
compile:core_transforms/2 1 0.00 0 [ 0.00]
compile:foldl_core_transforms/3 1 0.00 0 [ 0.00]
compile:get_module/1 1 0.00 0 [ 0.00]
compile:add_default_base/2 1 0.00 0 [ 0.00]
compile:lint_module/2 1 0.00 0 [ 0.00]
compile:expand_records/2 1 0.00 0 [ 0.00]
compile:core/2 1 0.00 0 [ 0.00]
compile:v3_kernel/2 1 0.00 0 [ 0.00]
compile:test_old_inliner/1 2 0.00 0 [ 0.00]
compile:test_core_inliner/1 2 0.00 0 [ 0.00]
compile:test_any_inliner/1 1 0.00 0 [ 0.00]
compile:save_abstract_code/2 1 0.00 0 [ 0.00]
compile:keep_compile_option/1 4 0.00 0 [ 0.00]
compile:beam_asm/2 1 0.00 0 [ 0.00]
compile:test_native/1 1 0.00 0 [ 0.00]
compile:is_native_enabled/1 6 0.00 0 [ 0.00]
compile:report_warnings/1 1 0.00 0 [ 0.00]
compile:outfile/3 1 0.00 0 [ 0.00]
compile:objfile/2 1 0.00 0 [ 0.00]
compile:'-core_transforms/2-lc$^0/1-0-'/1 6 0.00 0 [ 0.00]
compile:'-foldl_transform/3-anonymous-2-'/3 1 0.00 0 [ 0.00]
compile:'-foldl_transform/3-anonymous-0-'/3 1 0.00 0 [ 0.00]
compile:'-asm_passes/0-anonymous-4-'/2 1 0.00 0 [ 0.00]
compile:'-asm_passes/0-anonymous-0-'/1 1 0.00 0 [ 0.00]
compile:'-kernel_passes/0-anonymous-2-'/2 1 0.00 0 [ 0.00]
compile:'-core_passes/0-anonymous-7-'/2 1 0.00 0 [ 0.00]
compile:'-core_passes/0-anonymous-5-'/1 1 0.00 0 [ 0.00]
compile:'-core_passes/0-anonymous-3-'/1 1 0.00 0 [ 0.00]
compile:'-core_passes/0-anonymous-1-'/1 1 0.00 0 [ 0.00]
compile:'-standard_passes/0-anonymous-6-'/2 1 0.00 0 [ 0.00]
compile:'-standard_passes/0-anonymous-5-'/2 1 0.00 0 [ 0.00]
compile:'-standard_passes/0-anonymous-4-'/2 1 0.00 0 [ 0.00]
compile:'-standard_passes/0-anonymous-3-'/2 1 0.00 0 [ 0.00]
compile:'-standard_passes/0-anonymous-0-'/2 1 0.00 0 [ 0.00]
compile:'-messages_per_file/1-anonymous-5-'/1 2 0.00 0 [ 0.00]
compile:'-messages_per_file/1-lc$^0/1-0-'/1 1 0.00 0 [ 0.00]
compile:'-expand_opts/1-anonymous-0-'/2 5 0.00 0 [ 0.00]
compile:'-do_compile/2-anonymous-1-'/1 1 0.00 0 [ 0.00]
compile:'-do_compile/2-anonymous-0-'/2 1 0.00 0 [ 0.00]
beam_dead:module/2 1 0.00 0 [ 0.00]
beam_dead:equal_ops/2 1 0.00 0 [ 0.00]
beam_dead:shortcut_bs_ctb_1/4 1 0.00 0 [ 0.00]
beam_split:module/2 1 0.00 0 [ 0.00]
beam_except:module/2 1 0.00 0 [ 0.00]
ordsets:new/0 1 0.00 0 [ 0.00]
erlang:system_info/1 2 0.00 0 [ 0.00]
erlang:make_tuple/2 2 0.00 0 [ 0.00]
erlang:exit/1 1 0.00 0 [ 0.00]
beam_clean:module/2 1 0.00 1 [ 1.00]
beam_clean:rootset/3 1 0.00 1 [ 1.00]
beam_clean:bs_fix/1 1 0.00 1 [ 1.00]
sys_core_bsm:bsm_ensure_no_partition_2/5 3 0.00 1 [ 0.33]
erl_internal:'-predefined_functions/1-lc$^3/1-3-'/1 3 0.00 1 [ 0.33]
erl_internal:'-predefined_functions/1-lc$^2/1-2-'/1 3 0.00 1 [ 0.33]
v3_core:module/2 1 0.00 1 [ 1.00]
v3_core:map_build_pairs/4 3 0.00 1 [ 0.33]
v3_core:maybe_warn_repeated_keys/4 3 0.00 1 [ 0.33]
v3_core:is_valid_map_src/1 3 0.00 1 [ 0.33]
v3_core:'-is_simple/1-anonymous-1-'/1 8 0.00 1 [ 0.13]
v3_core:'-is_simple/1-anonymous-0-'/1 6 0.00 1 [ 0.17]
sys_core_fold:sub_subst_scope/1 3 0.00 1 [ 0.33]
cerl_sets:to_list/1 3 0.00 1 [ 0.33]
cerl_sets:union/2 3 0.00 1 [ 0.33]
beam_bs:module/2 1 0.00 1 [ 1.00]
sets:new/0 2 0.00 1 [ 0.50]
sets:expand_segs/2 2 0.00 1 [ 0.50]
lists:usort_1/2 3 0.00 1 [ 0.33]
zlib:collect/2 3 0.00 1 [ 0.33]
zlib:call/3 3 0.00 1 [ 0.33]
v3_codegen:module/2 1 0.00 1 [ 1.00]
v3_codegen:set_cg_map/7 3 0.00 1 [ 0.33]
v3_codegen:cg_build_args/2 5 0.00 1 [ 0.20]
v3_codegen:fetch_var_prefer_y/2 6 0.00 1 [ 0.17]
v3_codegen:find_stack/3 6 0.00 1 [ 0.17]
v3_codegen:'-set_cg/6-lc$^1/1-1-'/1 6 0.00 1 [ 0.17]
v3_codegen:'-set_cg/6-lc$^0/1-0-'/1 6 0.00 1 [ 0.17]
v3_kernel:map_split_pairs/5 3 0.00 1 [ 0.33]
v3_kernel:map_split_pairs_1/5 6 0.00 1 [ 0.17]
v3_kernel:map_remove_dup_keys/2 6 0.00 1 [ 0.17]
v3_kernel:map_key_clean/1 3 0.00 1 [ 0.33]
v3_kernel:lit_list_vars/1 8 0.00 1 [ 0.13]
v3_kernel:'-map_group_pairs/5-lc$^1/1-1-'/1 6 0.00 1 [ 0.17]
v3_kernel:'-map_group_pairs/5-lc$^0/1-0-'/1 6 0.00 1 [ 0.17]
filename:flatten/1 3 0.00 1 [ 0.33]
dict:to_list/1 4 0.00 1 [ 0.25]
beam_reorder:module/2 1 0.00 1 [ 1.00]
beam_validator:module/2 1 0.00 1 [ 1.00]
beam_validator:extract_map_keys/1 3 0.00 1 [ 0.33]
beam_validator:validate_bs_get/6 13 0.00 1 [ 0.08]
beam_validator:'-verify_put_map/6-anonymous-0-'/2 6 0.00 1 [ 0.17]
beam_asm:'-finalize_fun_table/2-lc$^0/1-0-'/2 7 0.00 1 [ 0.14]
beam_asm:'-build_file/9-lc$^0/1-0-'/1 7 0.00 1 [ 0.14]
beam_type:module/2 1 0.00 1 [ 1.00]
beam_dict:highest_opcode/1 1 0.00 1 [ 1.00]
beam_dict:local_table/1 1 0.00 1 [ 1.00]
beam_dict:import_table/1 1 0.00 1 [ 1.00]
beam_dict:literal_table/1 1 0.00 1 [ 1.00]
erl_lint:map_fields/4 6 0.00 1 [ 0.17]
erl_lint:'-check_option_functions/4-lc$^3/1-3-'/1 3 0.00 1 [ 0.33]
erl_lint:'-start/2-lc$^1/1-1-'/1 4 0.00 1 [ 0.25]
erl_lint:'-value_option/7-fun-0-'/7 5 0.00 1 [ 0.20]
erl_expand_records:record_upd_fs/3 4 0.00 1 [ 0.25]
sofs:relation/1 2 0.00 1 [ 0.50]
sofs:relative_product1/2 1 0.00 1 [ 1.00]
sofs:image/2 1 0.00 1 [ 1.00]
sofs:check_for_sort/2 1 0.00 1 [ 1.00]
sys_core_dsetel:'-visit/2-anonymous-6-'/2 3 0.00 1 [ 0.33]
cerl:is_c_atom/1 6 0.00 1 [ 0.17]
erlang:apply/2 1 0.00 1 [ 1.00]
erlang:port_control/3 3 0.00 1 [ 0.33]
erl_parse:anno_to_term/1 1 0.00 1 [ 1.00]
compile:passes_1/1 5 0.00 1 [ 0.20]
compile:pass/1 4 0.00 1 [ 0.25]
compile:select_list_passes/2 3 0.00 1 [ 0.33]
compile:asm_passes/0 1 0.00 1 [ 1.00]
compile:debug_info/1 1 0.00 1 [ 1.00]
compile:effects_code_generation/1 8 0.00 1 [ 0.13]
compile:'-debug_info/1-anonymous-0-'/1 4 0.00 1 [ 0.25]
compile:'-transform_module/2-lc$^0/1-0-'/1 7 0.00 1 [ 0.14]
compile:'-messages_per_file/1-anonymous-3-'/2 3 0.00 1 [ 0.33]
maps:merge/2 3 0.00 1 [ 0.33]
unicode:characters_to_binary/2 1 0.00 1 [ 1.00]
erlang:demonitor/2 1 0.00 1 [ 1.00]
erlang:function_exported/3 1 0.00 1 [ 1.00]
beam_clean:clean_labels/1 3 0.00 2 [ 0.67]
v3_core:map_build_pairs_1/3 6 0.00 2 [ 0.33]
sys_core_fold:body/2 9 0.00 2 [ 0.22]
sys_core_fold:pair_list/3 9 0.00 2 [ 0.22]
sys_core_fold:'-pair_list/3-lc$^0/1-0-'/3 9 0.00 2 [ 0.22]
beam_utils:is_not_used/3 17 0.00 2 [ 0.12]
lists:ukeymergel/3 10 0.00 2 [ 0.20]
lists:ukeymerge3_1/11 7 0.00 2 [ 0.29]
diameter_exprecs:is_head/1 23 0.00 2 [ 0.09]
diameter_exprecs:export/1 17 0.00 2 [ 0.12]
diameter_exprecs:accessors/2 17 0.00 2 [ 0.12]
diameter_exprecs:'info-'/1 17 0.00 2 [ 0.12]
diameter_exprecs:'new-'/1 17 0.00 2 [ 0.12]
diameter_exprecs:'new--'/1 17 0.00 2 [ 0.12]
diameter_exprecs:'get--'/1 17 0.00 2 [ 0.12]
diameter_exprecs:'get-'/1 17 0.00 2 [ 0.12]
diameter_exprecs:'set-'/1 17 0.00 2 [ 0.12]
v3_kernel:'-map_split_pairs/5-lc$^0/1-0-'/1 6 0.00 2 [ 0.33]
proplists:get_value/2 5 0.00 2 [ 0.40]
erl_lint:pseudolocals/0 6 0.00 2 [ 0.33]
erl_lint:record_def/4 18 0.00 2 [ 0.11]
erl_lint:check_type/2 18 0.00 2 [ 0.11]
erl_lint:handle_comprehension/4 17 0.00 2 [ 0.12]
sofs:relprod2/5 17 0.00 2 [ 0.12]
sofs:relprod/8 17 0.00 2 [ 0.12]
beam_trim:frame_layout_2/1 17 0.00 2 [ 0.12]
cerl:ann_c_map/3 15 0.00 2 [ 0.13]
compile:'-beam_asm/2-lc$^0/1-0-'/1 5 0.00 2 [ 0.40]
compile:'-test_core_inliner/1-anonymous-1-'/1 10 0.00 2 [ 0.20]
compile:'-test_core_inliner/1-anonymous-0-'/1 10 0.00 2 [ 0.20]
compile:'-test_old_inliner/1-anonymous-0-'/1 10 0.00 2 [ 0.20]
erlang:make_ref/0 13 0.00 2 [ 0.15]
erlang:binary_to_list/1 13 0.00 2 [ 0.15]
erl_internal:'-get_optional_callbacks/1-lc$^0/1-0-'/1 24 0.00 3 [ 0.13]
erl_internal:'-predefined_functions/1-lc$^1/1-1-'/1 24 0.00 3 [ 0.13]
sys_core_fold:pair/3 9 0.00 3 [ 0.33]
lists:flatten/1 9 0.00 3 [ 0.33]
lists:keysplit_1_1/10 22 0.00 3 [ 0.14]
lists:rkeymergel/4 19 0.00 3 [ 0.16]
diameter_exprecs:'-#set-/2/1-fun-1-'/1 17 0.00 3 [ 0.18]
diameter_exprecs:'-#get-/2/1-fun-1-'/1 17 0.00 3 [ 0.18]
diameter_exprecs:'-#get-/1/1-fun-1-'/1 17 0.00 3 [ 0.18]
diameter_exprecs:'-#new-/2/1-fun-1-'/1 17 0.00 3 [ 0.18]
diameter_exprecs:'-#new-/1/1-fun-1-'/1 17 0.00 3 [ 0.18]
diameter_exprecs:'-#info-/2/1-fun-1-'/1 17 0.00 3 [ 0.18]
diameter_exprecs:'-parse_transform/2-lc$^2/1-1-'/1 23 0.00 3 [ 0.13]
v3_codegen:select_cons/6 18 0.00 3 [ 0.17]
v3_codegen:select_nil/6 17 0.00 3 [ 0.18]
v3_codegen:get_bin_size_reg/2 13 0.00 3 [ 0.23]
v3_codegen:bif_cg/7 17 0.00 3 [ 0.18]
v3_codegen:'-cg_build_args/2-lc$^0/1-0-'/2 15 0.00 3 [ 0.20]
v3_kernel:'-lit_list_vars/1-anonymous-0-'/2 16 0.00 3 [ 0.19]
dict:expand_segs/2 8 0.00 3 [ 0.38]
beam_asm:finalize_fun_table_1/2 7 0.00 3 [ 0.43]
beam_asm:chunk/2 5 0.00 3 [ 0.60]
beam_asm:filter_essentials/1 8 0.00 3 [ 0.38]
beam_type:simplify_select_val_int/2 13 0.00 3 [ 0.23]
beam_dict:export_table/1 1 0.00 3 [ 3.00]
erl_lint:'-start/2-lc$^0/1-0-'/1 16 0.00 3 [ 0.19]
beam_dead:shortcut_bs_start_match_1/4 13 0.00 3 [ 0.23]
erlang:monitor/2 1 0.00 3 [ 3.00]
v3_core:attribute/1 20 0.00 4 [ 0.20]
sys_core_fold:sub_subst_scope_1/3 25 0.00 4 [ 0.16]
lists:do_flatten/2 21 0.00 4 [ 0.19]
lists:rukeymergel/3 22 0.00 4 [ 0.18]
lists:rukeymerge2_2/8 27 0.00 4 [ 0.15]
diameter_exprecs:fields/2 17 0.00 4 [ 0.24]
diameter_exprecs:fname/1 14 0.00 4 [ 0.29]
diameter_exprecs:'#new-X/0'/1 17 0.00 4 [ 0.24]
diameter_exprecs:'#new-X/1'/1 17 0.00 4 [ 0.24]
diameter_exprecs:'#set-X/2'/2 17 0.00 4 [ 0.24]
diameter_exprecs:'#get-X/1'/2 17 0.00 4 [ 0.24]
diameter_exprecs:'#get-X/2'/2 17 0.00 4 [ 0.24]
diameter_exprecs:'#info-X/1'/2 17 0.00 4 [ 0.24]
diameter_exprecs:'-f_accessors/2-fun-0-'/2 17 0.00 4 [ 0.24]
diameter_exprecs:'-a_export/1-fun-0-'/1 17 0.00 4 [ 0.24]
epp:default_encoding/0 17 0.00 4 [ 0.24]
v3_codegen:select_binary/6 14 0.00 4 [ 0.29]
v3_codegen:put_reg/2 18 0.00 4 [ 0.22]
v3_kernel:include_attribute/1 20 0.00 4 [ 0.20]
v3_kernel:iletrec_funs_gen/3 17 0.00 4 [ 0.24]
v3_kernel:'-uexpr/3-anonymous-18-'/2 17 0.00 4 [ 0.24]
v3_kernel:'-iletrec_funs/2-anonymous-1-'/2 17 0.00 4 [ 0.24]
proplists:get_bool/2 18 0.00 4 [ 0.22]
proplists:delete/2 15 0.00 4 [ 0.27]
beam_validator:verify_no_ct_1/1 17 0.00 4 [ 0.24]
beam_validator:is_bif_safe/2 17 0.00 4 [ 0.24]
beam_block:alloc_may_pass/1 17 0.00 4 [ 0.24]
erl_lint:bool_option/4 15 0.00 4 [ 0.27]
erl_lint:attribute_state/2 22 0.00 4 [ 0.18]
erl_lint:vt_no_unsafe/1 17 0.00 4 [ 0.24]
erl_lint:vt_no_unused/1 17 0.00 4 [ 0.24]
erl_expand_records:strict_record_access/2 34 0.00 4 [ 0.12]
erl_expand_records:opt_rec_vars/2 34 0.00 4 [ 0.12]
sofs:relprod1/5 36 0.00 4 [ 0.11]
beam_trim:trim_instructions/1 17 0.00 4 [ 0.24]
beam_trim:config_cost_1/2 17 0.00 4 [ 0.24]
beam_trim:expand_config/2 17 0.00 4 [ 0.24]
beam_trim:create_map/2 17 0.00 4 [ 0.24]
beam_trim:try_remap/3 17 0.00 4 [ 0.24]
beam_trim:frame_layout/3 17 0.00 4 [ 0.24]
beam_trim:'-frame_layout/3-anonymous-0-'/3 17 0.00 4 [ 0.24]
beam_trim:'-expand_config/2-lc$^0/1-0-'/1 17 0.00 4 [ 0.24]
sys_core_dsetel:visit_def_list/2 17 0.00 4 [ 0.24]
sys_core_dsetel:'-visit_def_list/2-anonymous-0-'/2 17 0.00 4 [ 0.24]
cerl:update_c_letrec/3 17 0.00 4 [ 0.24]
cerl:letrec_defs/1 17 0.00 4 [ 0.24]
cerl:letrec_body/1 17 0.00 4 [ 0.24]
erl_parse:enc_func/1 17 0.00 4 [ 0.24]
erl_parse:'-new_anno/1-fun-0-'/2 16 0.00 4 [ 0.25]
erts_internal:port_close/1 1 0.00 4 [ 4.00]
v3_core:preprocess_quals/3 17 0.00 5 [ 0.29]
v3_core:list_gen_pattern/3 17 0.00 5 [ 0.29]
v3_core:'-uexpr/3-anonymous-3-'/1 17 0.00 5 [ 0.29]
v3_core:'-uexpr/3-anonymous-2-'/3 17 0.00 5 [ 0.29]
v3_life:is_gc_bif/2 17 0.00 5 [ 0.29]
v3_life:'-k_bif/4-lc$^0/1-2-'/1 17 0.00 5 [ 0.29]
sys_core_fold:v_is_value/2 34 0.00 5 [ 0.15]
lists:keymergel/4 32 0.00 5 [ 0.16]
lists:ukeymerge3_21_3/9 36 0.00 5 [ 0.14]
diameter_exprecs:'-parse_transform/2-lc$^1/1-0-'/1 23 0.00 5 [ 0.22]
diameter_exprecs:'-parse_transform/2-fun-0-'/1 23 0.00 5 [ 0.22]
v3_codegen:select_extract_bin/12 13 0.00 5 [ 0.38]
v3_codegen:build_bs_instr/8 13 0.00 5 [ 0.38]
v3_codegen:internal_cg/7 17 0.00 5 [ 0.29]
v3_codegen:'-match_cg/5-anonymous-0-'/4 37 0.00 5 [ 0.14]
v3_kernel:group_bin_seg/2 26 0.00 5 [ 0.19]
v3_kernel:'-uexpr/3-anonymous-19-'/2 17 0.00 5 [ 0.29]
v3_kernel:'-uexpr/3-anonymous-15-'/2 17 0.00 5 [ 0.29]
v3_kernel:'-uexpr/3-anonymous-14-'/2 17 0.00 5 [ 0.29]
v3_kernel:'-uexpr/3-anonymous-3-'/2 17 0.00 5 [ 0.29]
beam_validator:bif_type/3 17 0.00 5 [ 0.29]
beam_asm:finalize_fun_table_2/3 18 0.00 5 [ 0.28]
beam_block:alloc_live_regs/2 17 0.00 5 [ 0.29]
beam_type:get_bs_integer_type/1 13 0.00 5 [ 0.38]
beam_dict:string/2 13 0.00 5 [ 0.38]
beam_dict:'-lambda_table/1-lc$^1/1-1-'/1 18 0.00 5 [ 0.28]
beam_dict:'-import_table/1-lc$^0/1-0-'/1 23 0.00 5 [ 0.22]
erl_lint:normalise_fields/1 18 0.00 5 [ 0.28]
erl_lint:nowarn/0 18 0.00 5 [ 0.28]
erl_lint:lc_quals/3 17 0.00 5 [ 0.29]
erl_lint:handle_generator/5 17 0.00 5 [ 0.29]
erl_lint:shadow_vars/4 17 0.00 5 [ 0.29]
erl_expand_records:normalise_fields/1 18 0.00 5 [ 0.28]
erl_expand_records:make_list/2 17 0.00 5 [ 0.29]
beam_trim:trim_instructions_1/4 34 0.00 5 [ 0.15]
beam_trim:save_config/4 17 0.00 5 [ 0.29]
sys_core_dsetel:'-visit/2-lc$^0/1-0-'/1 17 0.00 5 [ 0.29]
compile:select_cond/5 36 0.00 5 [ 0.14]
compile:clean_parse_transforms_1/2 48 0.00 5 [ 0.10]
erlang:term_to_binary/1 2 0.00 5 [ 2.50]
v3_core:generator/4 17 0.00 6 [ 0.35]
v3_core:lc_guard_tests/2 17 0.00 6 [ 0.35]
v3_core:new_fun_name/2 17 0.00 6 [ 0.35]
v3_core:'-cexpr/3-anonymous-0-'/2 17 0.00 6 [ 0.35]
sets:maybe_expand_segs/1 18 0.00 6 [ 0.33]
v3_codegen:select_extract_cons/6 18 0.00 6 [ 0.33]
v3_kernel:ubody_used_vars/2 17 0.00 6 [ 0.35]
v3_kernel:iletrec_funs/2 17 0.00 6 [ 0.35]
v3_kernel:'-expr/3-anonymous-2-'/4 17 0.00 6 [ 0.35]
beam_asm:bif_type/2 17 0.00 6 [ 0.35]
beam_asm:'-flatten_imports/1-anonymous-0-'/1 22 0.00 6 [ 0.27]
beam_block:x_live/2 34 0.00 6 [ 0.18]
erl_lint:guard_test2/3 34 0.00 6 [ 0.18]
erl_lint:def_fields/3 18 0.00 6 [ 0.33]
erl_lint:exist_record/3 34 0.00 6 [ 0.18]
erl_lint:check_type/3 18 0.00 6 [ 0.33]
erl_expand_records:field_names/1 17 0.00 6 [ 0.35]
erl_expand_records:record_info_call/3 34 0.00 6 [ 0.18]
compile:compile_options/1 48 0.00 6 [ 0.13]
erlang:list_to_bitstring/1 14 0.00 6 [ 0.43]
lists:rkeymerge2_1/6 56 0.00 7 [ 0.13]
lists:rkeymerge2_2/7 53 0.00 7 [ 0.13]
eval_bits:match_field/10 56 0.00 7 [ 0.13]
v3_codegen:protected_cg/7 37 0.00 7 [ 0.19]
v3_codegen:test_cg/7 37 0.00 7 [ 0.19]
v3_codegen:maybe_adjust_stack/5 20 0.00 7 [ 0.35]
v3_codegen:'-select_bin_segs/5-anonymous-0-'/5 56 0.00 7 [ 0.13]
v3_codegen:'-turn_yreg/2-lc$^0/1-0-'/2 37 0.00 7 [ 0.19]
v3_kernel:attributes/1 21 0.00 7 [ 0.33]
v3_kernel:new_fun_name/2 17 0.00 7 [ 0.41]
v3_kernel:bif_returns/3 17 0.00 7 [ 0.41]
v3_kernel:'-iletrec_funs_gen/3-anonymous-0-'/3 17 0.00 7 [ 0.41]
v3_kernel:'-iletrec_funs/2-anonymous-3-'/3 17 0.00 7 [ 0.41]
v3_kernel:'-iletrec_funs/2-lc$^0/1-0-'/1 17 0.00 7 [ 0.41]
v3_kernel:'-iletrec_funs/2-anonymous-2-'/3 17 0.00 7 [ 0.41]
beam_validator:test_heap/3 56 0.00 7 [ 0.13]
beam_validator:branch_arities/3 45 0.00 7 [ 0.16]
beam_block:live_regs/2 51 0.00 7 [ 0.14]
beam_dict:lambda/3 17 0.00 7 [ 0.41]
erl_lint:'-expr/3-fun-3-'/6 51 0.00 7 [ 0.14]
erl_expand_records:in_guard/1 34 0.00 7 [ 0.21]
compile:select_list_passes_1/3 55 0.00 7 [ 0.13]
erts_internal:open_port/2 1 0.00 7 [ 7.00]
v3_core:gexpr_test/3 34 0.00 8 [ 0.24]
v3_life:'-k_bif/4-lc$^0/1-3-'/1 34 0.00 8 [ 0.24]
lists:keymerge3_21_3/9 67 0.00 8 [ 0.12]
lists:ukeysplit_1_1/10 37 0.00 8 [ 0.22]
eval_bits:match_check_size/4 56 0.00 8 [ 0.14]
v3_codegen:select_bin_segs/5 56 0.00 8 [ 0.14]
v3_codegen:guard_clause_cg/4 37 0.00 8 [ 0.22]
v3_kernel:'-uexpr/3-anonymous-2-'/2 34 0.00 8 [ 0.24]
beam_validator:set_type/3 53 0.00 8 [ 0.15]
beam_asm:'-encode_arg/2-anonymous-0-'/2 39 0.00 8 [ 0.21]
beam_type:eq_ranges/3 56 0.00 8 [ 0.14]
beam_dict:old_string/2 13 0.00 8 [ 0.62]
beam_dict:'-lambda_table/1-lc$^0/1-0-'/1 38 0.00 8 [ 0.21]
erl_lint:vtsubtract/2 34 0.00 8 [ 0.24]
beam_trim:'-trim_instructions/1-lc$^0/1-0-'/1 34 0.00 8 [ 0.24]
beam_trim:'-trim/3-anonymous-0-'/1 34 0.00 8 [ 0.24]
beam_dead:shortcut_selectval/4 35 0.00 8 [ 0.23]
erlang:erase/1 36 0.00 8 [ 0.22]
v3_life:'-k_bif/4-lc$^0/1-5-'/1 34 0.00 9 [ 0.26]
v3_life:'-k_bif/4-lc$^0/1-4-'/1 34 0.00 9 [ 0.26]
v3_life:'-protected/3-lc$^0/1-1-'/1 37 0.00 9 [ 0.24]
lists:keysplit_1/8 64 0.00 9 [ 0.14]
v3_codegen:'-select_binary/6-anonymous-1-'/2 42 0.00 9 [ 0.21]
v3_kernel:add_local_function/2 17 0.00 9 [ 0.53]
beam_validator:upgrade_tuple_type/2 35 0.00 9 [ 0.26]
beam_asm:chunk/3 9 0.00 9 [ 1.00]
beam_asm:flag_to_bit/1 39 0.00 9 [ 0.23]
beam_block:x_dead/2 51 0.00 9 [ 0.18]
beam_dict:local/4 37 0.00 9 [ 0.24]
erl_lint:pattern_fields/7 51 0.00 9 [ 0.18]
erl_lint:init_fields/6 51 0.00 9 [ 0.18]
erl_lint:lc_quals/4 34 0.00 9 [ 0.26]
erl_lint:check_old_unused_vars/3 34 0.00 9 [ 0.26]
erl_lint:'-gexpr_list/3-fun-0-'/3 34 0.00 9 [ 0.26]
core_lib:'-vu_var_list/2-anonymous-0-'/2 34 0.00 9 [ 0.26]
beam_trim:remap_block/3 51 0.00 9 [ 0.18]
erl_internal:old_type_test/2 34 0.00 10 [ 0.29]
v3_core:preprocess_quals/4 34 0.00 10 [ 0.29]
v3_core:new_fun_name/1 17 0.00 10 [ 0.59]
lists:rkeymerge3_21_3/9 81 0.00 10 [ 0.12]
v3_codegen:'-guard_cg_list/6-anonymous-0-'/4 37 0.00 10 [ 0.27]
v3_kernel:'-uexpr/3-anonymous-20-'/2 37 0.00 10 [ 0.27]
beam_validator:'-verify_no_ct/1-lc$^0/1-0-'/1 51 0.00 10 [ 0.20]
erl_lint:guard_test/3 34 0.00 10 [ 0.29]
erl_lint:check_record_info_call/4 34 0.00 10 [ 0.29]
erl_lint:is_imported_function/2 34 0.00 10 [ 0.29]
erl_lint:'-vt_no_unused/1-lc$^0/1-0-'/1 51 0.00 10 [ 0.20]
erl_expand_records:guard_tests/2 34 0.00 10 [ 0.29]
erl_expand_records:guard_test/2 34 0.00 10 [ 0.29]
erl_expand_records:normalise_test/2 34 0.00 10 [ 0.29]
core_lib:vu_var_list/2 34 0.00 10 [ 0.29]
beam_trim:frame_layout_1/5 51 0.00 10 [ 0.20]
binary:match/2 13 0.00 10 [ 0.77]
v3_core:guard_tests/1 34 0.00 11 [ 0.32]
v3_core:gexpr_top/2 34 0.00 11 [ 0.32]
v3_core:force_booleans_1/4 68 0.00 11 [ 0.16]
v3_core:lc_tq/5 34 0.00 11 [ 0.32]
v3_life:protected/3 37 0.00 11 [ 0.30]
v3_life:guard_clause/5 37 0.00 11 [ 0.30]
v3_life:'-expr/3-lc$^0/1-4-'/1 37 0.00 11 [ 0.30]
sys_core_fold:'-expr/3-anonymous-4-'/3 34 0.00 11 [ 0.32]
sets:put_bucket_s/3 36 0.00 11 [ 0.31]
lists:keymerge3_12_3/9 85 0.00 11 [ 0.13]
lists:keymerge2_1/6 83 0.00 11 [ 0.13]
lists:keymerge2_2/7 85 0.00 11 [ 0.13]
v3_kernel:integers/2 34 0.00 11 [ 0.32]
v3_kernel:'-forest_pre_seq/2-lc$^2/1-2-'/1 37 0.00 11 [ 0.30]
beam_validator:'-valfun_1/2-lc$^0/1-0-'/2 51 0.00 11 [ 0.22]
erl_lint:gexpr/3 34 0.00 11 [ 0.32]
erl_lint:no_guard_bif_clash/2 34 0.00 11 [ 0.32]
erl_lint:'-vt_no_unsafe/1-lc$^0/1-0-'/1 51 0.00 11 [ 0.22]
cerl_trees:mapfold_pairs/4 34 0.00 11 [ 0.32]
erl_expand_records:lc_tq/3 34 0.00 11 [ 0.32]
erl_expand_records:pattern_fields/2 51 0.00 11 [ 0.22]
erl_expand_records:opt_rec_vars_2/2 34 0.00 11 [ 0.32]
erl_expand_records:'-guard_test/2-fun-0-'/2 34 0.00 11 [ 0.32]
beam_trim:frame_size/2 68 0.00 11 [ 0.16]
maps:is_key/2 37 0.00 11 [ 0.30]
erlang:iolist_to_binary/1 9 0.00 11 [ 1.22]
beam_utils:bif_to_test/3 34 0.00 12 [ 0.35]
beam_jump:extract_seq_1/2 69 0.00 12 [ 0.17]
v3_codegen:turn_yregs/3 91 0.00 12 [ 0.13]
v3_codegen:guard_cg_list/6 37 0.00 12 [ 0.32]
v3_codegen:'-save_stack/4-anonymous-2-'/2 85 0.00 12 [ 0.14]
v3_kernel:'-new_clauses/3-anonymous-2-'/3 51 0.00 12 [ 0.24]
v3_kernel:'-expr/3-anonymous-1-'/2 17 0.00 12 [ 0.71]
v3_kernel:'-extract_vars/1-anonymous-1-'/2 37 0.00 12 [ 0.32]
v3_kernel:'-extract_all_vars/3-lc$^1/1-1-'/2 37 0.00 12 [ 0.32]
v3_kernel:'-forest_pre_seq/2-lc$^0/1-0-'/1 37 0.00 12 [ 0.32]
beam_validator:call/3 85 0.00 12 [ 0.14]
beam_validator:allocate/5 69 0.00 12 [ 0.17]
erl_lint:gexpr_list/3 34 0.00 12 [ 0.35]
beam_trim:'-remap_block/3-lc$^0/1-0-'/2 51 0.00 12 [ 0.24]
cerl:update_c_values/2 47 0.00 12 [ 0.26]
cerl:update_c_alias/3 51 0.00 12 [ 0.24]
lists:ukeymerge2_2/6 100 0.00 13 [ 0.13]
eval_bits:add_bin_binding/4 56 0.00 13 [ 0.23]
v3_kernel:wrap_guard/2 37 0.00 13 [ 0.35]
v3_kernel:flatten_alias/1 51 0.00 13 [ 0.25]
v3_kernel:'-new_clauses/3-anonymous-1-'/3 51 0.00 13 [ 0.25]
v3_kernel:'-match_vars/2-anonymous-0-'/2 91 0.00 13 [ 0.14]
erl_lint:obsolete_guard/2 34 0.00 13 [ 0.38]
erl_expand_records:guard_test1/2 34 0.00 13 [ 0.38]
erl_expand_records:opt_rec_vars_1/2 68 0.00 13 [ 0.19]
erts_internal:port_command/3 1 0.00 13 [ 13.00]
v3_core:pat_alias/2 51 0.00 14 [ 0.27]
v3_life:test_op/1 37 0.00 14 [ 0.38]
v3_life:k_bif/4 34 0.00 14 [ 0.41]
lists:keysplit_2_1/10 101 0.00 14 [ 0.14]
eval_bits:coerce_to_float/2 56 0.00 14 [ 0.25]
eval_bits:match_check_size/3 56 0.00 14 [ 0.25]
v3_codegen:select_bin_seg/5 56 0.00 14 [ 0.25]
v3_kernel:guard/3 37 0.00 14 [ 0.38]
dict:is_key/2 52 0.00 14 [ 0.27]
dict:find_key/2 116 0.00 14 [ 0.12]
beam_dict:'-line_table/1-lc$^1/1-1-'/1 67 0.00 14 [ 0.21]
erl_lint:reject_invalid_alias/4 51 0.00 14 [ 0.27]
erl_lint:init_fields/3 51 0.00 14 [ 0.27]
erl_expand_records:record_inits/2 51 0.00 14 [ 0.27]
beam_trim:remap/3 85 0.00 14 [ 0.16]
sys_core_dsetel:rewrite/3 88 0.00 14 [ 0.16]
maps:keys/1 40 0.00 14 [ 0.35]
eval_bits:match_bits/6 56 0.00 15 [ 0.27]
v3_codegen:select_extract_int/11 43 0.00 15 [ 0.35]
v3_kernel:'-match_fun/1-anonymous-0-'/3 56 0.00 15 [ 0.27]
beam_validator:set_type_y/3 85 0.00 15 [ 0.18]
beam_validator:return_type_1/4 103 0.00 15 [ 0.15]
beam_validator:return_type_erl/2 103 0.00 15 [ 0.15]
beam_asm:encode_line_items/2 67 0.00 15 [ 0.22]
erl_lint:'-bool_option/4-fun-0-'/4 75 0.00 15 [ 0.20]
sys_core_dsetel:'-visit/2-anonymous-3-'/2 71 0.00 15 [ 0.21]
lists:rkeymerge3_12_3/9 125 0.00 16 [ 0.13]
lists:ukeysplit_1/8 80 0.00 16 [ 0.20]
lists:rukeymerge3_1/11 91 0.00 16 [ 0.18]
lists:rukeymerge2_1/6 109 0.00 16 [ 0.15]
v3_kernel:translate_match_fail_1/4 68 0.00 16 [ 0.24]
v3_kernel:store_free/4 17 0.00 16 [ 0.94]
v3_kernel:'-expr/3-lc$^0/1-0-'/1 51 0.00 16 [ 0.31]
beam_validator:bsm_get_context/2 59 0.00 16 [ 0.27]
core_lib:'-vu_expr/2-anonymous-0-'/2 68 0.00 16 [ 0.24]
beam_trim:'-remap_block/3-lc$^1/1-1-'/2 68 0.00 16 [ 0.24]
beam_trim:'-create_map/2-anonymous-2-'/2 68 0.00 16 [ 0.24]
cerl:primop_name/1 71 0.00 16 [ 0.23]
cerl:primop_args/1 71 0.00 16 [ 0.23]
eval_bits:get_value/6 56 0.00 17 [ 0.30]
v3_kernel:guard_opt/2 37 0.00 17 [ 0.46]
v3_kernel:select_assert_match_possible/3 56 0.00 17 [ 0.30]
v3_kernel:'-extract_var_list/1-lc$^0/1-0-'/1 37 0.00 17 [ 0.46]
proplists:get_value/3 82 0.00 17 [ 0.21]
erl_lint:pre_scan/2 157 0.00 17 [ 0.11]
erl_lint:'-check_dialyzer_attribute/2-lc$^2/1-0-'/1 157 0.00 17 [ 0.11]
erl_lint:'-check_unused_types/2-lc$^0/1-0-'/1 157 0.00 17 [ 0.11]
erl_lint:'-check_unused_records/2-lc$^0/1-0-'/1 157 0.00 17 [ 0.11]
erl_lint:'-disallowed_compile_flags/2-lc$^2/1-2-'/2 157 0.00 17 [ 0.11]
erl_lint:'-disallowed_compile_flags/2-lc$^0/1-0-'/2 157 0.00 17 [ 0.11]
erl_lint:'-not_deprecated/2-lc$^0/1-0-'/1 157 0.00 17 [ 0.11]
erl_lint:'-includes_qlc_hrl/2-lc$^0/1-0-'/1 157 0.00 17 [ 0.11]
cerl:update_c_cons_skel/3 68 0.00 17 [ 0.25]
cerl:update_c_primop/3 71 0.00 17 [ 0.24]
v3_core:unforce/3 68 0.00 18 [ 0.26]
sys_core_fold:sub_new/1 65 0.00 18 [ 0.28]
sys_core_fold:eval_case_warn/1 65 0.00 18 [ 0.28]
lists:unzip/1 65 0.00 18 [ 0.28]
eval_bits:match_field_1/6 56 0.00 18 [ 0.32]
v3_codegen:call_cg/7 68 0.00 18 [ 0.26]
v3_kernel:match_fun/1 56 0.00 18 [ 0.32]
beam_validator:eat_heap/2 66 0.00 18 [ 0.27]
beam_block:gen_init/4 102 0.00 18 [ 0.18]
erl_lint:'-bif_clashes/2-lc$^0/1-0-'/1 157 0.00 18 [ 0.11]
erl_expand_records:init_calltype_imports/2 157 0.00 18 [ 0.11]
compile:'-core/2-lc$^0/1-0-'/2 157 0.00 18 [ 0.11]
v3_life:'-match/5-lc$^1/1-0-'/5 74 0.00 19 [ 0.26]
lists:unzip/3 120 0.00 19 [ 0.16]
beam_validator:heap_alloc/2 125 0.00 19 [ 0.15]
erl_lint:'-compiler_options/1-lc$^0/1-0-'/1 157 0.00 19 [ 0.12]
erl_expand_records:guard_tests1/2 68 0.00 19 [ 0.28]
beam_except:dig_out_block_fc/1 68 0.00 19 [ 0.28]
erl_internal:'-predefined_functions/1-lc$^0/1-0-'/1 157 0.00 20 [ 0.13]
v3_codegen:put_stack/2 119 0.00 20 [ 0.17]
v3_kernel:rewrite_bool/4 37 0.00 20 [ 0.54]
v3_kernel:extract_vars/1 37 0.00 20 [ 0.54]
erl_lint:clauses/2 132 0.00 20 [ 0.15]
erl_lint:pattern_bin/5 131 0.00 20 [ 0.15]
erl_lint:'-vtnew/2-fun-0-'/3 85 0.00 20 [ 0.24]
sofs:restrict/5 130 0.00 20 [ 0.15]
sofs:diff_restrict_n/6 134 0.00 20 [ 0.15]
cerl:let_vars/1 88 0.00 20 [ 0.23]
compile:select_passes/2 80 0.00 20 [ 0.25]
beam_clean:find_all_used/3 169 0.00 21 [ 0.12]
beam_bs:function/2 168 0.00 21 [ 0.13]
v3_codegen:free_dead/1 68 0.00 21 [ 0.31]
v3_kernel:'-uexpr/3-anonymous-12-'/2 85 0.00 21 [ 0.25]
beam_block:'-init_yreg/2-anonymous-0-'/2 85 0.00 21 [ 0.25]
erl_lint:function_state/2 133 0.00 21 [ 0.16]
erl_lint:function/5 132 0.00 21 [ 0.16]
sys_core_dsetel:'-visit/2-anonymous-8-'/2 91 0.00 21 [ 0.23]
cerl:update_c_let/4 88 0.00 21 [ 0.24]
cerl:let_body/1 88 0.00 21 [ 0.24]
beam_clean:bs_fix/2 169 0.00 22 [ 0.13]
v3_kernel:forest_pre_seq/2 37 0.00 22 [ 0.59]
v3_kernel:extract_all_vars/3 74 0.00 22 [ 0.30]
erl_lint:'-check_deprecated/2-lc$^0/1-0-'/3 157 0.00 22 [ 0.14]
compile:fold_comp/4 38 0.00 22 [ 0.58]
erl_internal:type_test/2 68 0.00 23 [ 0.34]
v3_core:force_booleans/4 68 0.00 23 [ 0.34]
sys_core_fold:make_var_name/0 55 0.00 23 [ 0.42]
v3_codegen:select_bin_end/5 131 0.00 23 [ 0.18]
v3_codegen:build_call/3 68 0.00 23 [ 0.34]
v3_codegen:need_stack_frame/1 69 0.00 23 [ 0.33]
v3_codegen:'-load_vars/2-anonymous-0-'/2 85 0.00 23 [ 0.27]
beam_bsm:btb_index_find_start_match/1 168 0.00 23 [ 0.14]
erl_lint:format_function/5 171 0.00 23 [ 0.13]
lists:keymerge3_2/10 184 0.00 24 [ 0.13]
erl_lint:expr_bin/4 153 0.00 24 [ 0.16]
cerl:make_list/1 68 0.00 24 [ 0.35]
v3_life:'-expr/3-lc$^0/1-9-'/1 102 0.00 25 [ 0.25]
eval_bits:match_bits_1/6 112 0.00 25 [ 0.22]
eval_bits:get_integer/4 56 0.00 25 [ 0.45]
beam_bsm:btb_index_1/2 169 0.00 25 [ 0.15]
lists:rmerge3_21_3/6 158 0.00 26 [ 0.16]
v3_kernel:'-group_bin_seg/2-anonymous-0-'/2 117 0.00 26 [ 0.22]
v3_kernel:'-extract_all_vars/3-lc$^0/1-0-'/2 74 0.00 26 [ 0.35]
beam_validator:index_bs_start_match/2 169 0.00 26 [ 0.15]
erl_expand_records:record_wildcard_init/1 102 0.00 26 [ 0.25]
v3_core:cfun/3 151 0.00 27 [ 0.18]
sys_core_fold:returns_integer/2 102 0.00 27 [ 0.26]
sets:maybe_expand/1 185 0.00 27 [ 0.15]
lists:rkeymerge3_1/10 190 0.00 27 [ 0.14]
erl_lint:vtold/2 102 0.00 27 [ 0.26]
compile:'-internal_comp/5-anonymous-1-'/3 31 0.00 27 [ 0.87]
beam_dead:function/2 168 0.00 27 [ 0.16]
erlang:put/2 92 0.00 27 [ 0.29]
lists:keysplit_2/8 218 0.00 28 [ 0.13]
v3_kernel:make_forest_1/4 74 0.00 28 [ 0.38]
v3_kernel:extract_var_list/1 74 0.00 28 [ 0.38]
v3_kernel:'-select_bin_con_2/1-anonymous-0-'/2 117 0.00 28 [ 0.24]
sofs:restrict/4 169 0.00 28 [ 0.17]
v3_core:'-module/2-lc$^1/1-1-'/1 132 0.00 29 [ 0.22]
sys_core_fold:opt_bool_case_in_let_1/5 210 0.00 29 [ 0.14]
sets:'-from_list/1-fun-0-'/2 131 0.00 29 [ 0.22]
lists:keymerge3_1/10 195 0.00 29 [ 0.15]
v3_codegen:guard_cg/5 74 0.00 29 [ 0.39]
beam_block:count_ones/2 137 0.00 29 [ 0.21]
erl_lint:form/2 156 0.00 29 [ 0.19]
erl_expand_records:'-compiler_options/1-lc$^0/1-0-'/1 157 0.00 29 [ 0.18]
sys_core_dsetel:visit_module_1/3 135 0.00 29 [ 0.21]
cerl:binary_segments/1 131 0.00 29 [ 0.22]
compile:'-select_passes/2-anonymous-2-'/3 23 0.00 29 [ 1.26]
v3_kernel:pattern_bin/4 131 0.00 30 [ 0.23]
beam_block:init_yreg/2 138 0.00 30 [ 0.22]
v3_core:form/3 159 0.00 31 [ 0.19]
v3_life:'-guard_clause/5-lc$^0/1-0-'/3 116 0.00 31 [ 0.27]
sys_core_fold:opt_bool_case_in_let/2 210 0.00 31 [ 0.15]
v3_codegen:free_dead/4 136 0.00 31 [ 0.23]
dict:maybe_expand_segs/1 101 0.00 31 [ 0.31]
beam_asm:assemble_1/4 169 0.00 31 [ 0.18]
erl_lint:'-local_functions/1-lc$^0/1-0-'/1 157 0.00 31 [ 0.20]
erl_lint:'-export/3-fun-0-'/3 129 0.00 31 [ 0.24]
cerl:update_c_binary/2 131 0.00 31 [ 0.24]
v3_core:pat_bin/2 131 0.00 32 [ 0.24]
v3_life:'-expr/3-lc$^0/1-10-'/1 136 0.00 32 [ 0.24]
beam_jump:extract_seq/2 138 0.00 32 [ 0.23]
v3_codegen:set_cg/6 144 0.00 32 [ 0.22]
beam_validator:validate_0/3 169 0.00 32 [ 0.19]
beam_validator:heap_alloc_1/2 125 0.00 32 [ 0.26]
erl_expand_records:pattern_bin/2 131 0.00 32 [ 0.24]
erl_expand_records:'-init_calltype/1-lc$^0/1-0-'/1 157 0.00 32 [ 0.20]
v3_life:functions/2 169 0.00 33 [ 0.20]
sys_core_fold:make_vars/3 120 0.00 33 [ 0.28]
v3_core:gexpr/3 68 0.00 34 [ 0.50]
v3_core:constant_bin_1/1 153 0.00 34 [ 0.22]
v3_core:bin_expand_strings/1 131 0.00 34 [ 0.26]
v3_core:upat_bin/3 131 0.00 34 [ 0.26]
v3_life:'-protected/3-lc$^0/1-0-'/3 116 0.00 34 [ 0.29]
lists:rkeymerge3_2/10 260 0.00 34 [ 0.13]
v3_codegen:function/3 168 0.00 34 [ 0.20]
v3_kernel:translate_match_fail/4 71 0.00 34 [ 0.48]
beam_dict:export/4 131 0.00 34 [ 0.26]
erl_lint:eval_file_attr/2 157 0.00 34 [ 0.22]
erl_lint:define_function/4 132 0.00 34 [ 0.26]
sets:rehash/4 153 0.00 35 [ 0.23]
v3_codegen:save_carefully/3 248 0.00 35 [ 0.14]
v3_kernel:function/2 134 0.00 35 [ 0.26]
erl_lint:'-forms/2-fun-0-'/2 156 0.00 35 [ 0.22]
cerl:c_let/3 130 0.00 35 [ 0.27]
beam_clean:'-module/2-lc$^0/1-0-'/1 169 0.00 36 [ 0.21]
beam_bs:bsm_subst_labels_1/4 286 0.00 36 [ 0.13]
v3_codegen:extend_stack/4 107 0.00 36 [ 0.34]
beam_z:'-module/2-lc$^0/1-0-'/1 169 0.00 36 [ 0.21]
cerl:fun_vars/1 151 0.00 36 [ 0.24]
cerl:fun_body/1 151 0.00 36 [ 0.24]
beam_clean:remove_unused/3 169 0.00 37 [ 0.22]
sys_core_fold:'-body/3-lc$^0/1-0-'/3 133 0.00 37 [ 0.28]
beam_flatten:'-module/2-lc$^0/1-0-'/1 169 0.00 37 [ 0.22]
v3_codegen:cg_basic_block/7 107 0.00 37 [ 0.35]
v3_codegen:x0_vars/4 107 0.00 37 [ 0.35]
v3_kernel:'-module/2-anonymous-0-'/1 131 0.00 37 [ 0.28]
beam_receive:'-module/2-lc$^0/1-0-'/1 169 0.00 37 [ 0.22]
beam_validator:validate_2/5 168 0.00 37 [ 0.22]
erl_lint:function_check_max_args/3 132 0.00 37 [ 0.28]
cerl:update_c_fun/3 151 0.00 37 [ 0.25]
cerl:alias_var/1 159 0.00 37 [ 0.23]
cerl:alias_pat/1 159 0.00 37 [ 0.23]
v3_core:expr_bin/3 153 0.00 38 [ 0.25]
beam_flatten:block/1 168 0.00 38 [ 0.23]
beam_flatten:norm_allocate/2 160 0.00 38 [ 0.24]
v3_codegen:max_reg/1 123 0.00 38 [ 0.31]
v3_kernel:'-module/2-anonymous-1-'/2 134 0.00 38 [ 0.28]
beam_reorder:'-module/2-lc$^0/1-0-'/1 169 0.00 38 [ 0.22]
erl_expand_records:expr_bin/2 153 0.00 38 [ 0.25]
sofs:to_external/1 172 0.00 38 [ 0.22]
beam_trim:'-module/2-lc$^0/1-0-'/1 169 0.00 38 [ 0.22]
erlang:min/2 128 0.00 38 [ 0.30]
beam_clean:'-rootset/3-lc$^0/1-0-'/1 169 0.00 39 [ 0.23]
v3_core:new_vars/3 134 0.00 39 [ 0.29]
sys_core_fold:'-module/2-lc$^0/1-0-'/1 135 0.00 39 [ 0.29]
beam_peep:'-module/2-lc$^0/1-0-'/1 169 0.00 39 [ 0.23]
v3_codegen:reserve_x0/2 141 0.00 39 [ 0.28]
beam_bsm:btb_index_2/4 168 0.00 39 [ 0.23]
beam_bsm:'-module/2-lc$^0/1-0-'/2 169 0.00 39 [ 0.23]
erl_lint:set_form_file/2 156 0.00 39 [ 0.25]
erl_lint:check_get_stacktrace/5 171 0.00 39 [ 0.23]
beam_split:'-module/2-lc$^0/1-0-'/1 169 0.00 39 [ 0.23]
beam_except:function/1 168 0.00 39 [ 0.23]
beam_except:dig_out_fc/3 170 0.00 39 [ 0.23]
beam_except:'-module/2-lc$^0/1-0-'/1 169 0.00 39 [ 0.23]
beam_clean:bs_clean_saves/1 168 0.00 40 [ 0.24]
v3_life:vdb_store_new/3 171 0.00 40 [ 0.23]
beam_record:'-module/2-lc$^0/1-0-'/1 169 0.00 40 [ 0.24]
beam_bs:'-module/2-anonymous-0-'/2 168 0.00 40 [ 0.24]
v3_kernel:gexpr_test/2 74 0.00 40 [ 0.54]
beam_validator:validate_3/7 168 0.00 40 [ 0.24]
beam_validator:verify_local_call/3 257 0.00 40 [ 0.16]
cerl_trees:mapfold/3 134 0.00 40 [ 0.30]
sofs:rel2family/1 169 0.00 40 [ 0.24]
gb_sets:balance/2 279 0.00 40 [ 0.14]
beam_a:'-module/2-lc$^0/1-0-'/1 169 0.00 40 [ 0.24]
sys_core_dsetel:'-visit/2-anonymous-7-'/2 180 0.00 40 [ 0.22]
erl_parse:not_string/4 385 0.00 40 [ 0.10]
beam_clean:make_save_point_dict/2 168 0.00 41 [ 0.24]
beam_clean:'-module/2-anonymous-1-'/2 168 0.00 41 [ 0.24]
v3_core:constant_bin/1 153 0.00 41 [ 0.27]
beam_record:function/1 168 0.00 41 [ 0.24]
lists:umergel/3 246 0.00 41 [ 0.17]
beam_jump:find_fixpoint/2 276 0.00 41 [ 0.15]
beam_validator:'-validate_3/7-lc$^0/1-0-'/2 168 0.00 41 [ 0.24]
erl_lint:is_latin1_name/1 172 0.00 41 [ 0.24]
erl_lint:check_qlc_hrl/5 171 0.00 41 [ 0.24]
erl_lint:is_format_function/2 171 0.00 41 [ 0.24]
erl_lint:'-vtold/2-fun-0-'/3 170 0.00 41 [ 0.24]
sofs:relation_to_family/1 169 0.00 41 [ 0.24]
sofs:rel/3 172 0.00 41 [ 0.24]
beam_split:split_blocks/1 168 0.00 41 [ 0.24]
beam_clean:bs_function/1 168 0.00 42 [ 0.25]
beam_jump:'-module/2-lc$^0/1-0-'/1 169 0.00 42 [ 0.25]
sofs:relation/2 171 0.00 42 [ 0.25]
erl_anno:is_filename/1 385 0.00 42 [ 0.11]
v3_core:'-module/2-anonymous-2-'/3 159 0.00 43 [ 0.27]
beam_bs:bsm_opt/2 168 0.00 43 [ 0.26]
beam_utils:empty_label_index/0 168 0.00 43 [ 0.26]
beam_peep:function/1 168 0.00 43 [ 0.26]
v3_codegen:fetch_stack/3 238 0.00 43 [ 0.18]
beam_bsm:function/2 168 0.00 43 [ 0.26]
beam_asm:'-flatten_exports/1-anonymous-0-'/1 168 0.00 43 [ 0.26]
beam_type:'-module/2-lc$^0/1-0-'/1 169 0.00 43 [ 0.25]
erl_lint:check_module_name/3 172 0.00 43 [ 0.25]
erl_expand_records:'-make_list/2-fun-0-'/3 385 0.00 43 [ 0.11]
beam_jump:function/1 168 0.00 44 [ 0.26]
beam_flatten:function/1 168 0.00 44 [ 0.26]
beam_z:function/1 168 0.00 44 [ 0.26]
beam_validator:prune_x_regs/2 154 0.00 44 [ 0.29]
gb_trees:keys/1 168 0.00 44 [ 0.26]
beam_dead:'-module/2-anonymous-0-'/2 168 0.00 44 [ 0.26]
beam_jump:share/1 168 0.00 45 [ 0.27]
v3_kernel:'-uexpr/3-anonymous-23-'/2 178 0.00 45 [ 0.25]
beam_receive:function/1 168 0.00 45 [ 0.27]
beam_validator:index_bs_start_match_1/3 168 0.00 45 [ 0.27]
beam_validator:init_state/1 168 0.00 45 [ 0.27]
beam_block:opt_alloc/4 176 0.00 45 [ 0.26]
erl_expand_records:forms/2 157 0.00 45 [ 0.29]
sofs:diff_restrict_n/5 276 0.00 45 [ 0.16]
beam_trim:function/1 168 0.00 45 [ 0.27]
erl_parse:abstract_list/4 385 0.00 45 [ 0.12]
v3_core:'-uexpr/3-anonymous-0-'/2 188 0.00 46 [ 0.24]
diameter_exprecs:'info-X'/2 385 0.00 46 [ 0.12]
v3_codegen:'-functions/2-anonymous-0-'/3 168 0.00 46 [ 0.27]
v3_kernel:'-select_assert_match_possible/3-anonymous-0-'/2 168 0.00 46 [ 0.27]
beam_validator:validate_1/5 168 0.00 46 [ 0.27]
beam_block:function/1 168 0.00 46 [ 0.27]
beam_block:'-module/2-lc$^0/1-0-'/1 169 0.00 46 [ 0.27]
erl_lint:check_remote_function/5 171 0.00 46 [ 0.27]
v3_core:ufun_clauses/3 151 0.00 47 [ 0.31]
lists:rumergel/3 318 0.00 47 [ 0.15]
diameter_exprecs:'set-X'/2 385 0.00 47 [ 0.12]
diameter_exprecs:'get-X'/2 385 0.00 47 [ 0.12]
beam_a:function/1 168 0.00 47 [ 0.28]
lists:seq_loop/3 307 0.00 48 [ 0.16]
beam_validator:validate_fun_info_branches/3 336 0.00 48 [ 0.14]
beam_type:function/1 168 0.00 48 [ 0.29]
beam_type:'-simplify_select_val_int/2-lc$^0/1-0-'/1 273 0.00 48 [ 0.18]
gb_sets:to_list/1 174 0.00 48 [ 0.28]
core_lib:is_var_used/2 210 0.00 48 [ 0.23]
v3_core:cbody/2 134 0.00 49 [ 0.37]
beam_reorder:function/1 168 0.00 49 [ 0.29]
beam_validator:return_type/2 171 0.00 49 [ 0.29]
erl_lint:'-expr/3-fun-2-'/4 385 0.00 49 [ 0.13]
erl_lint:'-record_def/4-lc$^0/1-0-'/1 412 0.00 50 [ 0.12]
erl_lint:'-expr/3-fun-4-'/4 385 0.00 50 [ 0.13]
beam_dead:shortcut_label/2 198 0.00 50 [ 0.25]
beam_except:function_1/1 168 0.00 50 [ 0.30]
v3_core:body/4 134 0.00 51 [ 0.38]
cerl:values_es/1 199 0.00 51 [ 0.26]
v3_core:new_vars/2 151 0.00 52 [ 0.34]
sets:update_bucket/3 185 0.00 52 [ 0.28]
v3_codegen:cg_fun/7 168 0.00 52 [ 0.31]
v3_codegen:'-x0_vars/4-lc$^0/1-0-'/3 289 0.00 52 [ 0.18]
cerl:ann_make_list/3 170 0.00 52 [ 0.31]
sys_core_bsm:function/3 135 0.00 53 [ 0.39]
v3_kernel:ensure_return_vars/2 178 0.00 53 [ 0.30]
orddict:is_key/2 340 0.00 53 [ 0.16]
erl_expand_records:get_record_field/5 385 0.00 53 [ 0.14]
v3_core:function/4 134 0.00 54 [ 0.40]
eval_bits:expr_grp/3 209 0.00 54 [ 0.26]
v3_codegen:cg_reg_args/2 187 0.00 54 [ 0.29]
v3_kernel:c_apply/5 263 0.00 54 [ 0.21]
erl_lint:'-expr/3-fun-5-'/5 385 0.00 54 [ 0.14]
erl_lint:'-check_option_functions/4-lc$^0/1-0-'/2 471 0.00 54 [ 0.11]
erl_expand_records:strict_get_record_field/5 385 0.00 54 [ 0.14]
sys_core_fold:update_types_from_expr/3 210 0.00 55 [ 0.26]
sys_core_fold:'-sub_add_scope/2-anonymous-0-'/2 213 0.00 55 [ 0.26]
lists:seq/2 185 0.00 55 [ 0.30]
cerl:apply_args/1 246 0.00 55 [ 0.22]
sys_core_fold:'-expr/3-lc$^0/1-0-'/3 200 0.00 56 [ 0.28]
cerl:let_arg/1 226 0.00 56 [ 0.25]
cerl:apply_op/1 246 0.00 56 [ 0.23]
erl_eval:new_bindings/0 209 0.00 57 [ 0.27]
sys_core_fold:delay_build_1/2 385 0.00 57 [ 0.15]
beam_block:opt_move_rev/3 470 0.00 57 [ 0.12]
erl_lint:update_fields/5 385 0.00 57 [ 0.15]
otp_internal:obsolete/3 239 0.00 58 [ 0.24]
otp_internal:obsolete_1/3 239 0.00 58 [ 0.24]
sys_core_fold:delay_build_expr/2 385 0.00 58 [ 0.15]
lists:merge3_12_3/6 394 0.00 58 [ 0.15]
v3_codegen:'-max_reg/1-anonymous-0-'/2 252 0.00 58 [ 0.23]
v3_codegen:'-save_carefully/4-lc$^1/1-1-'/1 248 0.00 58 [ 0.23]
beam_validator:verify_live/2 223 0.00 58 [ 0.26]
erl_expand_records:'-pattern_bin/2-fun-0-'/2 524 0.00 58 [ 0.11]
sys_core_fold:function_1/1 134 0.00 59 [ 0.44]
sys_core_fold:opt_not_in_let_1/3 196 0.00 59 [ 0.30]
beam_validator:kill_heap_allocation/1 293 0.00 59 [ 0.20]
beam_type:live_regs_1/2 315 0.00 59 [ 0.19]
sys_core_fold:delay_build_expr_1/2 385 0.00 60 [ 0.16]
erl_expand_records:'-record_setel/4-fun-2-'/2 383 0.00 60 [ 0.16]
cerl:update_c_apply/3 246 0.00 60 [ 0.24]
v3_life:function/1 168 0.00 61 [ 0.36]
sofs:is_types/2 513 0.00 61 [ 0.12]
erlang:atom_to_binary/2 320 0.00 61 [ 0.19]
sys_core_fold:extract_type/2 210 0.00 62 [ 0.30]
erl_lint:call_function/4 212 0.00 62 [ 0.29]
gb_sets:add_element/2 261 0.00 62 [ 0.24]
beam_clean:add_to_work_list/2 274 0.00 63 [ 0.23]
sys_core_fold:find_fixpoint/3 251 0.00 63 [ 0.25]
v3_codegen:'-cg_fun/7-anonymous-0-'/2 239 0.00 65 [ 0.27]
dict:put_bucket_s/3 202 0.00 65 [ 0.32]
erl_eval:ret_expr/2 636 0.00 66 [ 0.10]
sys_core_fold:is_any_var_used/2 210 0.00 66 [ 0.31]
beam_validator:init_regs/2 237 0.00 66 [ 0.28]
gb_sets:to_list_1/1 279 0.00 66 [ 0.24]
v3_life:'-expr/3-lc$^0/1-12-'/1 288 0.00 67 [ 0.23]
lists:split_2_1/6 318 0.00 67 [ 0.21]
beam_clean:function_replace/3 507 0.00 68 [ 0.13]
erl_lint:deprecated_function/5 239 0.00 68 [ 0.28]
erl_expand_records:'-expr_bin/2-fun-0-'/2 612 0.00 68 [ 0.11]
beam_dict:'-atom_table/2-lc$^0/1-0-'/2 321 0.00 69 [ 0.21]
lists:merge3_21_3/6 462 0.00 70 [ 0.15]
v3_codegen:cg_basic_block/4 355 0.00 71 [ 0.20]
beam_dict:'-literal_table/1-anonymous-1-'/3 329 0.00 71 [ 0.22]
erl_lint:pattern_element_1/4 524 0.00 71 [ 0.14]
erl_expand_records:pattern_element/2 524 0.00 71 [ 0.14]
beam_clean:function_renumber/3 507 0.00 72 [ 0.14]
v3_codegen:save_carefully/4 248 0.00 72 [ 0.29]
v3_kernel:'-ubody/3-anonymous-0-'/2 314 0.00 72 [ 0.23]
gb_sets:from_ordset/1 508 0.00 73 [ 0.14]
lists:rumerge3_21_3/7 529 0.00 75 [ 0.14]
diameter_exprecs:fname/2 323 0.00 75 [ 0.23]
beam_bsm:drop_to_label/2 504 0.00 75 [ 0.15]
erl_internal:bool_op/2 315 0.00 76 [ 0.24]
diameter_exprecs:fname_prefix/1 337 0.00 77 [ 0.23]
beam_validator:verify_live_1/2 587 0.00 77 [ 0.13]
erl_expand_records:bin_element/2 612 0.00 77 [ 0.13]
v3_codegen:make_reservation/2 282 0.00 78 [ 0.28]
v3_codegen:'-x0_vars/4-lc$^0/1-1-'/3 635 0.00 78 [ 0.12]
beam_validator:'-init_regs/2-lc$^0/1-0-'/2 307 0.00 78 [ 0.25]
beam_dict:'-literal_table/1-lc$^1/1-0-'/1 330 0.00 78 [ 0.24]
dict:fetch/2 336 0.00 79 [ 0.24]
erl_lint:pattern_element/4 524 0.00 79 [ 0.15]
beam_validator:validate_fun_info_branches_1/3 407 0.00 80 [ 0.20]
sofs:rel/4 669 0.00 80 [ 0.12]
erl_expand_records:'-field_names/1-fun-0-'/1 385 0.00 83 [ 0.22]
beam_except:translate_exception/4 773 0.00 83 [ 0.11]
erl_lint:is_autoimport_suppressed/2 314 0.00 84 [ 0.27]
sofs:atoms_only/2 512 0.00 84 [ 0.16]
core_lib:'-vu_expr/2-anonymous-4-'/2 389 0.00 84 [ 0.22]
beam_validator:merge_types/2 280 0.00 85 [ 0.30]
erl_lint:is_warn_enabled/2 305 0.00 85 [ 0.28]
sys_core_fold:sub_set_name/3 495 0.00 86 [ 0.17]
diameter_exprecs:'-#info-X/1/2-fun-0-'/2 385 0.00 86 [ 0.22]
diameter_exprecs:'-#set-X/2/2-fun-0-'/2 385 0.00 86 [ 0.22]
beam_asm:encode1/2 702 0.00 86 [ 0.12]
erl_lint:bin_element/4 612 0.00 86 [ 0.14]
diameter_exprecs:'-#get-X/2/2-fun-0-'/2 385 0.00 87 [ 0.23]
v3_codegen:'-cg_basic_block/7-anonymous-0-'/4 355 0.00 87 [ 0.25]
erl_lint:'-update_fields/5-fun-0-'/3 385 0.00 91 [ 0.24]
erl_expand_records:is_simple_val/1 385 0.00 91 [ 0.24]
beam_validator:tail_call/3 639 0.00 92 [ 0.14]
erl_lint:'-normalise_fields/1-fun-0-'/1 394 0.00 92 [ 0.23]
lists:keymember/3 596 0.00 92 [ 0.15]
v3_core:new_vars_1/4 661 0.00 93 [ 0.14]
lists:rmerge3_12_3/6 677 0.00 93 [ 0.14]
erl_lint:check_fields/6 487 0.00 93 [ 0.19]
diameter_exprecs:'-fields/2-fun-0-'/1 385 0.00 94 [ 0.24]
erl_expand_records:'-normalise_fields/1-fun-0-'/1 394 0.00 94 [ 0.24]
erl_anno:set_file/2 385 0.00 94 [ 0.24]
erl_internal:comp_op/2 315 0.00 96 [ 0.30]
beam_validator:assert_type/2 553 0.00 96 [ 0.17]
maps:to_list/1 532 0.00 96 [ 0.18]
v3_core:'-cexpr/3-anonymous-1-'/3 770 0.00 97 [ 0.13]
v3_codegen:allocate_x0/3 389 0.00 97 [ 0.25]
erl_lint:'-def_fields/3-fun-0-'/3 394 0.00 97 [ 0.25]
sys_core_fold:opt_simple_let/3 725 0.00 99 [ 0.14]
lists:dropwhile/2 672 0.00 99 [ 0.15]
beam_jump:opt/2 168 0.00 99 [ 0.59]
erl_lint:is_local_function/2 331 0.00 99 [ 0.30]
sets:is_element/2 442 0.00 100 [ 0.23]
v3_life:'-function/1-lc$^0/1-1-'/1 407 0.00 101 [ 0.25]
erl_anno:set_generated/2 788 0.00 101 [ 0.13]
beam_jump:insert_fc_labels/2 552 0.00 103 [ 0.19]
erl_expand_records:is_in_guard/0 385 0.00 103 [ 0.27]
erl_expand_records:'-record_setel/4-fun-0-'/4 383 0.00 103 [ 0.27]
sys_core_fold:delay_build/2 385 0.00 105 [ 0.27]
v3_life:'-function/1-lc$^0/1-0-'/1 407 0.00 106 [ 0.26]
v3_codegen:'-cg_reg_args/2-lc$^0/1-0-'/2 510 0.00 106 [ 0.21]
beam_validator:verify_y_init_1/1 846 0.00 106 [ 0.13]
beam_validator:'-prune_x_regs/2-lc$^0/1-0-'/2 467 0.00 106 [ 0.23]
v3_core:'-bin_expand_strings/1-anonymous-1-'/2 524 0.00 107 [ 0.20]
sys_core_fold:opt_simple_let_2/7 725 0.00 107 [ 0.15]
dict:store/3 518 0.00 107 [ 0.21]
beam_except:translate_1/5 856 0.00 107 [ 0.13]
erl_expand_records:record_update/5 385 0.00 108 [ 0.28]
beam_bs:bsm_subst_label/3 444 0.00 109 [ 0.25]
gb_sets:from_list/1 508 0.00 109 [ 0.21]
v3_kernel:get_free/3 297 0.00 110 [ 0.37]
beam_dict:literal/2 400 0.00 110 [ 0.28]
erl_lint:record_field/4 770 0.00 110 [ 0.14]
binary:encode_unsigned/1 702 0.00 110 [ 0.16]
sys_core_fold:move_let_into_expr/3 728 0.00 111 [ 0.15]
sys_core_fold:opt_simple_let_0/3 725 0.00 111 [ 0.15]
beam_utils:is_killed_block/2 436 0.00 111 [ 0.25]
erl_expand_records:record_setel/4 383 0.00 111 [ 0.29]
erlang:iolist_size/1 703 0.00 111 [ 0.16]
erl_lint:bif_clash_specifically_disabled/2 280 0.00 112 [ 0.40]
erl_expand_records:record_exprs/4 770 0.00 112 [ 0.15]
cerl:data_type/1 385 0.00 112 [ 0.29]
sys_core_fold:opt_simple_let_1/4 725 0.00 113 [ 0.16]
erl_expand_records:call_error/2 385 0.00 113 [ 0.29]
cerl:bitstr_type/1 524 0.00 113 [ 0.22]
v3_core:verify_suitable_fields/1 765 0.00 114 [ 0.15]
v3_core:fold_match/2 385 0.00 114 [ 0.30]
lists:usplit_2_1/6 641 0.00 114 [ 0.18]
cerl:bitstr_size/1 524 0.00 114 [ 0.22]
cerl:bitstr_unit/1 524 0.00 114 [ 0.22]
eval_bits:expr_grp/4 877 0.00 115 [ 0.13]
beam_jump:'-opt/2-anonymous-0-'/2 276 0.00 115 [ 0.42]
erl_lint:'-pattern_bin/5-fun-0-'/4 524 0.00 117 [ 0.22]
cerl:bitstr_flags/1 524 0.00 117 [ 0.22]
erlang:'--'/2 172 0.00 117 [ 0.68]
sys_core_fold:is_compiler_generated/1 990 0.00 118 [ 0.12]
cerl:bitstr_val/1 524 0.00 118 [ 0.23]
erl_lint:pattern_list/5 770 0.00 119 [ 0.15]
sofs:is_type/1 514 0.00 119 [ 0.23]
sys_core_bsm:bsm_an_1/2 859 0.00 120 [ 0.14]
cerl_sets:from_list/1 949 0.00 122 [ 0.13]
sys_core_fold:update_let_types_1/3 935 0.00 123 [ 0.13]
lists:merge2_1/4 837 0.00 123 [ 0.15]
lists:rmerge2_2/5 863 0.00 123 [ 0.14]
v3_core:'-uexpr/3-anonymous-1-'/2 550 0.00 124 [ 0.23]
sys_core_dsetel:'-visit/2-anonymous-1-'/2 550 0.00 124 [ 0.23]
lists:duplicate/2 497 0.00 125 [ 0.25]
cerl:update_c_bitstr/6 524 0.00 126 [ 0.24]
v3_core:coerce_to_float/2 524 0.00 127 [ 0.24]
v3_codegen:'-extend_stack/4-lc$^0/1-0-'/4 924 0.00 127 [ 0.14]
erl_lint:pat_bit_size/4 524 0.00 127 [ 0.24]
sys_core_fold:eval_setelement/4 766 0.00 129 [ 0.17]
sys_core_fold:'-let_substs/3-anonymous-1-'/2 495 0.00 130 [ 0.26]
beam_block:eliminate_use_of_from_reg/4 487 0.00 130 [ 0.27]
v3_core:upat_element/4 524 0.00 131 [ 0.25]
dict:'-store/3-fun-0-'/3 518 0.00 132 [ 0.25]
v3_core:lit_list_vars/2 906 0.00 133 [ 0.15]
beam_jump:remove_unused_labels/1 504 0.00 133 [ 0.26]
erl_lint:is_pattern_expr/1 524 0.00 133 [ 0.25]
sys_core_fold:bit_pat_warn_int/4 1048 0.00 134 [ 0.13]
sys_core_fold:'-sub_subst_var/3-lc$^0/1-0-'/3 598 0.00 134 [ 0.22]
v3_codegen:turn_yregs/2 531 0.00 134 [ 0.25]
v3_kernel:pat_list_vars/1 894 0.00 134 [ 0.15]
erl_lint:is_pattern_expr_1/1 524 0.00 134 [ 0.26]
v3_core:pat_segment/2 524 0.00 135 [ 0.26]
erl_lint:'-expr_bin/4-fun-0-'/4 612 0.00 135 [ 0.22]
beam_validator:assert_type/3 553 0.00 136 [ 0.25]
erl_lint:pat_bit_expr/4 524 0.00 136 [ 0.26]
erl_anno:reset_simplify/1 1173 0.00 136 [ 0.12]
erl_lint:imported/3 412 0.00 138 [ 0.33]
v3_core:'-pat_bin/2-lc$^0/1-0-'/2 655 0.00 139 [ 0.21]
erl_anno:simplify/1 1173 0.00 139 [ 0.12]
sys_core_fold:kill_types2/2 529 0.00 140 [ 0.26]
v3_kernel:select_bin_int_1/4 407 0.00 140 [ 0.34]
sys_core_dsetel:bind_vars/3 549 0.00 141 [ 0.26]
lists:rmergel/2 934 0.00 143 [ 0.15]
beam_validator:'-index_bs_start_match/2-anonymous-0-'/2 672 0.00 143 [ 0.21]
erl_anno:set_anno/3 1173 0.00 143 [ 0.12]
erl_lint:has_wildcard_field/1 770 0.00 144 [ 0.19]
erl_lint:'-expr/3-fun-6-'/3 612 0.00 144 [ 0.24]
lists:merge2_2/5 935 0.00 145 [ 0.16]
beam_jump:insert_labels/4 1191 0.00 145 [ 0.12]
erl_lint:bit_size/4 612 0.00 145 [ 0.24]
erl_eval:line/1 636 0.00 146 [ 0.23]
beam_dict:import/4 535 0.00 146 [ 0.27]
sys_core_fold:'-expr/3-lc$^0/1-3-'/2 626 0.00 148 [ 0.24]
beam_utils:live_opt/1 504 0.00 148 [ 0.29]
beam_validator:all_ms_in_x_regs/2 863 0.00 148 [ 0.17]
sys_core_fold:copy_type/3 495 0.00 149 [ 0.30]
sys_core_fold:bin_pattern/2 1048 0.00 150 [ 0.14]
lists:merge3_2/6 870 0.00 150 [ 0.17]
erl_parse:map_anno/2 1155 0.00 150 [ 0.13]
sys_core_fold:sub_subst_var/3 495 0.00 152 [ 0.31]
erl_eval:partial_eval/1 636 0.00 153 [ 0.24]
gb_sets:balance_list/2 787 0.00 153 [ 0.19]
erl_anno:set/3 1173 0.00 154 [ 0.13]
v3_core:bin_element/1 612 0.00 155 [ 0.25]
v3_kernel:'-select_bin_con_1/1-anonymous-0-'/1 655 0.00 157 [ 0.24]
v3_core:upat_bin/4 655 0.00 158 [ 0.24]
eval_bits:eval_exp_field1/6 668 0.00 158 [ 0.24]
erl_internal:bif/2 497 0.00 159 [ 0.32]
sys_core_fold:fold_call_2/5 945 0.00 159 [ 0.17]
v3_codegen:match_cg/6 938 0.00 159 [ 0.17]
v3_codegen:'-top_level_block/4-anonymous-0-'/3 600 0.00 159 [ 0.27]
erl_eval:ev_expr/1 636 0.00 160 [ 0.25]
v3_kernel:'-uexpr/3-anonymous-11-'/2 669 0.00 160 [ 0.24]
beam_asm:to_bytes/1 702 0.00 162 [ 0.23]
v3_kernel:pattern_bin_1/4 655 0.00 165 [ 0.25]
v3_codegen:turn_yreg/2 690 0.00 167 [ 0.24]
lists:merge3_1/6 924 0.00 168 [ 0.18]
erl_expand_records:mark_record/2 489 0.00 168 [ 0.34]
beam_validator:labels_1/2 843 0.00 172 [ 0.20]
v3_core:'-expr_bin/3-lc$^0/1-0-'/1 765 0.00 174 [ 0.23]
sys_core_fold:fold_non_lit_args/5 945 0.00 174 [ 0.18]
lists:mergel/2 1262 0.00 174 [ 0.14]
eval_bits:eval_exp_field/6 668 0.00 174 [ 0.26]
erl_parse:abstract/3 787 0.00 174 [ 0.22]
lists:flatmap/2 732 0.00 175 [ 0.24]
core_lib:vu_expr/2 956 0.00 177 [ 0.19]
beam_validator:deallocate/1 673 0.00 178 [ 0.26]
erl_lint:warn_invalid_record/3 770 0.00 178 [ 0.23]
erl_expand_records:record_exprs/2 385 0.00 178 [ 0.46]
maps:get/2 1291 0.00 178 [ 0.14]
beam_bs:bsm_reroute/4 1362 0.00 179 [ 0.13]
v3_codegen:finish_select_binary/1 775 0.00 179 [ 0.23]
dict:fetch_val/2 1124 0.00 179 [ 0.16]
beam_validator:verify_no_ct/1 673 0.00 179 [ 0.27]
sys_core_fold:update_let_types/3 725 0.00 181 [ 0.25]
beam_utils:is_killed/3 773 0.00 181 [ 0.23]
erl_lint:vtmerge/1 612 0.00 181 [ 0.30]
v3_core:'-new_in_all/1-anonymous-0-'/2 770 0.00 182 [ 0.24]
erl_lint:is_valid_record/1 770 0.00 185 [ 0.24]
maps:size/1 391 0.00 187 [ 0.48]
beam_utils:is_killed_at/3 1176 0.00 188 [ 0.16]
beam_record:is_killed/4 772 0.00 189 [ 0.24]
beam_validator:verify_call_args/3 724 0.00 191 [ 0.26]
v3_codegen:local_func_label/2 448 0.00 193 [ 0.43]
sys_core_fold:simplify_let/2 728 0.00 194 [ 0.27]
beam_block:is_killed_or_used/2 801 0.00 194 [ 0.24]
erl_expand_records:new_var/2 772 0.00 194 [ 0.25]
v3_core:'-uexpr/3-anonymous-6-'/3 770 0.00 196 [ 0.25]
beam_validator:verify_y_init/1 727 0.00 196 [ 0.27]
beam_utils:index_labels/1 840 0.00 197 [ 0.23]
dict:rehash/4 848 0.00 199 [ 0.23]
sys_core_fold:opt_not_in_let_0/3 667 0.00 200 [ 0.30]
erl_expand_records:no_compiler_warning/1 770 0.00 200 [ 0.26]
lists:usplit_1_1/6 1023 0.00 201 [ 0.20]
eval_bits:make_bit_type/3 724 0.00 201 [ 0.28]
cerl:case_arg/1 859 0.00 201 [ 0.23]
erl_expand_records:index_expr/4 768 0.00 202 [ 0.26]
sys_core_fold:opt_case_in_let/1 728 0.00 204 [ 0.28]
v3_core:'-uexpr/3-anonymous-4-'/2 924 0.00 205 [ 0.22]
sys_core_fold:opt_not_in_let/1 725 0.00 205 [ 0.28]
lists:umerge3_2/7 1314 0.00 206 [ 0.16]
sys_core_fold:let_substs/3 728 0.00 208 [ 0.29]
erl_expand_records:new_var_name/1 772 0.00 208 [ 0.27]
erlang:make_fun/3 962 0.00 208 [ 0.22]
sys_core_fold:let_substs_1/3 728 0.00 210 [ 0.29]
sys_core_fold:case_opt_arg_1/3 1705 0.00 211 [ 0.12]
cerl:update_c_case/3 859 0.00 211 [ 0.25]
lists:umerge3_1/7 1183 0.01 216 [ 0.18]
beam_except:dig_out/2 856 0.01 218 [ 0.25]
v3_core:uclauses/3 773 0.01 219 [ 0.28]
sys_core_fold:add_warning/2 853 0.01 220 [ 0.26]
erl_lint:record_expr/4 770 0.01 220 [ 0.29]
sys_core_fold:should_suppress_warning/1 853 0.01 222 [ 0.26]
sys_core_fold:'-let_substs/3-lc$^0/1-0-'/1 941 0.01 223 [ 0.24]
sys_core_fold:'-warn_no_clause_match/2-anonymous-1-'/1 990 0.01 225 [ 0.23]
ordsets:del_element/2 892 0.01 225 [ 0.25]
v3_life:'-expr/3-lc$^0/1-8-'/1 938 0.01 226 [ 0.24]
sys_core_fold:matches_data/2 728 0.01 228 [ 0.31]
beam_validator:verify_call_args_1/2 1746 0.01 229 [ 0.13]
lists:last/2 1769 0.01 231 [ 0.13]
erl_lint:expr_var/4 1858 0.01 231 [ 0.12]
beam_validator:merge_y_regs_1/3 2020 0.01 232 [ 0.11]
v3_kernel:handle_reuse_annos/2 876 0.01 233 [ 0.27]
erl_expand_records:'-record_setel/4-lc$^1/1-0-'/1 766 0.01 233 [ 0.30]
sys_core_fold:sub_add_scope/2 728 0.01 235 [ 0.32]
lists:rmerge3_1/6 1174 0.01 236 [ 0.20]
beam_utils:check_liveness_block_1/6 1971 0.01 237 [ 0.12]
erl_lint:pat_var/5 1823 0.01 237 [ 0.13]
v3_core:new_in_all/1 773 0.01 239 [ 0.31]
lists:umerge2_1/5 1700 0.01 239 [ 0.14]
v3_core:cclauses/3 924 0.01 242 [ 0.26]
dict:fold/3 1930 0.01 242 [ 0.13]
erl_lint:elemtype_check/4 1136 0.01 242 [ 0.21]
sys_core_fold:'-pattern/3-anonymous-1-'/2 1048 0.01 246 [ 0.23]
erl_lint:'-copy_expr/2-fun-0-'/2 1155 0.01 246 [ 0.21]
beam_jump:maps_append_list/3 985 0.01 248 [ 0.25]
erlang:md5/1 1 0.01 248 [ 248.00]
v3_kernel:kmatch/4 859 0.01 250 [ 0.29]
beam_dead:shortcut_specific_label/3 1840 0.01 252 [ 0.14]
lists:rmerge3_2/6 1557 0.01 254 [ 0.16]
v3_kernel:'-expand_pat_lit/2-lc$^0/1-0-'/2 1155 0.01 255 [ 0.22]
v3_kernel:flatten_seq/1 859 0.01 257 [ 0.30]
beam_dict:line/2 758 0.01 257 [ 0.34]
v3_codegen:select_extract_tuple/6 846 0.01 258 [ 0.30]
lists:rmerge2_1/4 1873 0.01 261 [ 0.14]
eval_bits:eval_field/3 668 0.01 262 [ 0.39]
v3_codegen:return_cg/5 1844 0.01 262 [ 0.14]
beam_except:dig_out_block/1 788 0.01 262 [ 0.33]
v3_kernel:is_in_guard/1 913 0.01 266 [ 0.29]
beam_dead:combine_eqs/4 962 0.01 266 [ 0.28]
lists:rumerge3_12_3/7 2027 0.01 268 [ 0.13]
erl_lint:check_record/4 1206 0.01 268 [ 0.22]
v3_kernel:force_variable/2 903 0.01 270 [ 0.30]
sys_core_fold:signedness/1 1048 0.01 271 [ 0.26]
v3_codegen:'-save_carefully/4-lc$^0/1-0-'/4 2018 0.01 271 [ 0.13]
beam_utils:check_liveness_at/3 1182 0.01 272 [ 0.23]
v3_kernel:match_pre/3 859 0.01 272 [ 0.32]
lists:rumerge2_2/5 2033 0.01 273 [ 0.13]
erl_lint:bit_type/4 1136 0.01 274 [ 0.24]
erl_expand_records:'-pattern_fields/2-fun-0-'/3 1155 0.01 274 [ 0.24]
erl_anno:default/2 1173 0.01 275 [ 0.23]
v3_kernel:build_match/2 859 0.01 282 [ 0.33]
sys_core_fold:'-var_list/2-anonymous-0-'/2 1067 0.01 283 [ 0.27]
erl_expand_records:'-record_inits/2-fun-0-'/3 1155 0.01 284 [ 0.25]
v3_core:novars/2 1155 0.01 285 [ 0.25]
maps:from_list/1 1479 0.01 285 [ 0.19]
v3_codegen:'-match_cg/5-anonymous-1-'/6 2140 0.01 287 [ 0.13]
v3_kernel:match_vars/2 859 0.01 288 [ 0.34]
erl_lint:bit_size_check/4 1136 0.01 288 [ 0.25]
erl_lint:add_bit_size/5 1136 0.01 288 [ 0.25]
v3_kernel:select_bin_con_2/1 2206 0.01 289 [ 0.13]
erl_lint:copy_expr/2 1155 0.01 291 [ 0.25]
erl_parse:'-map_anno/2-fun-0-'/3 1155 0.01 292 [ 0.25]
beam_peep:is_test_redundant_1/3 2768 0.01 293 [ 0.11]
v3_core:make_bit_type/3 1136 0.01 295 [ 0.26]
beam_flatten:move_past_kill/3 1329 0.01 296 [ 0.22]
gb_trees:balance/2 2225 0.01 296 [ 0.13]
sys_core_fold:let_subst_list/3 1436 0.01 302 [ 0.21]
sys_core_fold:var_list/2 1013 0.01 302 [ 0.30]
io_lib:latin1_char_list/1 2698 0.01 302 [ 0.11]
sys_core_fold:bin_pat_warn/1 1048 0.01 306 [ 0.29]
beam_validator:validate_src/2 1153 0.01 306 [ 0.27]
v3_core:force_novars/2 1155 0.01 308 [ 0.27]
cerl:c_tuple/1 1158 0.01 308 [ 0.27]
lists:usort/1 2390 0.01 309 [ 0.13]
v3_codegen:load_vars/2 1023 0.01 310 [ 0.30]
erl_lint:warn_unused_vars/3 2645 0.01 310 [ 0.12]
beam_jump:drop_upto_label/1 1534 0.01 311 [ 0.20]
v3_codegen:enter_cg/6 1610 0.01 311 [ 0.19]
cerl:call_name/1 1398 0.01 311 [ 0.22]
beam_validator:'-validate_src/2-anonymous-0-'/2 1344 0.01 312 [ 0.23]
erl_lint:guard_tests/3 2628 0.01 312 [ 0.12]
erl_bits:set_bit_1/2 2784 0.01 314 [ 0.11]
sets:get_bucket_s/2 1919 0.01 315 [ 0.16]
beam_validator:kill_state/1 2080 0.01 315 [ 0.15]
erl_anno:is_settable/2 1173 0.01 316 [ 0.27]
cerl:update_c_tuple_skel/2 1279 0.01 316 [ 0.25]
cerl:call_args/1 1398 0.01 316 [ 0.23]
erl_expand_records:strict_record_tests/1 2310 0.01 319 [ 0.14]
cerl:call_module/1 1398 0.01 321 [ 0.23]
lists:umerge3_12_3/6 2562 0.01 323 [ 0.13]
beam_validator:merge_states_1/2 2020 0.01 323 [ 0.16]
erl_lint:'-init_fields/3-lc$^0/1-0-'/3 1206 0.01 323 [ 0.27]
v3_core:fail_clause/3 1158 0.01 324 [ 0.28]
v3_core:'-constant_bin_1/1-anonymous-0-'/2 1224 0.01 324 [ 0.26]
sys_core_fold:will_fail/1 1218 0.01 326 [ 0.27]
v3_kernel:match_con_1/4 2105 0.01 327 [ 0.16]
erl_expand_records:strict_record_updates/1 2310 0.01 329 [ 0.14]
erl_lint:check_unused_vars/3 2611 0.01 330 [ 0.13]
v3_kernel:select_bin_con_1/1 2105 0.01 335 [ 0.16]
v3_kernel:'-handle_reuse_annos/2-lc$^0/1-0-'/2 1796 0.01 337 [ 0.19]
erl_expand_records:record_fields/2 1291 0.01 337 [ 0.26]
erl_lint:'-init_fields/6-fun-1-'/3 1155 0.01 341 [ 0.30]
cerl:ann_c_cons/3 2543 0.01 342 [ 0.13]
cerl:update_c_call/4 1398 0.01 342 [ 0.24]
lists:foreach/2 2506 0.01 345 [ 0.14]
dict:fold_dict/3 1930 0.01 349 [ 0.18]
beam_type:merge_type_info/2 1582 0.01 351 [ 0.22]
beam_dead:shortcut_bs_test_1/4 3060 0.01 354 [ 0.12]
v3_kernel:match_con/4 2105 0.01 356 [ 0.17]
beam_jump:collect_labels_1/3 1976 0.01 359 [ 0.18]
erl_lint:used_record/2 1291 0.01 359 [ 0.28]
lists:rumerge2_1/4 2847 0.01 361 [ 0.13]
beam_utils:'-live_opt/1-anonymous-0-'/1 1512 0.01 364 [ 0.24]
v3_codegen:match_fmf/4 2233 0.01 369 [ 0.17]
erl_bifs:is_safe/3 1414 0.01 370 [ 0.26]
beam_dict:fname/2 755 0.01 371 [ 0.49]
ordsets:from_list/1 2210 0.01 373 [ 0.17]
v3_kernel:select_bin_int/1 2105 0.01 374 [ 0.18]
erl_lint:'-pattern_list/5-fun-0-'/5 1540 0.01 374 [ 0.24]
v3_core:ufun_clause/3 2747 0.01 376 [ 0.14]
erl_lint:'-check_fields/6-fun-0-'/6 1540 0.01 376 [ 0.24]
erl_lint:vtnew/2 2696 0.01 379 [ 0.14]
beam_dead:shortcut_select_list/4 2588 0.01 384 [ 0.15]
v3_core:'-uclauses/3-anonymous-0-'/3 1543 0.01 385 [ 0.25]
v3_core:uclause/3 2316 0.01 386 [ 0.17]
sys_core_fold:call_1/5 2860 0.01 387 [ 0.14]
dict:get_bucket_s/2 2149 0.01 387 [ 0.18]
lists:last/1 1352 0.01 389 [ 0.29]
beam_block:opt_tuple_element_1/4 1665 0.01 389 [ 0.23]
cerl:data_arity/1 385 0.01 389 [ 1.01]
v3_codegen:trap_bif/3 1397 0.01 394 [ 0.28]
erl_lint:'-vtmerge/1-fun-0-'/2 1836 0.01 394 [ 0.21]
lists:partition/4 2764 0.01 398 [ 0.14]
sys_core_fold:fold_call/5 2860 0.01 404 [ 0.14]
v3_kernel:is_remote_bif/3 1397 0.01 408 [ 0.29]
v3_core:'-lit_list_vars/2-anonymous-0-'/2 1869 0.01 411 [ 0.22]
erl_lint:check_field/7 1540 0.01 413 [ 0.27]
beam_dead:shortcut_rel_op_fp/3 3432 0.01 419 [ 0.12]
erl_internal:op_type/2 1187 0.01 422 [ 0.36]
cerl:var_name/1 1705 0.01 423 [ 0.25]
beam_record:is_tagged_tuple/4 789 0.01 424 [ 0.54]
erl_lint:'-unused_vars/3-fun-0-'/2 1874 0.01 432 [ 0.23]
erl_internal:guard_bif/2 1241 0.01 434 [ 0.35]
v3_core:new_var/2 1636 0.01 436 [ 0.27]
v3_codegen:move_unsaved/4 3556 0.01 436 [ 0.12]
lists:droplast/1 1734 0.01 440 [ 0.25]
v3_kernel:op_vars/1 1486 0.01 440 [ 0.30]
sets:get_bucket/2 1901 0.01 441 [ 0.23]
v3_life:call_op/1 1678 0.01 443 [ 0.26]
sys_core_fold:move_case_into_arg/2 1766 0.01 443 [ 0.25]
cerl:is_c_var/1 1844 0.01 446 [ 0.24]
beam_dead:normalize_op_1/3 3569 0.01 448 [ 0.13]
v3_kernel:'-ubody/3-anonymous-1-'/2 1878 0.01 451 [ 0.24]
dict:find/2 1660 0.01 451 [ 0.27]
v3_life:'-expr/3-lc$^0/1-3-'/1 1844 0.01 455 [ 0.25]
sys_core_fold:get_line/1 1891 0.01 460 [ 0.24]
beam_utils:check_liveness_block_2/4 1954 0.01 460 [ 0.24]
lists:umerge3_21_3/6 3631 0.01 460 [ 0.13]
beam_dead:will_succeed/2 1739 0.01 461 [ 0.27]
v3_codegen:enter_line/3 1609 0.01 463 [ 0.29]
sets:get_slot/2 1901 0.01 464 [ 0.24]
v3_codegen:func_vars/1 1678 0.01 468 [ 0.28]
lists:rumerge3_2/7 2857 0.01 470 [ 0.16]
v3_codegen:select_cg/6 2140 0.01 471 [ 0.22]
sys_core_fold:is_boolean_type/2 1874 0.01 477 [ 0.25]
dict:get_bucket/2 2048 0.01 479 [ 0.23]
sys_core_fold:case_expand_var/2 1705 0.01 482 [ 0.28]
beam_validator:min/2 2020 0.01 482 [ 0.24]
sys_core_fold:warn_no_clause_match/2 1766 0.01 486 [ 0.28]
beam_type:tdb_kill_xregs/1 3424 0.01 486 [ 0.14]
gb_sets:add/2 2174 0.01 488 [ 0.22]
cerl:is_c_values/1 1831 0.01 488 [ 0.27]
erl_bits:as_list/1 1860 0.01 490 [ 0.26]
sys_core_fold:'-call_1/5-lc$^0/1-0-'/2 1958 0.01 492 [ 0.25]
erl_bits:merge_bittype/2 2060 0.01 495 [ 0.24]
sys_core_fold:fold_call_1/5 2857 0.01 496 [ 0.17]
dict:mk_seg/1 1933 0.01 497 [ 0.26]
sys_core_fold:get_type/2 1874 0.01 499 [ 0.27]
erl_expand_records:find_field/2 2312 0.01 499 [ 0.22]
erl_bits:check_unit/1 2272 0.01 508 [ 0.22]
sys_core_fold:case_opt_arg/4 1844 0.01 513 [ 0.28]
beam_validator:merge_y_regs/2 2020 0.01 515 [ 0.25]
sys_core_fold:case_opt/3 1766 0.01 518 [ 0.29]
gb_trees:to_list_1/1 2225 0.01 518 [ 0.23]
v3_kernel:match_guard/3 4142 0.01 524 [ 0.13]
v3_codegen:'-saves/3-lc$^0/1-0-'/3 4562 0.01 525 [ 0.12]
sys_core_fold:opt_bool_case/2 1766 0.01 526 [ 0.30]
v3_life:type/1 2140 0.01 528 [ 0.25]
beam_validator:valfun_2/2 3927 0.01 529 [ 0.13]
beam_type:tag_literal/1 2146 0.01 532 [ 0.25]
beam_split:make_block/2 3875 0.01 532 [ 0.14]
sys_core_dsetel:'-visit/2-anonymous-4-'/2 2362 0.01 534 [ 0.23]
dict:new/0 1933 0.01 536 [ 0.28]
erlang:tuple_to_list/1 3749 0.01 537 [ 0.14]
v3_core:'-uexpr/3-anonymous-5-'/2 2362 0.01 538 [ 0.23]
erl_bifs:is_exit_bif/3 3414 0.01 538 [ 0.16]
sys_core_fold:call/4 2860 0.01 539 [ 0.19]
beam_jump:initial_labels/2 2844 0.01 539 [ 0.19]
sys_core_fold:eval_case/2 1766 0.01 540 [ 0.31]
sys_core_fold:shadow_warning/2 2619 0.01 541 [ 0.21]
sys_core_fold:is_bool_expr/2 1976 0.01 542 [ 0.27]
lists:partition/2 2109 0.01 543 [ 0.26]
beam_validator:valfun_3/2 3927 0.01 543 [ 0.14]
v3_codegen:build_enter/3 1609 0.01 544 [ 0.34]
beam_utils:check_liveness_block/3 1996 0.01 545 [ 0.27]
v3_kernel:call_type/3 1398 0.01 549 [ 0.39]
dict:fold_segs/4 3826 0.01 549 [ 0.14]
beam_validator:set_type_reg/3 3543 0.01 553 [ 0.16]
sys_core_fold:case_will_var_match/1 1844 0.01 555 [ 0.30]
v3_core:annotate_cons/4 2271 0.01 559 [ 0.25]
cerl_sets:new/0 2155 0.01 565 [ 0.26]
v3_kernel:uexpr/3 2891 0.01 572 [ 0.20]
v3_codegen:find_loc/3 3500 0.01 576 [ 0.16]
v3_kernel:'-uexpr/3-anonymous-13-'/2 2464 0.01 580 [ 0.24]
orddict:erase/2 3096 0.01 580 [ 0.19]
beam_validator:'-valfun_4/2-anonymous-1-'/2 2588 0.01 586 [ 0.23]
beam_dead:prune_redundant/2 2588 0.01 591 [ 0.23]
lists:usplit_1/5 3479 0.01 592 [ 0.17]
erlang:atom_to_list/1 886 0.01 595 [ 0.67]
v3_kernel:partition_intersection/4 2140 0.01 599 [ 0.28]
v3_kernel:'-match_con_1/4-anonymous-0-'/3 2140 0.01 600 [ 0.28]
erl_parse:abstract/2 17 0.01 602 [ 35.41]
v3_life:type_clause/5 2140 0.01 607 [ 0.28]
v3_codegen:select_val_cg/6 1904 0.01 608 [ 0.32]
erl_lint:expr_list/3 4097 0.01 608 [ 0.15]
erl_lint:'-clauses/2-fun-0-'/2 2560 0.01 609 [ 0.24]
v3_codegen:fetch_reg/2 3078 0.01 611 [ 0.20]
beam_dead:shortcut_select_label/4 2453 0.01 611 [ 0.25]
v3_kernel:select_bin_con/1 2105 0.01 622 [ 0.30]
sys_core_fold:'-signedness/1-lc$^0/1-0-'/1 3144 0.01 626 [ 0.20]
beam_peep:prune_redundant_values/2 2633 0.01 629 [ 0.24]
erl_lint:head/3 2560 0.01 632 [ 0.25]
v3_kernel:build_select/2 2105 0.01 634 [ 0.30]
erl_lint:clause/2 2560 0.01 638 [ 0.25]
erl_lint:guard/3 2594 0.01 638 [ 0.25]
v3_kernel:atomic_list/3 1784 0.01 639 [ 0.36]
beam_validator:branch_state/2 3952 0.01 640 [ 0.16]
v3_kernel:match_value/5 2140 0.02 642 [ 0.30]
beam_validator:get_move_term_type/2 2612 0.02 642 [ 0.25]
beam_type:tdb_update/2 4792 0.02 647 [ 0.14]
erl_lint:unused_vars/3 2645 0.02 650 [ 0.25]
beam_utils:check_liveness/3 2812 0.02 653 [ 0.23]
v3_core:'-ufun_clauses/3-anonymous-0-'/3 2596 0.02 656 [ 0.25]
erl_bits:type_to_record/1 2784 0.02 659 [ 0.24]
erlang:throw/1 2616 0.02 661 [ 0.25]
erlang:list_to_binary/1 21 0.02 662 [ 31.52]
dict:store_bkt_val/3 3022 0.02 666 [ 0.22]
v3_codegen:block_cg/4 4224 0.02 667 [ 0.16]
beam_asm:encode_list/3 5137 0.02 672 [ 0.13]
beam_peep:is_test_redundant/3 2768 0.02 684 [ 0.25]
beam_dead:useful_to_insert_label/1 2912 0.02 684 [ 0.23]
beam_flatten:norm/1 2607 0.02 690 [ 0.26]
sys_core_fold:'-function_1/1-anonymous-0-'/1 251 0.02 694 [ 2.76]
sys_core_fold:'-warn_no_clause_match/2-anonymous-0-'/1 2927 0.02 696 [ 0.24]
cerl_sets:'-from_list/1-lc$^0/1-0-'/1 2976 0.02 696 [ 0.23]
erl_bits:check_size_unit/3 2996 0.02 697 [ 0.23]
erl_bits:set_bit/1 2996 0.02 699 [ 0.23]
v3_kernel:'-match_pre/3-anonymous-0-'/3 4145 0.02 701 [ 0.17]
lists:usplit_2/5 5084 0.02 716 [ 0.14]
beam_dead:shortcut_bs_test/3 3060 0.02 717 [ 0.23]
v3_life:'-expr/3-lc$^0/1-11-'/1 2963 0.02 718 [ 0.24]
gb_trees:keys/2 4330 0.02 720 [ 0.17]
cerl:update_c_tuple/2 2979 0.02 724 [ 0.24]
v3_life:'-expr/3-lc$^0/1-7-'/3 3487 0.02 729 [ 0.21]
beam_validator:valfun_4/2 3927 0.02 734 [ 0.19]
gb_sets:count/1 3125 0.02 735 [ 0.24]
gb_sets:is_element/2 3542 0.02 743 [ 0.21]
lists:umerge2_2/4 5786 0.02 744 [ 0.13]
v3_codegen:top_level_block/4 2684 0.02 745 [ 0.28]
v3_codegen:cg/5 4745 0.02 749 [ 0.16]
sys_core_fold:useless_call/2 2860 0.02 751 [ 0.26]
erl_bifs:is_pure/3 2857 0.02 754 [ 0.26]
v3_kernel:match_clause/4 4497 0.02 755 [ 0.17]
lists:split_1/5 5072 0.02 762 [ 0.15]
v3_kernel:expand_pat_lit/2 3339 0.02 764 [ 0.23]
sys_core_bsm:bsm_leftmost_1/2 5004 0.02 765 [ 0.15]
v3_core:cclause/3 5063 0.02 782 [ 0.15]
sys_core_fold:case_opt_args/5 3610 0.02 785 [ 0.22]
lists:any/2 4298 0.02 787 [ 0.18]
v3_kernel:handle_reuse_anno/2 3042 0.02 787 [ 0.26]
v3_kernel:'-atomic_list/3-anonymous-0-'/3 5982 0.02 792 [ 0.13]
gb_trees:empty/0 3538 0.02 793 [ 0.22]
dict:find_val/2 5799 0.02 800 [ 0.14]
beam_dead:shortcut_any_label/2 3432 0.02 806 [ 0.23]
v3_core:is_simple/1 3320 0.02 809 [ 0.24]
dict:append/3 6241 0.02 811 [ 0.13]
v3_kernel:literal/2 4667 0.02 813 [ 0.17]
dict:maybe_expand/2 6759 0.02 814 [ 0.12]
v3_codegen:put_reg_1/3 3274 0.02 820 [ 0.25]
erl_internal:new_type_test/2 4564 0.02 824 [ 0.18]
v3_kernel:'-umatch_list/3-anonymous-0-'/3 6742 0.02 837 [ 0.12]
v3_codegen:line/1 3137 0.02 838 [ 0.27]
erl_lint:merge_used/2 3765 0.02 841 [ 0.22]
v3_codegen:unsaved_registers/5 3539 0.02 845 [ 0.24]
erl_lint:merge_lines/2 3766 0.02 848 [ 0.23]
erlang:list_to_tuple/1 5982 0.02 849 [ 0.14]
beam_validator:check_limit/1 3543 0.02 857 [ 0.24]
gb_trees:from_orddict/1 3637 0.02 862 [ 0.24]
v3_codegen:gen_moves/2 3539 0.02 869 [ 0.25]
lists:append/1 4010 0.02 883 [ 0.22]
erts_internal:port_control/3 3 0.02 883 [ 294.33]
beam_type:simplify_float/2 3855 0.02 890 [ 0.23]
beam_flatten:norm_block/2 4760 0.02 902 [ 0.19]
v3_codegen:move_unsaved/3 3539 0.02 905 [ 0.26]
v3_kernel:group_value/3 2140 0.02 915 [ 0.43]
erl_expand_records:head/2 4100 0.02 915 [ 0.22]
v3_kernel:build_alt/2 4142 0.02 920 [ 0.22]
lists:rumerge3_1/6 6334 0.02 925 [ 0.15]
erl_lint:'-vtupdate/2-fun-0-'/3 3765 0.02 927 [ 0.25]
erl_expand_records:guard/2 4134 0.02 931 [ 0.23]
beam_validator:get_fls/1 3927 0.02 932 [ 0.24]
erl_expand_records:opt_rec_vars/1 4100 0.02 937 [ 0.23]
sets:add_element/2 1459 0.02 947 [ 0.65]
cerl_clauses:match_list/2 3840 0.02 947 [ 0.25]
sys_core_dsetel:'-visit/2-anonymous-2-'/2 4145 0.02 951 [ 0.23]
beam_block:opt_block/1 3906 0.02 953 [ 0.24]
v3_kernel:'-group_value/3-anonymous-1-'/4 4261 0.02 957 [ 0.22]
gb_trees:size/1 4040 0.02 957 [ 0.24]
v3_core:guard/2 4102 0.02 966 [ 0.24]
gb_sets:is_member/2 5890 0.02 968 [ 0.16]
v3_core:head/2 4102 0.02 972 [ 0.24]
v3_codegen:cg_setup_call/4 3539 0.02 974 [ 0.28]
beam_type:flt_liveness/1 3855 0.02 974 [ 0.25]
beam_block:find_fixpoint/2 4325 0.02 975 [ 0.23]
v3_core:'-cclauses/3-anonymous-0-'/3 4139 0.02 976 [ 0.24]
beam_validator:merge_states/3 3932 0.02 981 [ 0.25]
erl_expand_records:optimize_is_record/3 4100 0.02 995 [ 0.24]
sys_core_fold:sub_get_var/2 7105 0.02 997 [ 0.14]
erl_bits:set_bit_type/2 5268 0.02 999 [ 0.19]
orddict:new/0 6525 0.02 1002 [ 0.15]
erl_anno:record/1 4187 0.02 1003 [ 0.24]
beam_type:simplify/2 3855 0.02 1014 [ 0.26]
v3_life:'-match/5-lc$^0/1-1-'/5 4245 0.02 1015 [ 0.24]
v3_kernel:ubody/3 6590 0.02 1020 [ 0.15]
v3_kernel:pattern_list/4 5732 0.02 1026 [ 0.18]
v3_codegen:select_labels/4 5741 0.02 1027 [ 0.18]
beam_jump:skip_unreachable/3 7552 0.02 1030 [ 0.14]
erl_anno:anno_info/3 8470 0.02 1032 [ 0.12]
gb_sets:insert/2 4942 0.02 1035 [ 0.21]
v3_core:record_anno/2 4187 0.02 1036 [ 0.25]
v3_kernel:select_types/2 4210 0.02 1038 [ 0.25]
dict:maybe_expand_aux/2 6759 0.02 1038 [ 0.15]
beam_type:tdb_copy/3 6132 0.02 1046 [ 0.17]
beam_validator:get_term_type/2 4982 0.02 1054 [ 0.21]
beam_block:'-opt_block/1-anonymous-0-'/1 4325 0.02 1056 [ 0.24]
cerl:tuple_es/1 4258 0.02 1060 [ 0.25]
v3_kernel:'-op_vars/1-lc$^0/1-0-'/1 4458 0.02 1061 [ 0.24]
v3_core:annotate_tuple/3 4187 0.02 1064 [ 0.25]
erl_anno:new_location/1 10503 0.03 1072 [ 0.10]
v3_kernel:is_enter_expr/1 4381 0.03 1074 [ 0.25]
v3_codegen:cg_call_args/4 3539 0.03 1076 [ 0.30]
beam_validator:'-valfun_4/2-lc$^0/1-0-'/2 5041 0.03 1076 [ 0.21]
cerl:case_clauses/1 4391 0.03 1078 [ 0.25]
erl_lint:vtmerge/2 5277 0.03 1079 [ 0.20]
v3_codegen:collect_chain/4 4376 0.03 1103 [ 0.25]
v3_codegen:saves/3 4477 0.03 1108 [ 0.25]
v3_kernel:sub_size_var/2 4497 0.03 1114 [ 0.25]
gb_trees:balance_list/2 5862 0.03 1114 [ 0.19]
v3_core:clause/2 4102 0.03 1117 [ 0.27]
sys_core_fold:clause_1/5 7922 0.03 1120 [ 0.14]
beam_utils:index_label/3 4466 0.03 1120 [ 0.25]
v3_kernel:pattern_list/3 4475 0.03 1123 [ 0.25]
v3_codegen:'-select_val_cg/6-lc$^0/1-0-'/2 5041 0.03 1130 [ 0.22]
v3_codegen:reserve/3 8344 0.03 1132 [ 0.14]
v3_codegen:'-save_stack/4-lc$^1/1-1-'/1 4562 0.03 1136 [ 0.25]
v3_kernel:arg_val/2 6371 0.03 1139 [ 0.18]
beam_trim:trim/3 9557 0.03 1142 [ 0.12]
v3_codegen:'-select_cg/6-anonymous-0-'/5 4261 0.03 1153 [ 0.27]
v3_codegen:need_heap/2 4534 0.03 1166 [ 0.26]
beam_type:'-tdb_update/2-anonymous-0-'/1 4828 0.03 1169 [ 0.24]
v3_kernel:get_con/1 4497 0.03 1177 [ 0.26]
v3_codegen:save_stack/4 4477 0.03 1179 [ 0.26]
cerl:ann_c_tuple/2 6882 0.03 1181 [ 0.17]
gb_trees:to_list/1 4973 0.03 1186 [ 0.24]
v3_codegen:'-cg_list/5-anonymous-0-'/3 4390 0.03 1187 [ 0.27]
v3_core:cguard/2 5063 0.03 1193 [ 0.24]
lists:all/2 7433 0.03 1196 [ 0.16]
v3_kernel:'-match_con/4-lc$^0/1-0-'/1 5473 0.03 1197 [ 0.22]
v3_kernel:'-match_value/5-anonymous-0-'/3 4497 0.03 1199 [ 0.27]
gb_trees:update/3 7316 0.03 1210 [ 0.17]
sys_core_fold:update_types_2/3 4456 0.03 1211 [ 0.27]
v3_codegen:gen_moves/4 8450 0.03 1213 [ 0.14]
beam_flatten:block/2 9557 0.03 1217 [ 0.13]
v3_codegen:match_cg/5 7260 0.03 1217 [ 0.17]
v3_codegen:adjust_stack/4 4477 0.03 1220 [ 0.27]
beam_block:opt_moves/2 5254 0.03 1228 [ 0.23]
v3_kernel:umatch_list/3 4333 0.03 1229 [ 0.28]
beam_type:flt_liveness_1/3 8435 0.03 1229 [ 0.15]
v3_life:expr/3 4675 0.03 1240 [ 0.27]
erl_expand_records:clauses/2 5002 0.03 1244 [ 0.25]
v3_codegen:cg/4 4745 0.03 1255 [ 0.26]
v3_codegen:basic_block/2 4470 0.03 1255 [ 0.28]
v3_life:body/3 4675 0.03 1256 [ 0.27]
v3_core:clauses/2 5006 0.03 1258 [ 0.25]
beam_record:rewrite/3 9542 0.03 1259 [ 0.13]
orddict:filter/2 7572 0.03 1262 [ 0.17]
erl_lint:exprs/3 5120 0.03 1265 [ 0.25]
cerl:is_literal/1 5246 0.03 1271 [ 0.24]
beam_dead:shortcut_rel_op/4 5365 0.03 1274 [ 0.24]
beam_block:opt_move_1/3 5782 0.03 1281 [ 0.22]
v3_core:'-new_in_any/1-anonymous-0-'/2 5573 0.03 1288 [ 0.23]
beam_validator:valfun/4 8912 0.03 1289 [ 0.14]
v3_codegen:cg_list/5 4390 0.03 1294 [ 0.29]
gb_sets:balance_list_1/2 5205 0.03 1300 [ 0.25]
beam_dead:update_value_dict/3 2588 0.03 1300 [ 0.50]
v3_core:uguard/4 5063 0.03 1309 [ 0.26]
v3_codegen:collect_block/1 4470 0.03 1309 [ 0.29]
sys_core_bsm:bsm_leftmost_2/4 10417 0.03 1313 [ 0.13]
beam_asm:assemble_function/3 9587 0.03 1313 [ 0.14]
beam_flatten:opt_1/2 10261 0.03 1316 [ 0.13]
sys_core_fold:pattern_list/3 7925 0.03 1330 [ 0.17]
lists:split_2/5 9072 0.03 1331 [ 0.15]
v3_kernel:new_clauses/3 4497 0.03 1333 [ 0.30]
erl_lint:exist_field/2 10254 0.03 1336 [ 0.13]
v3_kernel:match_guard_1/3 4179 0.03 1337 [ 0.32]
erl_lint:keyword_warning/3 5988 0.03 1338 [ 0.22]
v3_codegen:'-clear_dead_stk/3-lc$^0/1-0-'/3 11348 0.03 1345 [ 0.12]
sys_core_fold:'-case_will_var_match/1-anonymous-0-'/1 4569 0.03 1346 [ 0.29]
beam_trim:safe_labels/2 9410 0.03 1359 [ 0.14]
orddict:store/3 7603 0.03 1371 [ 0.18]
v3_codegen:need_heap_1/2 4675 0.03 1372 [ 0.29]
v3_codegen:select_val/5 4261 0.03 1380 [ 0.32]
beam_bsm:btb_opt_1/3 11869 0.03 1385 [ 0.12]
v3_codegen:order_moves/3 7414 0.03 1393 [ 0.19]
beam_dict:atom/2 4805 0.03 1413 [ 0.29]
beam_clean:bs_replace/3 11882 0.03 1414 [ 0.12]
beam_receive:opt/3 11869 0.03 1425 [ 0.12]
v3_kernel:get_match/2 4497 0.03 1428 [ 0.32]
beam_utils:is_pure_test/1 4686 0.03 1430 [ 0.31]
v3_kernel:atomic/3 5988 0.03 1431 [ 0.24]
v3_codegen:add_vls/3 8098 0.03 1436 [ 0.18]
beam_block:move_allocates_1/2 9109 0.03 1465 [ 0.16]
v3_life:val_clause/5 4497 0.03 1471 [ 0.33]
v3_core:'-safe_list/2-anonymous-0-'/2 12288 0.03 1477 [ 0.12]
v3_kernel:'-partition/1-anonymous-0-'/2 6163 0.03 1478 [ 0.24]
v3_core:cexprs/3 5590 0.04 1507 [ 0.27]
v3_kernel:'-group_value/3-anonymous-0-'/2 6241 0.04 1513 [ 0.24]
v3_core:uclause/4 5063 0.04 1516 [ 0.30]
v3_codegen:longest/2 6572 0.04 1542 [ 0.23]
v3_kernel:pre_seq/2 6656 0.04 1546 [ 0.23]
v3_codegen:fetch_var/2 5770 0.04 1548 [ 0.27]
erl_lint:head/4 7474 0.04 1548 [ 0.21]
v3_codegen:'-block_cg/4-anonymous-0-'/2 7067 0.04 1560 [ 0.22]
beam_split:split_block/3 8435 0.04 1562 [ 0.19]
dict:'-append/3-fun-0-'/3 6241 0.04 1570 [ 0.25]
v3_life:'-type_clause/5-lc$^0/1-0-'/5 6637 0.04 1577 [ 0.24]
v3_kernel:lit_vars/1 6338 0.04 1577 [ 0.25]
lists:keysort/2 8482 0.04 1583 [ 0.19]
v3_codegen:find_scratch_reg/2 9018 0.04 1592 [ 0.18]
beam_type:tdb_find/2 5902 0.04 1597 [ 0.27]
beam_clean:update_work_list/2 11882 0.04 1602 [ 0.13]
v3_kernel:clause_val/1 6371 0.04 1619 [ 0.25]
v3_kernel:body/3 5476 0.04 1642 [ 0.30]
erl_anno:anno_info/2 8488 0.04 1654 [ 0.19]
beam_dead:get_literal/1 7173 0.04 1662 [ 0.23]
lists:filter/2 6898 0.04 1674 [ 0.24]
v3_kernel:'-select_bin_con/1-anonymous-0-'/1 7078 0.04 1684 [ 0.24]
beam_asm:encode_op/3 9419 0.04 1706 [ 0.18]
beam_validator:merge_regs_1/2 7234 0.04 1709 [ 0.24]
v3_codegen:need_heap_0/3 9209 0.04 1738 [ 0.19]
erl_bits:apply_defaults/5 12196 0.04 1752 [ 0.14]
beam_peep:peep/3 11882 0.04 1758 [ 0.15]
erl_lint:pattern/5 6607 0.04 1759 [ 0.27]
beam_block:collect_block/2 9090 0.04 1765 [ 0.19]
erl_bits:merge_field/3 8240 0.04 1777 [ 0.22]
beam_type:x_live/2 9023 0.04 1788 [ 0.20]
beam_jump:move_1/3 15981 0.04 1794 [ 0.11]
v3_core:cexpr/3 6511 0.04 1845 [ 0.28]
v3_codegen:clear_dead_reg/3 7328 0.04 1853 [ 0.25]
beam_z:undo_rename/1 8780 0.04 1867 [ 0.21]
gb_trees:enter/3 9837 0.04 1913 [ 0.19]
sys_core_fold:pattern_list/2 7925 0.04 1916 [ 0.24]
v3_codegen:clear_dead/3 7328 0.04 1916 [ 0.26]
v3_kernel:maybe_add_warning/3 8216 0.04 1916 [ 0.23]
v3_codegen:sr_merge/2 5190 0.04 1924 [ 0.37]
beam_type:verify_type/1 7548 0.05 1936 [ 0.26]
v3_kernel:expand_pat_lit_clause/2 7078 0.05 1947 [ 0.28]
gb_sets:empty/0 9285 0.05 1954 [ 0.21]
beam_clean:bs_clean_saves_1/3 17192 0.05 1978 [ 0.12]
beam_validator:get_term_type_1/2 7594 0.05 1981 [ 0.26]
sys_core_fold:clauses/5 7919 0.05 1993 [ 0.25]
core_lib:make_values/1 8600 0.05 1997 [ 0.23]
sys_core_fold:guard/2 7925 0.05 2011 [ 0.25]
v3_life:atomic/1 7827 0.05 2015 [ 0.26]
cerl_clauses:match/2 8713 0.05 2018 [ 0.23]
v3_kernel:is_atomic/1 8141 0.05 2028 [ 0.25]
erl_lint:'-expr_list/3-fun-0-'/3 8606 0.05 2030 [ 0.24]
beam_bs:bsm_scan/4 16932 0.05 2044 [ 0.12]
v3_life:match/5 7260 0.05 2046 [ 0.28]
lists:duplicate/3 18233 0.05 2051 [ 0.11]
beam_type:tdb_update1/2 10602 0.05 2059 [ 0.19]
beam_bs:bsm_opt_2/2 17164 0.05 2063 [ 0.12]
beam_block:embed_lines/2 17184 0.05 2073 [ 0.12]
v3_codegen:cg_block/5 8553 0.05 2078 [ 0.24]
erl_expand_records:exprs/2 9355 0.05 2082 [ 0.22]
v3_core:lit_vars/2 10591 0.05 2091 [ 0.20]
v3_kernel:force_atomic/2 8141 0.05 2092 [ 0.26]
v3_codegen:match_cg/4 7260 0.05 2142 [ 0.30]
beam_dict:opcode/2 9420 0.05 2157 [ 0.23]
sys_core_fold:clause/4 7922 0.05 2159 [ 0.27]
beam_utils:live_join_label/3 8843 0.05 2159 [ 0.24]
dict:on_bucket/3 6759 0.05 2165 [ 0.32]
v3_core:uexpr/3 6984 0.05 2167 [ 0.31]
v3_codegen:load_arg_regs/3 8450 0.05 2172 [ 0.26]
beam_block:opt_alloc/1 11937 0.05 2172 [ 0.18]
cerl:make_lit_list/1 11523 0.05 2186 [ 0.19]
beam_opcodes:opcode/2 9420 0.05 2223 [ 0.24]
v3_core:exprs/2 8974 0.05 2231 [ 0.25]
sys_core_fold:update_types/3 8234 0.05 2245 [ 0.27]
beam_z:undo_renames/1 9587 0.05 2256 [ 0.24]
erl_anno:new/1 10503 0.05 2262 [ 0.22]
lists:split_1_1/6 784 0.05 2289 [ 2.92]
beam_except:translate/3 17164 0.05 2311 [ 0.13]
beam_split:split_blocks/2 17151 0.05 2325 [ 0.14]
gb_sets:to_list/2 14255 0.05 2327 [ 0.16]
sys_core_fold:will_match/2 7919 0.05 2331 [ 0.29]
beam_validator:val_dsetel/2 8744 0.05 2341 [ 0.27]
ordsets:add_element/2 12009 0.06 2397 [ 0.20]
erlang:phash/2 11590 0.06 2445 [ 0.21]
dict:get_slot/2 8807 0.06 2466 [ 0.28]
beam_type:opt_fmoves/2 16145 0.06 2469 [ 0.15]
sys_core_fold:'-case_opt/3-lc$^0/1-0-'/1 10538 0.06 2496 [ 0.24]
beam_jump:is_unreachable_after/1 10395 0.06 2499 [ 0.24]
beam_type:opt/3 17164 0.06 2501 [ 0.15]
v3_core:'-used_in_any/1-anonymous-0-'/2 10516 0.06 2504 [ 0.24]
beam_dead:backward/3 18352 0.06 2504 [ 0.14]
sys_core_fold:'-case_opt/3-lc$^1/1-1-'/1 10538 0.06 2513 [ 0.24]
v3_life:vdb_update/3 13239 0.06 2514 [ 0.19]
beam_block:blockify/2 17185 0.06 2527 [ 0.15]
beam_type:flt_alloc/2 11588 0.06 2529 [ 0.22]
beam_utils:live_join_labels/3 15798 0.06 2538 [ 0.16]
beam_validator:valfun_1/2 8744 0.06 2581 [ 0.30]
ordsets:is_element/2 17110 0.06 2583 [ 0.15]
beam_jump:eliminate_fallthroughs/2 17629 0.06 2590 [ 0.15]
beam_reorder:reorder_1/3 19139 0.06 2598 [ 0.14]
beam_dead:forward/4 17408 0.06 2599 [ 0.15]
beam_block:opt_tuple_element/1 13904 0.06 2617 [ 0.19]
beam_dead:normalize_op/1 10466 0.06 2617 [ 0.25]
beam_jump:share_1/4 18255 0.06 2620 [ 0.14]
lists:sort/1 10629 0.06 2632 [ 0.25]
v3_codegen:clear_dead_stk/3 10974 0.06 2632 [ 0.24]
beam_dead:move_move_into_block/2 20253 0.06 2644 [ 0.13]
cerl_clauses:match_1/3 22337 0.06 2650 [ 0.12]
v3_kernel:'-new_clauses/3-anonymous-3-'/2 7078 0.06 2688 [ 0.38]
beam_jump:mark_used_list/2 20512 0.06 2703 [ 0.13]
beam_asm:make_op/2 9436 0.06 2719 [ 0.29]
beam_type:flt_need_heap_1/4 16145 0.06 2731 [ 0.17]
sys_core_fold:body/3 11466 0.06 2769 [ 0.24]
beam_type:simplify_float_1/4 16145 0.07 2781 [ 0.17]
ordsets:union1/2 23048 0.07 2793 [ 0.12]
maps:put/3 3108 0.07 2829 [ 0.91]
beam_jump:'-function/1-anonymous-0-'/2 13709 0.07 2845 [ 0.21]
ordsets:union/1 11598 0.07 2880 [ 0.25]
cerl:clause_guard/1 12917 0.07 2917 [ 0.23]
cerl:clause_body/1 12917 0.07 2918 [ 0.23]
v3_core:uexprs/3 11092 0.07 2923 [ 0.26]
beam_type:flt_need_heap_2/3 12165 0.07 2975 [ 0.24]
beam_asm:encode_op_1/3 25603 0.07 2979 [ 0.12]
sys_core_fold:'-pattern_list/3-anonymous-0-'/3 12691 0.07 2986 [ 0.24]
v3_kernel:'-select_types/2-lc$^0/1-0-'/2 23155 0.07 3010 [ 0.13]
v3_core:used_in_any/1 11840 0.07 3024 [ 0.26]
v3_codegen:combine/1 12070 0.07 3026 [ 0.25]
cerl:update_c_clause/4 12917 0.07 3055 [ 0.24]
cerl:clause_pats/1 12917 0.07 3076 [ 0.24]
lists:'-filter/2-lc$^0/1-0-'/2 18808 0.07 3101 [ 0.16]
gb_sets:is_member_1/2 26104 0.08 3272 [ 0.13]
v3_kernel:expr/3 12421 0.08 3336 [ 0.27]
gb_trees:is_defined/2 14133 0.08 3374 [ 0.24]
beam_clean:bs_restores/2 29074 0.08 3431 [ 0.12]
cerl:update_c_cons/3 14636 0.08 3471 [ 0.24]
beam_block:opt/1 13904 0.08 3503 [ 0.25]
cerl:data_es/1 14418 0.08 3519 [ 0.24]
beam_utils:live_regs_1/2 19169 0.08 3529 [ 0.18]
erl_lint:expr/3 14519 0.08 3539 [ 0.24]
cerl:cons_tl/1 14704 0.08 3552 [ 0.24]
erl_expand_records:index_expr/3 27160 0.08 3572 [ 0.13]
dict:append_bkt/3 18136 0.09 3668 [ 0.20]
cerl:cons_hd/1 14704 0.09 3708 [ 0.25]
beam_clean:'-replace/3-anonymous-0-'/2 14970 0.09 3744 [ 0.25]
sys_core_fold:'-case_opt_args/5-lc$^0/1-0-'/1 15391 0.09 3744 [ 0.24]
erl_expand_records:expr_list/2 16454 0.09 3792 [ 0.23]
beam_a:rename_instr/1 16432 0.09 3835 [ 0.23]
v3_kernel:umatch/3 14008 0.09 3857 [ 0.28]
beam_block:opt_blocks/1 17164 0.09 3894 [ 0.23]
erl_lint:vtupdate/2 15587 0.09 3903 [ 0.25]
v3_core:safe/2 16839 0.09 3912 [ 0.23]
beam_utils:code_at/2 16987 0.09 3944 [ 0.23]
beam_bs:bs_put_opt/1 17062 0.09 3959 [ 0.23]
beam_jump:is_exit_instruction/1 20021 0.09 3960 [ 0.20]
beam_type:simplify_basic/2 16996 0.09 4009 [ 0.24]
erl_expand_records:record_pattern/6 18108 0.10 4118 [ 0.23]
sys_core_fold:letify/2 17544 0.10 4128 [ 0.24]
v3_core:is_safe/1 18011 0.10 4129 [ 0.23]
beam_block:move_allocates/1 17164 0.10 4155 [ 0.24]
dict:fold_seg/4 32606 0.10 4210 [ 0.13]
v3_kernel:select/2 18945 0.10 4283 [ 0.23]
gb_trees:insert/3 18006 0.10 4348 [ 0.24]
v3_core:force_safe/2 18011 0.10 4349 [ 0.24]
sys_core_dsetel:visit/2 20233 0.11 4504 [ 0.22]
cerl:lit_list_vals/1 20782 0.11 4544 [ 0.22]
v3_kernel:new_vars/3 38405 0.11 4548 [ 0.12]
beam_clean:label/2 17403 0.11 4561 [ 0.26]
beam_a:rename_instrs/1 18150 0.11 4732 [ 0.26]
maps:find/2 18432 0.11 4797 [ 0.26]
v3_core:full_anno/2 19710 0.11 4801 [ 0.24]
v3_codegen:'-clear_dead_reg/3-lc$^0/1-0-'/3 20503 0.11 4908 [ 0.24]
cerl:is_lit_list/1 30858 0.12 5011 [ 0.16]
beam_asm:encode/2 21230 0.12 5175 [ 0.24]
v3_codegen:new_label/1 6214 0.12 5257 [ 0.85]
v3_kernel:'-pattern_list/4-anonymous-0-'/3 45126 0.12 5279 [ 0.12]
beam_utils:x_dead/2 28264 0.12 5286 [ 0.19]
v3_kernel:'-match/4-anonymous-0-'/3 41079 0.13 5362 [ 0.13]
gb_sets:insert_1/3 21011 0.13 5416 [ 0.26]
v3_codegen:find_reg/2 12158 0.13 5458 [ 0.45]
v3_kernel:match_var/4 38974 0.13 5487 [ 0.14]
v3_kernel:match_varcon/4 41079 0.13 5493 [ 0.13]
beam_jump:opt/3 39214 0.13 5560 [ 0.14]
lists:member/2 36061 0.13 5567 [ 0.15]
erl_lint:vtmerge_pat/2 23190 0.13 5609 [ 0.24]
beam_utils:live_opt_block/4 29834 0.13 5621 [ 0.19]
v3_codegen:'-unsaved_registers/5-lc$^0/1-0-'/5 49016 0.13 5695 [ 0.12]
gb_trees:get/2 33999 0.13 5701 [ 0.17]
erl_anno:to_term/1 27518 0.14 5803 [ 0.21]
sys_core_dsetel:restore_vars/3 44018 0.14 5816 [ 0.13]
v3_core:safe_list/2 4203 0.14 5830 [ 1.39]
cerl:get_ann/1 24725 0.14 5839 [ 0.24]
beam_block:collect/1 26107 0.14 5919 [ 0.23]
beam_asm:encode_arg/2 21180 0.14 5922 [ 0.28]
beam_type:simplify_basic_1/3 42427 0.14 6082 [ 0.14]
beam_clean:replace/3 41489 0.14 6110 [ 0.15]
erl_parse:'-anno_to_term/1-fun-0-'/2 27518 0.14 6163 [ 0.22]
gb_trees:count/1 27728 0.15 6294 [ 0.23]
erlang:max/2 24717 0.15 6340 [ 0.26]
orddict:merge/3 49589 0.15 6357 [ 0.13]
v3_core:expr/2 22900 0.15 6396 [ 0.28]
sys_core_dsetel:visit_pats/3 50734 0.15 6451 [ 0.13]
sys_core_fold:expr/3 33651 0.15 6468 [ 0.19]
v3_kernel:match/4 44330 0.15 6474 [ 0.15]
v3_codegen:'-save_stack/4-lc$^0/1-0-'/4 52503 0.16 6636 [ 0.13]
lists:splitwith/3 48334 0.16 6742 [ 0.14]
beam_clean:renumber_labels/3 42525 0.16 6750 [ 0.16]
erl_expand_records:expr/2 23874 0.16 6796 [ 0.28]
beam_jump:label_used/2 36676 0.16 6855 [ 0.19]
gb_trees:lookup/2 30683 0.16 6975 [ 0.23]
erl_lint:find_field/2 54324 0.16 7051 [ 0.13]
v3_life:use_vars/3 24118 0.17 7110 [ 0.29]
gb_trees:update_1/3 29635 0.17 7152 [ 0.24]
dict:fold_bucket/3 35281 0.17 7284 [ 0.21]
beam_utils:live_opt/4 49967 0.17 7339 [ 0.15]
v3_core:new_in_any/1 10126 0.17 7483 [ 0.74]
beam_jump:rem_unused/3 62921 0.18 7561 [ 0.12]
ordsets:subtract/2 51321 0.18 7865 [ 0.15]
lists:reverse/2 30707 0.19 8060 [ 0.26]
cerl:is_data/1 34107 0.19 8117 [ 0.24]
v3_life:'-literal/2-lc$^0/1-0-'/2 37431 0.19 8199 [ 0.22]
beam_utils:index_labels_1/2 63625 0.20 8598 [ 0.14]
v3_kernel:'-pat_list_vars/1-anonymous-0-'/2 37504 0.21 8838 [ 0.24]
v3_codegen:'-select_extract_tuple/6-anonymous-0-'/5 37421 0.21 8998 [ 0.24]
maps:remove/2 39703 0.21 9122 [ 0.23]
beam_type:update/2 36624 0.21 9165 [ 0.25]
v3_kernel:'-match_var/4-anonymous-1-'/3 39273 0.22 9426 [ 0.24]
erlang:term_to_binary/2 330 0.23 9637 [ 29.20]
v3_kernel:new_var_name/1 39420 0.23 9699 [ 0.25]
gb_trees:is_defined_1/2 86526 0.23 9919 [ 0.11]
v3_core:new_var_name/1 38685 0.24 10131 [ 0.26]
beam_jump:'-remove_unused_labels/1-anonymous-0-'/2 48838 0.24 10148 [ 0.21]
beam_utils:x_live/2 53759 0.24 10161 [ 0.19]
beam_jump:ulbl/2 70747 0.24 10218 [ 0.14]
v3_kernel:'-match_var/4-anonymous-0-'/3 39273 0.24 10237 [ 0.26]
lists:splitwith/2 41778 0.24 10449 [ 0.25]
v3_kernel:'-select/2-lc$^0/1-0-'/2 82647 0.25 10487 [ 0.13]
orddict:from_list/1 78652 0.25 10596 [ 0.13]
v3_kernel:pat_vars/1 42105 0.25 10645 [ 0.25]
v3_codegen:flatmapfoldl/3 47583 0.27 11351 [ 0.24]
erl_expand_records:pattern_list/2 51056 0.27 11369 [ 0.22]
sys_core_bsm:'-function/3-anonymous-0-'/2 105235 0.27 11450 [ 0.11]
v3_core:pattern_list/2 51110 0.27 11568 [ 0.23]
erl_expand_records:pattern/2 46427 0.27 11677 [ 0.25]
sys_core_bsm:bsm_an/2 105235 0.28 12181 [ 0.12]
lists:ukeysort/2 77382 0.29 12218 [ 0.16]
sys_core_fold:pattern/3 91530 0.29 12271 [ 0.13]
v3_core:pattern/2 47003 0.29 12363 [ 0.26]
v3_core:upattern/3 46333 0.29 12508 [ 0.27]
v3_life:literal/2 44636 0.29 12582 [ 0.28]
cerl:concrete/1 54877 0.29 12608 [ 0.23]
v3_kernel:'-match_var/4-anonymous-2-'/2 39273 0.30 12847 [ 0.33]
lists:keyfind/3 71791 0.30 12920 [ 0.18]
v3_kernel:pattern/4 45769 0.30 12934 [ 0.28]
beam_utils:delete_live_annos/1 63039 0.31 13115 [ 0.21]
erlang:integer_to_list/1 79068 0.31 13136 [ 0.17]
v3_core:upattern_list/3 51908 0.31 13167 [ 0.25]
orddict:find/2 89347 0.34 14356 [ 0.16]
v3_life:vdb_find/2 49254 0.34 14473 [ 0.29]
gb_trees:to_list/2 94502 0.36 15491 [ 0.16]
v3_core:lineno_anno/2 74513 0.37 15670 [ 0.21]
erl_anno:location/1 74533 0.39 16540 [ 0.22]
cerl_trees:mapfold_list/4 71716 0.39 16699 [ 0.23]
erl_anno:line/1 74513 0.40 16895 [ 0.23]
erl_anno:generated/1 74513 0.40 16986 [ 0.23]
sys_core_fold:'-pattern/3-anonymous-2-'/3 76384 0.41 17600 [ 0.23]
sys_core_dsetel:visit_pat/3 46419 0.42 17861 [ 0.38]
gb_trees:balance_list_1/2 70256 0.43 18286 [ 0.26]
sys_core_fold:sub_del_var/2 79753 0.45 19286 [ 0.24]
sys_core_fold:sub_is_val/2 79753 0.45 19455 [ 0.24]
v3_kernel:partition/1 81267 0.47 20263 [ 0.25]
ordsets:intersection/2 144532 0.48 20342 [ 0.14]
v3_kernel:is_var_clause/1 88321 0.52 22083 [ 0.25]
cerl_clauses:match_list/3 176966 0.54 23136 [ 0.13]
sys_core_bsm:bsm_an/1 105235 0.55 23434 [ 0.22]
erlang:list_to_atom/1 79357 0.59 25074 [ 0.32]
cerl_trees:'-mapfold/3-anonymous-0-'/2 105235 0.59 25195 [ 0.24]
erl_parse:modify_anno1/3 99993 0.60 25693 [ 0.26]
lists:map/2 110970 0.62 26584 [ 0.24]
gb_trees:lookup_1/2 230216 0.64 27218 [ 0.12]
lists:reverse/1 122044 0.65 27622 [ 0.23]
cerl_trees:mapfold/4 105235 0.65 27889 [ 0.27]
gb_trees:get_1/2 247600 0.66 28191 [ 0.11]
cerl_clauses:'-match_1/3-lc$^0/1-0-'/1 150164 0.78 33173 [ 0.22]
lists:mapfoldl/3 142434 0.78 33411 [ 0.23]
gb_trees:insert_1/4 145420 0.82 35231 [ 0.24]
v3_kernel:arg_con/1 160017 0.87 37325 [ 0.23]
cerl_clauses:match/3 167587 0.88 37476 [ 0.22]
lists:foldr/3 199608 0.98 41728 [ 0.21]
erlang:'++'/2 337382 1.03 43981 [ 0.13]
cerl_sets:is_element/2 219320 1.27 54228 [ 0.25]
cerl_sets:add_element/2 158421 1.37 58422 [ 0.37]
lists:foldl/3 384147 1.44 61755 [ 0.16]
cerl:type/1 273982 1.55 66363 [ 0.24]
erlang:setelement/3 409336 1.67 71545 [ 0.17]
v3_life:vdb_update_vars/3 319576 1.69 72308 [ 0.23]
v3_kernel:subst_vsub_2/3 343932 1.83 78060 [ 0.23]
orddict:reverse_pairs/2 2497074 6.76 289258 [ 0.12]
lists:ukeysplit_2/5 2336493 7.63 326450 [ 0.14]
ordsets:union/2 1692288 8.93 381951 [ 0.23]
v3_kernel:subst_vsub_1/3 2152994 11.93 510068 [ 0.24]
---------------------------------------------------------- -------- ------- ------- [----------]
Total: 22253284 100.00% 4276149 [ 0.19]
---
lib/diameter/test/diameter_util.erl | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/lib/diameter/test/diameter_util.erl b/lib/diameter/test/diameter_util.erl
index 03f79096ac..d249b0e4fa 100644
--- a/lib/diameter/test/diameter_util.erl
+++ b/lib/diameter/test/diameter_util.erl
@@ -32,7 +32,8 @@
foldl/3,
scramble/1,
unique_string/0,
- have_sctp/0]).
+ have_sctp/0,
+ eprof/1]).
%% diameter-specific
-export([lport/2,
@@ -48,6 +49,16 @@
-define(L, atom_to_list).
+%% ---------------------------------------------------------------------------
+
+eprof(start) ->
+ eprof:start(),
+ eprof:start_profiling([self()]);
+
+eprof(stop) ->
+ eprof:stop_profiling(),
+ eprof:analyze(),
+ eprof:stop().
%% ---------------------------------------------------------------------------
%% name/2
--
cgit v1.2.3
From 1339269fefcbd688b3eb4bde2bb6c55fe2e1b17d Mon Sep 17 00:00:00 2001
From: Anders Svensson
Date: Wed, 19 Jul 2017 14:48:12 +0200
Subject: Increase init_per_group timetrap in traffic suite
Connection establishment is slow on some test hosts.
---
lib/diameter/test/diameter_traffic_SUITE.erl | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl
index d676614084..eb2fdb7721 100644
--- a/lib/diameter/test/diameter_traffic_SUITE.erl
+++ b/lib/diameter/test/diameter_traffic_SUITE.erl
@@ -30,6 +30,7 @@
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,
@@ -314,6 +315,9 @@ end_per_suite(_Config) ->
%% --------------------
+init_per_group(_) ->
+ [{timetrap, {seconds, 30}}].
+
init_per_group(Name, Config)
when Name == shuffle;
Name == parallel ->
--
cgit v1.2.3
From fa233bb7bc4f37632166c468a0381e695433c318 Mon Sep 17 00:00:00 2001
From: Anders Svensson
Date: Wed, 12 Jul 2017 11:43:06 +0200
Subject: Limit SCTP testing in traffic suite
All SCTP testing on Solaris/Sparc was disabled in commit 69c5a741, but
there are issues on other platforms as well, resulting in failures in
diameter_gen_sctp_SUITE and more. The problems seem to be load-related,
when testcases are run in parallel, so only run a smallish subset
sequentially until the gen_sctp suite runs without error.
---
lib/diameter/test/diameter_traffic_SUITE.erl | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl
index eb2fdb7721..f05c850513 100644
--- a/lib/diameter/test/diameter_traffic_SUITE.erl
+++ b/lib/diameter/test/diameter_traffic_SUITE.erl
@@ -125,7 +125,7 @@
%% 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, 42).
+-define(LIMIT, #{tcp => 42, sctp => 5}).
-define(util, diameter_util).
@@ -269,12 +269,15 @@ all() ->
-define(GROUPS, []).
%-define(GROUPS, [[tcp,rfc6733,record,map,false,false,false,false]]).
+%% Issues with gen_sctp sporadically cause huge numbers of failed
+%% testcases when running testcases in parallel.
groups() ->
Names = names(),
[{P, [P], Ts} || Ts <- [tc()], P <- [shuffle, parallel]]
++
- [{?util:name(N), [], [{group, if S -> shuffle; not S -> parallel end}]}
- || [_,_,_,_,S|_] = N <- Names]
+ [{?util:name(N), [], [{group, if T == sctp; S -> shuffle;
+ true -> parallel end}]}
+ || [T,_,_,_,S|_] = N <- Names]
++
[{T, [], [{group, ?util:name(N)} || N <- names(Names, ?GROUPS),
T == hd(N)]}
@@ -348,7 +351,7 @@ init_per_group(Name, Config) ->
server_decoding = D,
server_sender = SS,
server_throttle = ST},
- [{group, G}, {runlist, select()} | Config];
+ [{group, G}, {runlist, select(T)} | Config];
_ ->
Config
end.
@@ -362,9 +365,10 @@ end_per_group(Name, Config)
end_per_group(_, _) ->
ok.
-select() ->
- try rand:uniform(?LIMIT) of
- N -> lists:sublist(?util:scramble(tc()), max(N,5))
+select(T) ->
+ try maps:get(T, ?LIMIT) of
+ N ->
+ lists:sublist(?util:scramble(tc()), max(5, rand:uniform(N)))
catch
error:_ -> ?LIMIT
end.
--
cgit v1.2.3