diff options
Diffstat (limited to 'lib')
105 files changed, 3871 insertions, 663 deletions
diff --git a/lib/asn1/c_src/asn1_erl_nif.c b/lib/asn1/c_src/asn1_erl_nif.c index 9c9f83bc2a..accd368af1 100644 --- a/lib/asn1/c_src/asn1_erl_nif.c +++ b/lib/asn1/c_src/asn1_erl_nif.c @@ -580,7 +580,7 @@ int per_insert_bits_as_bits(int desired_no, int no_bytes, unsigned char **input_ptr, unsigned char **output_ptr, int *unused) { unsigned char *in_ptr = *input_ptr; unsigned char val; - int no_bits, ret, ret2; + int no_bits, ret; if (desired_no == (no_bytes * 8)) { if (per_insert_octets_unaligned(no_bytes, &in_ptr, output_ptr, *unused) @@ -606,8 +606,7 @@ int per_insert_bits_as_bits(int desired_no, int no_bytes, == ASN1_ERROR ) return ASN1_ERROR; - ret2 = per_pad_bits(desired_no - (no_bytes * 8), output_ptr, unused); - /* printf("ret2 = %d\n\r",ret2); */ + per_pad_bits(desired_no - (no_bytes * 8), output_ptr, unused); ret = CEIL(desired_no,8); /* printf("ret = %d\n\r",ret); */ } diff --git a/lib/compiler/src/Makefile b/lib/compiler/src/Makefile index 7a237608ad..3415517fff 100644 --- a/lib/compiler/src/Makefile +++ b/lib/compiler/src/Makefile @@ -53,6 +53,7 @@ MODULES = \ beam_dead \ beam_dict \ beam_disasm \ + beam_except \ beam_flatten \ beam_jump \ beam_listing \ diff --git a/lib/compiler/src/beam_except.erl b/lib/compiler/src/beam_except.erl new file mode 100644 index 0000000000..fb1a43cd9e --- /dev/null +++ b/lib/compiler/src/beam_except.erl @@ -0,0 +1,149 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2011. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(beam_except). +-export([module/2]). + +%%% Rewrite certain calls to erlang:error/{1,2} to specialized +%%% instructions: +%%% +%%% erlang:error({badmatch,Value}) => badmatch Value +%%% erlang:error({case_clause,Value}) => case_end Value +%%% erlang:error({try_clause,Value}) => try_case_end Value +%%% erlang:error(if_clause) => if_end +%%% erlang:error(function_clause, Args) => jump FuncInfoLabel +%%% + +-import(lists, [reverse/1]). + +module({Mod,Exp,Attr,Fs0,Lc}, _Opt) -> + Fs = [function(F) || F <- Fs0], + {ok,{Mod,Exp,Attr,Fs,Lc}}. + +function({function,Name,Arity,CLabel,Is0}) -> + try + Is = function_1(Is0), + {function,Name,Arity,CLabel,Is} + catch + Class:Error -> + Stack = erlang:get_stacktrace(), + io:fwrite("Function: ~w/~w\n", [Name,Arity]), + erlang:raise(Class, Error, Stack) + end. + +-record(st, + {lbl, %func_info label + loc %location for func_info + }). + +function_1(Is0) -> + case Is0 of + [{label,Lbl},{line,Loc}|_] -> + St = #st{lbl=Lbl,loc=Loc}, + translate(Is0, St, []); + [{label,_}|_] -> + %% No line numbers. The source must be a .S file. + %% There is no need to do anything. + Is0 + end. + +translate([{call_ext,Ar,{extfunc,erlang,error,Ar}}=I|Is], St, Acc) -> + translate_1(Ar, I, Is, St, Acc); +translate([{call_ext_only,Ar,{extfunc,erlang,error,Ar}}=I|Is], St, Acc) -> + translate_1(Ar, I, Is, St, Acc); +translate([{call_ext_last,Ar,{extfunc,erlang,error,Ar},_}=I|Is], St, Acc) -> + translate_1(Ar, I, Is, St, Acc); +translate([I|Is], St, Acc) -> + translate(Is, St, [I|Acc]); +translate([], _, Acc) -> + reverse(Acc). + +translate_1(Ar, I, Is, St, [{line,_}=Line|Acc1]=Acc0) -> + case dig_out(Ar, Acc1) of + no -> + translate(Is, St, [I|Acc0]); + {yes,function_clause,Acc2} -> + case {Line,St} of + {{line,Loc},#st{lbl=Fi,loc=Loc}} -> + Instr = {jump,{f,Fi}}, + translate(Is, St, [Instr|Acc2]); + {_,_} -> + %% This must be "error(function_clause, Args)" in + %% the Erlang source code. Don't translate. + translate(Is, St, [I|Acc0]) + end; + {yes,Instr,Acc2} -> + translate(Is, St, [Instr,Line|Acc2]) + end. + +dig_out(Ar, [{kill,_}|Is]) -> + dig_out(Ar, Is); +dig_out(1, [{block,Bl0}|Is]) -> + case dig_out_block(reverse(Bl0)) of + no -> no; + {yes,What,[]} -> + {yes,What,Is}; + {yes,What,Bl} -> + {yes,What,[{block,Bl}|Is]} + end; +dig_out(2, [{block,Bl}|Is]) -> + case dig_out_block_fc(Bl) of + no -> no; + {yes,What} -> {yes,What,Is} + end; +dig_out(_, _) -> no. + +dig_out_block([{set,[{x,0}],[{atom,if_clause}],move}]) -> + {yes,if_end,[]}; +dig_out_block([{set,[{x,0}],[{literal,{Exc,Value}}],move}|Is]) -> + translate_exception(Exc, {literal,Value}, Is, 0); +dig_out_block([{set,[{x,0}],[Tuple],move}, + {set,[],[Value],put}, + {set,[],[{atom,Exc}],put}, + {set,[Tuple],[],{put_tuple,2}}|Is]) -> + translate_exception(Exc, Value, Is, 3); +dig_out_block([{set,[],[Value],put}, + {set,[],[{atom,Exc}],put}, + {set,[{x,0}],[],{put_tuple,2}}|Is]) -> + translate_exception(Exc, Value, Is, 3); +dig_out_block(_) -> no. + +translate_exception(badmatch, Val, Is, Words) -> + {yes,{badmatch,Val},fix_block(Is, Words)}; +translate_exception(case_clause, Val, Is, Words) -> + {yes,{case_end,Val},fix_block(Is, Words)}; +translate_exception(try_clause, Val, Is, Words) -> + {yes,{try_case_end,Val},fix_block(Is, Words)}; +translate_exception(_, _, _, _) -> no. + +fix_block(Is, 0) -> + reverse(Is); +fix_block(Is0, Words) -> + [{set,[],[],{alloc,Live,{F1,F2,Needed,F3}}}|Is] = reverse(Is0), + [{set,[],[],{alloc,Live,{F1,F2,Needed-Words,F3}}}|Is]. + +dig_out_block_fc([{set,[],[],{alloc,Live,_}}|Bl]) -> + dig_out_fc(Bl, Live-1, nil); +dig_out_block_fc(_) -> no. + +dig_out_fc([{set,[Dst],[{x,Reg},Dst0],put_list}|Is], Reg, Dst0) -> + dig_out_fc(Is, Reg-1, Dst); +dig_out_fc([{set,[{x,0}],[{atom,function_clause}],move}], -1, {x,1}) -> + {yes,function_clause}; +dig_out_fc(_, _, _) -> no. diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl index a17a10046e..9b505ad15c 100644 --- a/lib/compiler/src/compile.erl +++ b/lib/compiler/src/compile.erl @@ -629,6 +629,8 @@ asm_passes() -> [{unless,no_postopt, [{pass,beam_block}, {iff,dblk,{listing,"block"}}, + {unless,no_except,{pass,beam_except}}, + {iff,dexcept,{listing,"except"}}, {unless,no_bopt,{pass,beam_bool}}, {iff,dbool,{listing,"bool"}}, {unless,no_topt,{pass,beam_type}}, diff --git a/lib/compiler/src/compiler.app.src b/lib/compiler/src/compiler.app.src index fb06f2521c..1133882728 100644 --- a/lib/compiler/src/compiler.app.src +++ b/lib/compiler/src/compiler.app.src @@ -28,6 +28,7 @@ beam_dead, beam_dict, beam_disasm, + beam_except, beam_flatten, beam_jump, beam_listing, diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl index 6ea67741fa..5b155398dc 100644 --- a/lib/compiler/src/sys_core_fold.erl +++ b/lib/compiler/src/sys_core_fold.erl @@ -2641,9 +2641,9 @@ bsm_leftmost_2([_|Ps], Cs, N, Pos) -> bsm_leftmost_2([], Cs, _, Pos) -> bsm_leftmost_1(Cs, Pos). -%% bsm_notempty(Cs, Pos) -> true|false +%% bsm_nonempty(Cs, Pos) -> true|false %% Check if at least one of the clauses matches a non-empty -%% binary in the given argumet position. +%% binary in the given argument position. %% bsm_nonempty([#c_clause{pats=Ps}|Cs], Pos) -> case nth(Pos, Ps) of @@ -2704,7 +2704,7 @@ bsm_ensure_no_partition_2([P|_], 1, _, Vstate, State) -> %% %% But if the clauses can't be freely rearranged, as in %% - %% b(Var, <<>>) -> ... + %% b(Var, <<X>>) -> ... %% b(1, 2) -> ... %% %% we do have a problem. diff --git a/lib/compiler/src/v3_codegen.erl b/lib/compiler/src/v3_codegen.erl index e7dae67085..6623485609 100644 --- a/lib/compiler/src/v3_codegen.erl +++ b/lib/compiler/src/v3_codegen.erl @@ -53,7 +53,6 @@ %% Main codegen structure. -record(cg, {lcount=1, %Label counter - finfo, %Function info label bfail, %Fail label for BIFs break, %Break label recv, %Receive label @@ -126,7 +125,6 @@ cg_fun(Les, Hvs, Vdb, AtomMod, NameArity, Anno, St0) -> stk=[]}, 0, Vdb), {B,_Aft,St} = cg_list(Les, 0, Vdb, Bef, St3#cg{bfail=0, - finfo=Fi, ultimate_failure=UltimateMatchFail, is_top_block=true}), {Name,Arity} = NameArity, @@ -147,8 +145,6 @@ cg({match,M,Rs}, Le, Vdb, Bef, St) -> match_cg(M, Rs, Le, Vdb, Bef, St); cg({guard_match,M,Rs}, Le, Vdb, Bef, St) -> guard_match_cg(M, Rs, Le, Vdb, Bef, St); -cg({match_fail,F}, Le, Vdb, Bef, St) -> - match_fail_cg(F, Le, Vdb, Bef, St); cg({call,Func,As,Rs}, Le, Vdb, Bef, St) -> call_cg(Func, As, Rs, Le, Vdb, Bef, St); cg({enter,Func,As}, Le, Vdb, Bef, St) -> @@ -294,39 +290,6 @@ match_cg({block,Es}, Le, _Fail, Bef, St) -> Int = clear_dead(Bef, Le#l.i, Le#l.vdb), block_cg(Es, Le, Int, St). -%% match_fail_cg(FailReason, Le, Vdb, StackReg, State) -> -%% {[Ainstr],StackReg,State}. -%% Generate code for the match_fail "call". N.B. there is no generic -%% case for when the fail value has been created elsewhere. - -match_fail_cg({function_clause,As}, Le, Vdb, Bef, St) -> - %% Must have the args in {x,0}, {x,1},... - {Sis,Int} = cg_setup_call(As, Bef, Le#l.i, Vdb), - {Sis ++ [{jump,{f,St#cg.finfo}}], - Int#sr{reg=clear_regs(Int#sr.reg)},St}; -match_fail_cg({badmatch,Term}, Le, Vdb, Bef, St) -> - R = cg_reg_arg(Term, Bef), - Int0 = clear_dead(Bef, Le#l.i, Vdb), - {Sis,Int} = adjust_stack(Int0, Le#l.i, Le#l.i+1, Vdb), - {Sis ++ [line(Le),{badmatch,R}], - Int#sr{reg=clear_regs(Int0#sr.reg)},St}; -match_fail_cg({case_clause,Reason}, Le, Vdb, Bef, St) -> - R = cg_reg_arg(Reason, Bef), - Int0 = clear_dead(Bef, Le#l.i, Vdb), - {Sis,Int} = adjust_stack(Int0, Le#l.i, Le#l.i+1, Vdb), - {Sis++[line(Le),{case_end,R}], - Int#sr{reg=clear_regs(Bef#sr.reg)},St}; -match_fail_cg(if_clause, Le, Vdb, Bef, St) -> - Int0 = clear_dead(Bef, Le#l.i, Vdb), - {Sis,Int1} = adjust_stack(Int0, Le#l.i, Le#l.i+1, Vdb), - {Sis++[line(Le),if_end],Int1#sr{reg=clear_regs(Int1#sr.reg)},St}; -match_fail_cg({try_clause,Reason}, Le, Vdb, Bef, St) -> - R = cg_reg_arg(Reason, Bef), - Int0 = clear_dead(Bef, Le#l.i, Vdb), - {Sis,Int} = adjust_stack(Int0, Le#l.i, Le#l.i+1, Vdb), - {Sis ++ [line(Le),{try_case_end,R}], - Int#sr{reg=clear_regs(Int0#sr.reg)},St}. - %% bsm_rename_ctx([Clause], Var) -> [Clause] %% We know from an annotation that the register for a binary can %% be reused for the match context because the two are not truly diff --git a/lib/compiler/src/v3_kernel.erl b/lib/compiler/src/v3_kernel.erl index d76291f57f..f2eaa37617 100644 --- a/lib/compiler/src/v3_kernel.erl +++ b/lib/compiler/src/v3_kernel.erl @@ -83,6 +83,7 @@ -import(lists, [map/2,foldl/3,foldr/3,mapfoldl/3,splitwith/2,member/2, keymember/3,keyfind/3]). -import(ordsets, [add_element/2,del_element/2,union/2,union/1,subtract/2]). +-import(cerl, [c_tuple/1]). -include("core_parse.hrl"). -include("v3_kernel.hrl"). @@ -422,10 +423,11 @@ expr(#c_call{anno=A,module=M0,name=F0,args=Cargs}, Sub, St0) -> end; expr(#c_primop{anno=A,name=#c_literal{val=match_fail},args=Cargs0}, Sub, St0) -> Cargs = translate_match_fail(Cargs0, Sub, A, St0), - %% This special case will disappear. {Kargs,Ap,St} = atomic_list(Cargs, Sub, St0), Ar = length(Cargs), - Call = #k_call{anno=A,op=#k_internal{name=match_fail,arity=Ar},args=Kargs}, + Call = #k_call{anno=A,op=#k_remote{mod=#k_atom{val=erlang}, + name=#k_atom{val=error}, + arity=Ar},args=Kargs}, {Call,Ap,St}; expr(#c_primop{anno=A,name=#c_literal{val=N},args=Cargs}, Sub, St0) -> {Kargs,Ap,St1} = atomic_list(Cargs, Sub, St0), @@ -455,14 +457,14 @@ expr(#ireceive_accept{anno=A}, _Sub, St) -> {#k_receive_accept{anno=A},[],St}. translate_match_fail(Args, Sub, Anno, St) -> case Args of [#c_tuple{es=[#c_literal{val=function_clause}|As]}] -> - translate_match_fail_1(Anno, Args, As, Sub, St); + translate_match_fail_1(Anno, As, Sub, St); [#c_literal{val=Tuple}] when is_tuple(Tuple) -> %% The inliner may have created a literal out of %% the original #c_tuple{}. case tuple_to_list(Tuple) of [function_clause|As0] -> As = [#c_literal{val=E} || E <- As0], - translate_match_fail_1(Anno, Args, As, Sub, St); + translate_match_fail_1(Anno, As, Sub, St); _ -> Args end; @@ -471,7 +473,7 @@ translate_match_fail(Args, Sub, Anno, St) -> Args end. -translate_match_fail_1(Anno, Args, As, Sub, #kern{ff=FF}) -> +translate_match_fail_1(Anno, As, Sub, #kern{ff=FF}) -> AnnoFunc = case keyfind(function_name, 1, Anno) of false -> none; %Force rewrite. @@ -481,10 +483,10 @@ translate_match_fail_1(Anno, Args, As, Sub, #kern{ff=FF}) -> case {AnnoFunc,FF} of {Same,Same} -> %% Still in the correct function. - Args; + translate_fc(As); {{F,_},F} -> %% Still in the correct function. - Args; + translate_fc(As); _ -> %% Wrong function or no function_name annotation. %% @@ -493,9 +495,12 @@ translate_match_fail_1(Anno, Args, As, Sub, #kern{ff=FF}) -> %% the current function). match_fail(function_clause) will %% only work at the top level of the function it was originally %% defined in, so we will need to rewrite it to a case_clause. - [#c_tuple{es=[#c_literal{val=case_clause},#c_tuple{es=As}]}] + [c_tuple([#c_literal{val=case_clause},c_tuple(As)])] end. +translate_fc(Args) -> + [#c_literal{val=function_clause},make_list(Args)]. + %% call_type(Module, Function, Arity) -> call | bif | apply | error. %% Classify the call. call_type(#c_literal{val=M}, #c_literal{val=F}, Ar) when is_atom(M), is_atom(F) -> @@ -1494,7 +1499,6 @@ iletrec_funs_gen(Fs, FreeVs, St) -> %% is_exit_expr(Kexpr) -> boolean(). %% Test whether Kexpr always exits and never returns. -is_exit_expr(#k_call{op=#k_internal{name=match_fail,arity=1}}) -> true; is_exit_expr(#k_receive_next{}) -> true; is_exit_expr(_) -> false. diff --git a/lib/compiler/src/v3_life.erl b/lib/compiler/src/v3_life.erl index fac9a9843d..93f8034230 100644 --- a/lib/compiler/src/v3_life.erl +++ b/lib/compiler/src/v3_life.erl @@ -89,19 +89,8 @@ function(#k_fdef{anno=#k{a=Anno},func=F,arity=Ar,vars=Vs,body=Kb}) -> end. %% body(Kbody, I, Vdb) -> {[Expr],MaxI,Vdb}. -%% Handle a body, need special cases for transforming match_fails. -%% We KNOW that they only occur last in a body. - -body(#k_seq{arg=#k_put{anno=Pa,arg=Arg,ret=[R]}, - body=#k_enter{anno=Ea,op=#k_internal{name=match_fail,arity=1}, - args=[R]}}, - I, Vdb0) -> - Vdb1 = use_vars(Pa#k.us, I, Vdb0), %All used here - {[match_fail(Arg, I, Pa#k.a ++ Ea#k.a)],I,Vdb1}; -body(#k_enter{anno=Ea,op=#k_internal{name=match_fail,arity=1},args=[Arg]}, - I, Vdb0) -> - Vdb1 = use_vars(Ea#k.us, I, Vdb0), - {[match_fail(Arg, I, Ea#k.a)],I,Vdb1}; +%% Handle a body. + body(#k_seq{arg=Ke,body=Kb}, I, Vdb0) -> %%ok = io:fwrite("life ~w:~p~n", [?LINE,{Ke,I,Vdb0}]), A = get_kanno(Ke), @@ -353,25 +342,6 @@ guard_clause(#k_guard_clause{anno=A,guard=Kg,body=Kb}, Ls, I, Ctxt, Vdb0) -> i=I,vdb=use_vars((get_kanno(Kg))#k.us, I+2, Vdb1), a=A#k.a}. -%% match_fail(FailValue, I, Anno) -> Expr. -%% Generate the correct match_fail instruction. N.B. there is no -%% generic case for when the fail value has been created elsewhere. - -match_fail(#k_literal{anno=Anno,val={Atom,Val}}, I, A) when is_atom(Atom) -> - match_fail(#k_tuple{anno=Anno,es=[#k_atom{val=Atom},#k_literal{val=Val}]}, I, A); -match_fail(#k_literal{anno=Anno,val={Atom}}, I, A) when is_atom(Atom) -> - match_fail(#k_tuple{anno=Anno,es=[#k_atom{val=Atom}]}, I, A); -match_fail(#k_tuple{es=[#k_atom{val=function_clause}|As]}, I, A) -> - #l{ke={match_fail,{function_clause,literal_list(As, [])}},i=I,a=A}; -match_fail(#k_tuple{es=[#k_atom{val=badmatch},Val]}, I, A) -> - #l{ke={match_fail,{badmatch,literal(Val, [])}},i=I,a=A}; -match_fail(#k_tuple{es=[#k_atom{val=case_clause},Val]}, I, A) -> - #l{ke={match_fail,{case_clause,literal(Val, [])}},i=I,a=A}; -match_fail(#k_atom{val=if_clause}, I, A) -> - #l{ke={match_fail,if_clause},i=I,a=A}; -match_fail(#k_tuple{es=[#k_atom{val=try_clause},Val]}, I, A) -> - #l{ke={match_fail,{try_clause,literal(Val, [])}},i=I,a=A}. - %% type(Ktype) -> Type. type(k_literal) -> literal; diff --git a/lib/compiler/test/Makefile b/lib/compiler/test/Makefile index b90adaf917..e13ad4ae90 100644 --- a/lib/compiler/test/Makefile +++ b/lib/compiler/test/Makefile @@ -10,6 +10,7 @@ MODULES= \ apply_SUITE \ beam_validator_SUITE \ beam_disasm_SUITE \ + beam_expect_SUITE \ bs_bincomp_SUITE \ bs_bit_binaries_SUITE \ bs_construct_SUITE \ @@ -29,7 +30,6 @@ MODULES= \ misc_SUITE \ num_bif_SUITE \ pmod_SUITE \ - parteval_SUITE \ receive_SUITE \ record_SUITE \ trycatch_SUITE \ @@ -39,6 +39,7 @@ MODULES= \ NO_OPT= \ andor \ apply \ + beam_expect \ bs_construct \ bs_match \ bs_utf \ diff --git a/lib/compiler/test/beam_expect_SUITE.erl b/lib/compiler/test/beam_expect_SUITE.erl new file mode 100644 index 0000000000..6f216eac4f --- /dev/null +++ b/lib/compiler/test/beam_expect_SUITE.erl @@ -0,0 +1,67 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2011. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +-module(beam_expect_SUITE). + +-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, + init_per_group/2,end_per_group/2, + coverage/1]). + +suite() -> [{ct_hooks,[ts_install_cth]}]. + +all() -> + [coverage]. + +groups() -> + []. + +init_per_suite(Config) -> + Config. + +end_per_suite(_Config) -> + ok. + +init_per_group(_GroupName, Config) -> + Config. + +end_per_group(_GroupName, Config) -> + Config. + +coverage(_) -> + File = {file,"fake.erl"}, + ok = fc(a), + {'EXIT',{function_clause, + [{?MODULE,fc,[[x]],[File,{line,2}]}|_]}} = + (catch fc([x])), + {'EXIT',{function_clause, + [{?MODULE,fc,[y],[File,{line,2}]}|_]}} = + (catch fc(y)), + {'EXIT',{function_clause, + [{?MODULE,fc,[[a,b,c]],[File,{line,6}]}|_]}} = + (catch fc([a,b,c])), + + {'EXIT',{undef,[{erlang,error,[a,b,c],_}|_]}} = + (catch erlang:error(a, b, c)), + ok. + +-file("fake.erl", 1). +fc(a) -> %Line 2 + ok; %Line 3 +fc(L) when length(L) > 2 -> %Line 4 + %% Not the same as a "real" function_clause error. + error(function_clause, [L]). %Line 6 diff --git a/lib/compiler/test/beam_validator_SUITE.erl b/lib/compiler/test/beam_validator_SUITE.erl index 556dc54a8f..902867bc19 100644 --- a/lib/compiler/test/beam_validator_SUITE.erl +++ b/lib/compiler/test/beam_validator_SUITE.erl @@ -79,21 +79,18 @@ beam_files(Config) when is_list(Config) -> %% a grammatical error in the output of the io:format/2 call below. ;-) ?line [_,_|_] = Fs = filelib:wildcard(Wc), ?line io:format("~p files\n", [length(Fs)]), - beam_files_1(Fs, 0). - -beam_files_1([F|Fs], Errors) -> - ?line case beam_validator:file(F) of - ok -> - beam_files_1(Fs, Errors); - {error,Es} -> - io:format("File: ~s", [F]), - io:format("Error: ~p\n", [Es]), - beam_files_1(Fs, Errors+1) - end; -beam_files_1([], 0) -> ok; -beam_files_1([], Errors) -> - ?line io:format("~p error(s)", [Errors]), - ?line ?t:fail(). + test_lib:p_run(fun do_beam_file/1, Fs). + + +do_beam_file(F) -> + case beam_validator:file(F) of + ok -> + ok; + {error,Es} -> + io:format("File: ~s", [F]), + io:format("Error: ~p\n", [Es]), + error + end. compiler_bug(Config) when is_list(Config) -> %% Check that the compiler returns an error if we try to diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl index f8c71a0257..01b7568122 100644 --- a/lib/compiler/test/bs_match_SUITE.erl +++ b/lib/compiler/test/bs_match_SUITE.erl @@ -342,6 +342,10 @@ partitioned_bs_match(Config) when is_list(Config) -> ?line fc(partitioned_bs_match_2, [4,<<0:17>>], catch partitioned_bs_match_2(4, <<0:17>>)), + + anything = partitioned_bs_match_3(anything, <<42>>), + ok = partitioned_bs_match_3(1, 2), + ok. partitioned_bs_match(_, <<42:8,T/binary>>) -> @@ -356,6 +360,9 @@ partitioned_bs_match_2(1, <<B:8,T/binary>>) -> partitioned_bs_match_2(Len, <<_:8,T/binary>>) -> {Len,T}. +partitioned_bs_match_3(Var, <<_>>) -> Var; +partitioned_bs_match_3(1, 2) -> ok. + function_clause(Config) when is_list(Config) -> ?line ok = function_clause_1(<<0,7,0,7,42>>), ?line fc(function_clause_1, [<<0,1,2,3>>], diff --git a/lib/compiler/test/compilation_SUITE.erl b/lib/compiler/test/compilation_SUITE.erl index 1343fbd1c9..664582a3a8 100644 --- a/lib/compiler/test/compilation_SUITE.erl +++ b/lib/compiler/test/compilation_SUITE.erl @@ -44,7 +44,7 @@ all() -> trycatch_4, opt_crash, otp_5404, otp_5436, otp_5481, otp_5553, otp_5632, otp_5714, otp_5872, otp_6121, otp_6121a, otp_6121b, otp_7202, otp_7345, on_load, - string_table,otp_8949_a,otp_8949_a]. + string_table,otp_8949_a,otp_8949_a,split_cases]. groups() -> [{vsn, [], [vsn_1, vsn_2, vsn_3]}]. @@ -427,9 +427,9 @@ self_compile_1(Config, Prefix, Opts) -> %% Compile the compiler again using the newly compiled compiler. %% (In another node because reloading the compiler would disturb cover.) CompilerB = Prefix++"compiler_b", - ?line CompB = make_compiler_dir(Priv, Prefix++"compiler_b"), + CompB = make_compiler_dir(Priv, CompilerB), ?line VsnB = VsnA ++ ".0", - ?line self_compile_node(CompilerB, CompA, CompB, VsnB, Opts), + self_compile_node(CompA, CompB, VsnB, Opts), %% Compare compiler directories. ?line compare_compilers(CompA, CompB), @@ -438,21 +438,26 @@ self_compile_1(Config, Prefix, Opts) -> ?line CompilerC = Prefix++"compiler_c", ?line CompC = make_compiler_dir(Priv, CompilerC), ?line VsnC = VsnB ++ ".0", - ?line self_compile_node(CompilerC, CompB, CompC, VsnC, Opts), + self_compile_node(CompB, CompC, VsnC, Opts), ?line compare_compilers(CompB, CompC), ?line test_server:timetrap_cancel(Dog), ok. -self_compile_node(NodeName0, CompilerDir, OutDir, Version, Opts) -> - ?line NodeName = list_to_atom(NodeName0), - ?line Dog = test_server:timetrap(test_server:minutes(10)), +self_compile_node(CompilerDir, OutDir, Version, Opts) -> + ?line Dog = test_server:timetrap(test_server:minutes(15)), ?line Pa = "-pa " ++ filename:dirname(code:which(?MODULE)) ++ " -pa " ++ CompilerDir, - ?line {ok,Node} = start_node(NodeName, Pa), ?line Files = compiler_src(), - ?line ok = rpc:call(Node, ?MODULE, compile_compiler, [Files,OutDir,Version,Opts]), - ?line test_server:stop_node(Node), + + %% We don't want the cover server started on the other node, + %% because it will load the same cover-compiled code as on this + %% node. Use a shielded node to prevent the cover server from + %% being started. + ?t:run_on_shielded_node( + fun() -> + compile_compiler(Files, OutDir, Version, Opts) + end, Pa), ?line test_server:timetrap_cancel(Dog), ok. @@ -465,9 +470,12 @@ compile_compiler(Files, OutDir, Version, InlineOpts) -> {d,'COMPILER_VSN',"\""++Version++"\""}, nowarn_shadow_vars, {i,filename:join(code:lib_dir(stdlib), "include")}|InlineOpts], - lists:foreach(fun(File) -> - {ok,_} = compile:file(File, Opts) - end, Files). + test_lib:p_run(fun(File) -> + case compile:file(File, Opts) of + {ok,_} -> ok; + _ -> error + end + end, Files). compiler_src() -> filelib:wildcard(filename:join([code:lib_dir(compiler), "src", "*.erl"])). @@ -657,5 +665,19 @@ otp_8949_b(A, B) -> id(Var) end. +split_cases(_) -> + dummy1 = do_split_cases(x), + {'EXIT',{{badmatch,b},_}} = (catch do_split_cases(y)), + ok. + +do_split_cases(A) -> + case A of + x -> + Z = dummy1; + _ -> + Z = dummy2, + a=b + end, + Z. id(I) -> I. diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl index fedbd98f71..32d53add53 100644 --- a/lib/compiler/test/compile_SUITE.erl +++ b/lib/compiler/test/compile_SUITE.erl @@ -29,7 +29,8 @@ binary/1, makedep/1, cond_and_ifdef/1, listings/1, listings_big/1, other_output/1, package_forms/1, encrypted_abstr/1, bad_record_use1/1, bad_record_use2/1, strict_record/1, - missing_testheap/1, cover/1, env/1, core/1, asm/1]). + missing_testheap/1, cover/1, env/1, core/1, asm/1, + sys_pre_attributes/1]). -export([init/3]). @@ -45,7 +46,8 @@ all() -> binary, makedep, cond_and_ifdef, listings, listings_big, other_output, package_forms, encrypted_abstr, {group, bad_record_use}, strict_record, - missing_testheap, cover, env, core, asm]. + missing_testheap, cover, env, core, asm, + sys_pre_attributes]. groups() -> [{bad_record_use, [], @@ -785,6 +787,37 @@ do_asm(Beam, Outdir) -> error end. +sys_pre_attributes(Config) -> + DataDir = ?config(data_dir, Config), + File = filename:join(DataDir, "attributes.erl"), + Mod = attributes, + CommonOpts = [binary,report,verbose, + {parse_transform,sys_pre_attributes}], + PreOpts = [{attribute,delete,deleted}], + PostOpts = [{attribute,insert,inserted,"value"}], + PrePostOpts = [{attribute,replace,replaced,42}, + {attribute,replace,replace_nonexisting,new}], + {ok,Mod,Code} = compile:file(File, PrePostOpts ++ PreOpts ++ + PostOpts ++ CommonOpts), + code:load_binary(Mod, File, Code), + Attr = Mod:module_info(attributes), + io:format("~p", [Attr]), + {inserted,"value"} = lists:keyfind(inserted, 1, Attr), + {replaced,[42]} = lists:keyfind(replaced, 1, Attr), + {replace_nonexisting,[new]} = lists:keyfind(replace_nonexisting, 1, Attr), + false = lists:keymember(deleted, 1, Attr), + + %% Cover more code. + {ok,Mod,_} = compile:file(File, PostOpts ++ CommonOpts), + {ok,Mod,_} = compile:file(File, CommonOpts -- [verbose]), + {ok,Mod,_} = compile:file(File, PreOpts ++ CommonOpts), + {ok,Mod,_} = compile:file(File, + [{attribute,replace,replaced,42}|CommonOpts]), + {ok,Mod,Code} = compile:file(File, PrePostOpts ++ PreOpts ++ + PostOpts ++ CommonOpts -- + [report,verbose]), + ok. + %%% %%% Utilities. %%% diff --git a/lib/compiler/test/compile_SUITE_data/attributes.erl b/lib/compiler/test/compile_SUITE_data/attributes.erl new file mode 100644 index 0000000000..9c3451d272 --- /dev/null +++ b/lib/compiler/test/compile_SUITE_data/attributes.erl @@ -0,0 +1,23 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2012. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(attributes). +-deleted(dummy). +-replaced(dummy). + diff --git a/lib/compiler/test/compiler.cover b/lib/compiler/test/compiler.cover index 9fc4c7dd43..3fd7fc1937 100644 --- a/lib/compiler/test/compiler.cover +++ b/lib/compiler/test/compiler.cover @@ -1,5 +1,5 @@ {incl_app,compiler,details}. %% -*- erlang -*- -{excl_mods,[sys_pre_attributes,core_scan,core_parse]}. +{excl_mods,compiler,[core_scan,core_parse]}. diff --git a/lib/compiler/test/core_SUITE.erl b/lib/compiler/test/core_SUITE.erl index 26173c62b8..874e02803d 100644 --- a/lib/compiler/test/core_SUITE.erl +++ b/lib/compiler/test/core_SUITE.erl @@ -21,7 +21,9 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, init_per_testcase/2,end_per_testcase/2, - dehydrated_itracer/1,nested_tries/1]). + dehydrated_itracer/1,nested_tries/1, + make_effect_seq/1,eval_is_boolean/1, + unsafe_case/1,nomatch_shadow/1,reversed_annos/1]). -include_lib("test_server/include/test_server.hrl"). @@ -41,7 +43,8 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> test_lib:recompile(?MODULE), - [dehydrated_itracer, nested_tries]. + [dehydrated_itracer,nested_tries,make_effect_seq, + eval_is_boolean,unsafe_case,nomatch_shadow,reversed_annos]. groups() -> []. @@ -61,19 +64,18 @@ end_per_group(_GroupName, Config) -> ?comp(dehydrated_itracer). ?comp(nested_tries). +?comp(make_effect_seq). +?comp(eval_is_boolean). +?comp(unsafe_case). +?comp(nomatch_shadow). +?comp(reversed_annos). try_it(Mod, Conf) -> - ?line Src = filename:join(?config(data_dir, Conf), atom_to_list(Mod)), - ?line Out = ?config(priv_dir,Conf), - ?line io:format("Compiling: ~s\n", [Src]), - ?line CompRc0 = compile:file(Src, [from_core,{outdir,Out},report,time]), - ?line io:format("Result: ~p\n",[CompRc0]), - ?line {ok,Mod} = CompRc0, - - ?line {module,Mod} = code:load_abs(filename:join(Out, Mod)), - ?line ok = Mod:Mod(), - ok. - - - - + Src = filename:join(?config(data_dir, Conf), atom_to_list(Mod)), + compile_and_load(Src, []), + compile_and_load(Src, [no_copt]). + +compile_and_load(Src, Opts) -> + {ok,Mod,Bin} = compile:file(Src, [from_core,report,time,binary|Opts]), + {module,Mod} = code:load_binary(Mod, Mod, Bin), + ok = Mod:Mod(). diff --git a/lib/compiler/test/core_SUITE_data/eval_is_boolean.core b/lib/compiler/test/core_SUITE_data/eval_is_boolean.core new file mode 100644 index 0000000000..6a68b1414d --- /dev/null +++ b/lib/compiler/test/core_SUITE_data/eval_is_boolean.core @@ -0,0 +1,22 @@ +module 'eval_is_boolean' ['eval_is_boolean'/0] + attributes [] +'eval_is_boolean'/0 = + %% Line 4 + fun () -> + case <> of + <> when 'true' -> + case call 'erlang':'is_boolean'(call 'erlang':'make_ref'()) of + <'false'> when 'true' -> + 'ok' + ( <_cor1> when 'true' -> + primop 'match_fail' + ({'badmatch',_cor1}) + -| ['compiler_generated'] ) + end + ( <> when 'true' -> + ( primop 'match_fail' + ({'function_clause'}) + -| [{'function_name',{'eval_is_boolean',0}}] ) + -| ['compiler_generated'] ) + end +end diff --git a/lib/compiler/test/core_SUITE_data/make_effect_seq.core b/lib/compiler/test/core_SUITE_data/make_effect_seq.core new file mode 100644 index 0000000000..9941e63b76 --- /dev/null +++ b/lib/compiler/test/core_SUITE_data/make_effect_seq.core @@ -0,0 +1,51 @@ +module 'make_effect_seq' ['make_effect_seq'/0] + attributes [] +'make_effect_seq'/0 = + fun () -> + case <> of + <> when 'true' -> + let <_cor0> = + catch + apply 't'/1 + ('a') + in + case _cor0 of + <{'EXIT',{'badarg',_cor3}}> when 'true' -> + let <_cor4> = + apply 't'/1 + ({'a','b','c'}) + in + case _cor4 of + <'ok'> when 'true' -> + ( _cor4 + -| ['compiler_generated'] ) + ( <_cor2> when 'true' -> + primop 'match_fail' + ({'badmatch',_cor2}) + -| ['compiler_generated'] ) + end + ( <_cor1> when 'true' -> + primop 'match_fail' + ({'badmatch',_cor1}) + -| ['compiler_generated'] ) + end + ( <> when 'true' -> + ( primop 'match_fail' + ({'function_clause'}) + -| [{'function_name',{'make_effect_seq',0}}] ) + -| ['compiler_generated'] ) + end +'t'/1 = + fun (_cor0) -> + case _cor0 of + <T> when 'true' -> + do + {'ok',call 'erlang':'element'(2, T)} + 'ok' + ( <_cor2> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_cor2}) + -| [{'function_name',{'t',1}}] ) + -| ['compiler_generated'] ) + end +end diff --git a/lib/compiler/test/core_SUITE_data/nomatch_shadow.core b/lib/compiler/test/core_SUITE_data/nomatch_shadow.core new file mode 100644 index 0000000000..565d9dc0f3 --- /dev/null +++ b/lib/compiler/test/core_SUITE_data/nomatch_shadow.core @@ -0,0 +1,28 @@ +module 'nomatch_shadow' ['nomatch_shadow'/0] + attributes [] +'nomatch_shadow'/0 = + fun () -> + case <> of + <> when 'true' -> + apply 't'/1 + (42) + ( <> when 'true' -> + ( primop 'match_fail' + ({'function_clause'}) + -| [{'function_name',{'nomatch_shadow',0}}] ) + -| ['compiler_generated'] ) + end +'t'/1 = + fun (_cor0) -> + case _cor0 of + <42> when 'true' -> + 'ok' + <42> when 'true' -> + 'ok' + ( <_cor1> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_cor1}) + -| [{'function_name',{'t',1}}] ) + -| ['compiler_generated'] ) + end +end diff --git a/lib/compiler/test/core_SUITE_data/reversed_annos.core b/lib/compiler/test/core_SUITE_data/reversed_annos.core new file mode 100644 index 0000000000..95b3cd52d6 --- /dev/null +++ b/lib/compiler/test/core_SUITE_data/reversed_annos.core @@ -0,0 +1,49 @@ +module 'reversed_annos' ['reversed_annos'/0] + attributes [] +'reversed_annos'/0 = + fun () -> + case <> of + <> when 'true' -> + case apply 't'/1 + (['a']) of + <'ok'> when 'true' -> + let <_cor2> = + apply 't'/1 + (['a'|['b']]) + in + case _cor2 of + <'ok'> when 'true' -> + ( _cor2 + -| ['compiler_generated'] ) + ( <_cor1> when 'true' -> + primop 'match_fail' + ({'badmatch',_cor1}) + -| ['compiler_generated'] ) + end + ( <_cor0> when 'true' -> + primop 'match_fail' + ({'badmatch',_cor0}) + -| ['compiler_generated'] ) + end + ( <> when 'true' -> + ( primop 'match_fail' + ({'function_clause'}) + -| [{'function_name',{'reversed_annos',0}}] ) + -| ['compiler_generated'] ) + end +'t'/1 = + fun (_cor0) -> + case _cor0 of + <[_cor2|_cor3]> when 'true' -> + 'ok' + %% Cover v3_kernel:get_line/1. + ( <['a']> when 'true' -> + 'error' + -| [{'file',"reversed_annos.erl"},11] ) + ( <_cor1> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_cor1}) + -| [{'function_name',{'t',1}}] ) + -| ['compiler_generated'] ) + end +end diff --git a/lib/compiler/test/core_SUITE_data/unsafe_case.core b/lib/compiler/test/core_SUITE_data/unsafe_case.core new file mode 100644 index 0000000000..84cb2c310a --- /dev/null +++ b/lib/compiler/test/core_SUITE_data/unsafe_case.core @@ -0,0 +1,25 @@ +module 'unsafe_case' ['unsafe_case'/0] + attributes [] +'unsafe_case'/0 = + fun () -> + case apply 't'/1 + (42) of + <{'ok',42}> when 'true' -> + 'ok' + ( <_cor0> when 'true' -> + primop 'match_fail' + ({'badmatch',_cor0}) + -| ['compiler_generated'] ) + end +'t'/1 = + fun (_cor0) -> + case _cor0 of + <X> + when call 'erlang':'>' + (_cor0, + 0) -> + {'ok',X} + %% The default case is intentionally missing + %% to cover v3_kernel:build_match/2. + end +end diff --git a/lib/compiler/test/core_fold_SUITE.erl b/lib/compiler/test/core_fold_SUITE.erl index ac14d36e82..fb5ec88c9f 100644 --- a/lib/compiler/test/core_fold_SUITE.erl +++ b/lib/compiler/test/core_fold_SUITE.erl @@ -214,6 +214,7 @@ coverage(Config) when is_list(Config) -> (catch cover_will_match_list_type({a,b,c,d})), ?line a = cover_remove_non_vars_alias({a,b,c}), ?line error = cover_will_match_lit_list(), + {ok,[a]} = cover_is_safe_bool_expr(a), %% Make sure that we don't attempt to make literals %% out of pids. (Putting a pid into a #c_literal{} @@ -249,4 +250,17 @@ cover_will_match_lit_list() -> error end. +cover_is_safe_bool_expr(X) -> + %% Use a try...catch that looks like a try...catch in a guard. + try + %% let V = [X] in {ok,V} + %% is_safe_simple([X]) ==> true + %% is_safe_bool_expr([X]) ==> false + V = [X], + {ok,V} + catch + _:_ -> + false + end. + id(I) -> I. diff --git a/lib/compiler/test/misc_SUITE.erl b/lib/compiler/test/misc_SUITE.erl index 9b414cade6..5e13a93c52 100644 --- a/lib/compiler/test/misc_SUITE.erl +++ b/lib/compiler/test/misc_SUITE.erl @@ -190,6 +190,15 @@ silly_coverage(Config) when is_list(Config) -> {label,2}|non_proper_list]}],99}, ?line expect_error(fun() -> beam_block:module(BlockInput, []) end), + %% beam_except + ExceptInput = {?MODULE,[{foo,0}],[], + [{function,foo,0,2, + [{label,1}, + {line,loc}, + {func_info,{atom,?MODULE},{atom,foo},0}, + {label,2}|non_proper_list]}],99}, + expect_error(fun() -> beam_except:module(ExceptInput, []) end), + %% beam_bool BoolInput = {?MODULE,[{foo,0}],[], [{function,foo,0,2, @@ -253,8 +262,15 @@ expect_error(Fun) -> io:format("~p", [Any]), ?t:fail(call_was_supposed_to_fail) catch - _:_ -> - io:format("~p\n", [erlang:get_stacktrace()]) + Class:Reason -> + Stk = erlang:get_stacktrace(), + io:format("~p:~p\n~p\n", [Class,Reason,Stk]), + case {Class,Reason} of + {error,undef} -> + ?t:fail(not_supposed_to_fail_with_undef); + {_,_} -> + ok + end end. confused_literals(Config) when is_list(Config) -> diff --git a/lib/compiler/test/parteval_SUITE.erl b/lib/compiler/test/parteval_SUITE.erl deleted file mode 100644 index 6b1ae38c1b..0000000000 --- a/lib/compiler/test/parteval_SUITE.erl +++ /dev/null @@ -1,66 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1998-2011. All Rights Reserved. -%% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%% -%% %CopyrightEnd% -%% --module(parteval_SUITE). - --include_lib("test_server/include/test_server.hrl"). - --export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, - init_per_group/2,end_per_group/2, pe2/1]). - -suite() -> [{ct_hooks,[ts_install_cth]}]. - -all() -> - [pe2]. - -groups() -> - []. - -init_per_suite(Config) -> - Config. - -end_per_suite(_Config) -> - ok. - -init_per_group(_GroupName, Config) -> - Config. - -end_per_group(_GroupName, Config) -> - Config. - - -%% (This is more general than needed, since we once compiled the same -%% source code with and without a certain option.) -compile_and_load(Srcname, Outdir, Module, Options) -> - ?line Objname = filename:join(Outdir, "t1") ++ code:objfile_extension(), - ?line {ok, Module} = - compile:file(Srcname, - [{d, 'M', Module}, {outdir, Outdir}] ++ Options), - ?line {ok, B} = file:read_file(Objname), - ?line {module, Module} = code:load_binary(Module, Objname, B), - B. - -pe2(Config) when is_list(Config) -> - ?line DataDir = ?config(data_dir, Config), - ?line PrivDir = ?config(priv_dir, Config), - ?line Srcname = filename:join(DataDir, "t1.erl"), - ?line compile_and_load(Srcname, PrivDir, t1, []), - - ?line {Correct, Actual} = t1:run(), - ?line Correct = Actual, - ok. diff --git a/lib/compiler/test/parteval_SUITE_data/t1.erl b/lib/compiler/test/parteval_SUITE_data/t1.erl deleted file mode 100644 index 5e4a40f103..0000000000 --- a/lib/compiler/test/parteval_SUITE_data/t1.erl +++ /dev/null @@ -1,140 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1998-2009. All Rights Reserved. -%% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%% -%% %CopyrightEnd% -%% --module(?M). - --compile(export_all). - -%%% The arity-0 functions are all called from the test suite. - -f2() -> - size({1,2}). - -i() -> - case [] of - [] -> - ok; - X -> - hopp - end. - -e() -> - case 4+5 of -% X when X>10 -> kvock; % not removed by BEAM opt. - {X,X} when list(X) -> - kvack; - 9 -> - ok; - _ -> - ko - end. - -f() -> - element(2,{a,b,c,d}), - erlang:element(2,{a,b,c,d}), - "hej" ++ "hopp". - -g(X) -> - if - float(3.4) -> - hej; - X == 5, 4==4 -> - japp; - 4 == 4, size({1,2}) == 1 -> - ok - end. - -g() -> - {g(3),g(5)}. - -bliff() -> - if - 3==4 -> - himm - end. - -fi() -> - case 4 of - X when 4==3 -> - {X}; - 4 -> - 4; - _ -> - ok - end. - -iff() when 3==2 -> - if - 3 == 4 -> - baff; - 3 == 3 -> - nipp - end. - -sleep(I) -> receive after I -> ok end. - -sleep() -> - sleep(45). - -s() -> - case 4 of - 3 -> - ok - end. - -error_reason(R) when atom(R) -> - R; -error_reason(R) when tuple(R) -> - error_reason(element(1, R)). - -plusplus() -> - ?MODULE ++ " -> mindre snygg felhantering". - -call_it(F) -> - case (catch apply(?MODULE, F, [])) of - {'EXIT', R0} -> - {'EXIT', error_reason(R0)}; - V -> - V - end. - -run() -> - L = [{f2, 2}, - {i, ok}, - {e, ok}, - {f, "hejhopp"}, - {g, {hej, hej}}, - {bliff, {'EXIT', if_clause}}, - {fi, 4}, - {iff, {'EXIT', function_clause}}, - {sleep, ok}, - {s, {'EXIT', case_clause}, - {plusplus, {'EXIT', badarg}}}], - Actual = [call_it(F) || {F, _} <- L], - Correct = [C || {_, C} <- L], - {Correct, Actual}. - - -%%% Don't call, only compile. -t(A) -> - receive - A when 1==2 -> - ok; - B -> - B - end. diff --git a/lib/compiler/test/test_lib.erl b/lib/compiler/test/test_lib.erl index 53d8c04169..2295592a38 100644 --- a/lib/compiler/test/test_lib.erl +++ b/lib/compiler/test/test_lib.erl @@ -77,7 +77,14 @@ get_data_dir(Config) -> %% Will fail the test case if there were any errors. p_run(Test, List) -> - N = erlang:system_info(schedulers) + 1, + N = case ?t:is_cover() of + false -> + erlang:system_info(schedulers); + true -> + %% Cover is running. Using more than one process + %% will probably only slow down compilation. + 1 + end, p_run_loop(Test, List, N, [], 0, 0). p_run_loop(_, [], _, [], Errors, Ws) -> diff --git a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl index b42f5e8191..458f3a4c81 100644 --- a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl +++ b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl @@ -359,8 +359,17 @@ store_core(Mod, Core, NoWarn, Callgraph, CServer) -> store_code_and_build_callgraph(Mod, LabeledCore, Callgraph, CServer3, NoWarn). abs_get_nowarn(Abs, M) -> - [{M, F, A} - || {attribute, _, compile, {nowarn_unused_function, {F, A}}} <- Abs]. + Opts = lists:flatten([C || {attribute, _, compile, C} <- Abs]), + Warn = erl_lint:bool_option(warn_unused_function, nowarn_unused_function, + true, Opts), + case Warn of + false -> + [{M, F, A} || {function, _, F, A, _} <- Abs]; % all functions + true -> + [{M, F, A} || + {nowarn_unused_function, FAs} <- Opts, + {F, A} <- lists:flatten([FAs])] + end. get_exported_types_from_core(Core) -> Attrs = cerl:module_attrs(Core), diff --git a/lib/dialyzer/test/user_SUITE_data/results/nowarn_unused_function_1 b/lib/dialyzer/test/user_SUITE_data/results/nowarn_unused_function_1 new file mode 100644 index 0000000000..de416455e2 --- /dev/null +++ b/lib/dialyzer/test/user_SUITE_data/results/nowarn_unused_function_1 @@ -0,0 +1,2 @@ + +nowarn_unused_function_1.erl:17: Function f3/1 will never be called diff --git a/lib/dialyzer/test/user_SUITE_data/results/nowarn_unused_function_2 b/lib/dialyzer/test/user_SUITE_data/results/nowarn_unused_function_2 new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/lib/dialyzer/test/user_SUITE_data/results/nowarn_unused_function_2 diff --git a/lib/dialyzer/test/user_SUITE_data/results/nowarn_unused_function_3 b/lib/dialyzer/test/user_SUITE_data/results/nowarn_unused_function_3 new file mode 100644 index 0000000000..8ae78673d5 --- /dev/null +++ b/lib/dialyzer/test/user_SUITE_data/results/nowarn_unused_function_3 @@ -0,0 +1,3 @@ + +nowarn_unused_function_3.erl:12: Function f2/1 will never be called +nowarn_unused_function_3.erl:9: Function f1/1 will never be called diff --git a/lib/dialyzer/test/user_SUITE_data/src/nowarn_unused_function_1.erl b/lib/dialyzer/test/user_SUITE_data/src/nowarn_unused_function_1.erl new file mode 100644 index 0000000000..fcce532f73 --- /dev/null +++ b/lib/dialyzer/test/user_SUITE_data/src/nowarn_unused_function_1.erl @@ -0,0 +1,18 @@ +%% Test that option 'nowarn_unused_funcion' works similarly in +%% Dialyzer as in the compiler. + +-module(nowarn_unused_function_1). + +-compile(warn_unused_function). + +-compile({nowarn_unused_function,f1/1}). +f1(_) -> + a. + +-compile({nowarn_unused_function,[{f2,1}]}). +f2(_) -> + a. + +-compile({warn_unused_function,[{f3,1}]}). +f3(_) -> + a. diff --git a/lib/dialyzer/test/user_SUITE_data/src/nowarn_unused_function_2.erl b/lib/dialyzer/test/user_SUITE_data/src/nowarn_unused_function_2.erl new file mode 100644 index 0000000000..9bc3ab14ea --- /dev/null +++ b/lib/dialyzer/test/user_SUITE_data/src/nowarn_unused_function_2.erl @@ -0,0 +1,18 @@ +%% Test that option 'nowarn_unused_funcion' works similarly in +%% Dialyzer as in the compiler. + +-module(nowarn_unused_function_2). + +-compile(nowarn_unused_function). + +-compile({warn_unused_function,f1/1}). +f1(_) -> + a. + +-compile({warn_unused_function,[{f2,1}]}). +f2(_) -> + a. + +-compile({nowarn_unused_function,[{f3,1}]}). +f3(_) -> + a. diff --git a/lib/dialyzer/test/user_SUITE_data/src/nowarn_unused_function_3.erl b/lib/dialyzer/test/user_SUITE_data/src/nowarn_unused_function_3.erl new file mode 100644 index 0000000000..604c5e436b --- /dev/null +++ b/lib/dialyzer/test/user_SUITE_data/src/nowarn_unused_function_3.erl @@ -0,0 +1,16 @@ +%% Test that option 'nowarn_unused_funcion' works similarly in +%% Dialyzer as in the compiler. + +-module(nowarn_unused_function_3). + +-compile({warn_unused_function,[{f1,1},{f2,1}]}). +-compile({nowarn_unused_function,[{f3,1}]}). + +f1(_) -> + a. + +f2(_) -> + a. + +f3(_) -> + a. diff --git a/lib/diameter/examples/GNUmakefile b/lib/diameter/examples/code/GNUmakefile index 4c3f87939b..a0669119d2 100644 --- a/lib/diameter/examples/GNUmakefile +++ b/lib/diameter/examples/code/GNUmakefile @@ -1,19 +1,19 @@ -# +# # %CopyrightBegin% -# +# # Copyright Ericsson AB 2010-2011. All Rights Reserved. -# +# # The contents of this file are subject to the Erlang Public License, # Version 1.1, (the "License"); you may not use this file except in # compliance with the License. You should have received a copy of the # Erlang Public License along with this software. If not, it can be # retrieved online at http://www.erlang.org/. -# +# # Software distributed under the License is distributed on an "AS IS" # basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See # the License for the specific language governing rights and limitations # under the License. -# +# # %CopyrightEnd% # diff --git a/lib/diameter/examples/client.erl b/lib/diameter/examples/code/client.erl index 36a77dd524..9e65f98de0 100644 --- a/lib/diameter/examples/client.erl +++ b/lib/diameter/examples/code/client.erl @@ -112,7 +112,7 @@ cast(Name) -> {'Auth-Application-Id', 0}, {'Re-Auth-Request-Type', 1}], diameter:call(Name, ?APP_ALIAS, RAR, [detach]). - + cast() -> cast(?SVC_NAME). diff --git a/lib/diameter/examples/client_cb.erl b/lib/diameter/examples/code/client_cb.erl index 524a8f94a1..524a8f94a1 100644 --- a/lib/diameter/examples/client_cb.erl +++ b/lib/diameter/examples/code/client_cb.erl diff --git a/lib/diameter/examples/peer.erl b/lib/diameter/examples/code/peer.erl index 89203e15c3..89203e15c3 100644 --- a/lib/diameter/examples/peer.erl +++ b/lib/diameter/examples/code/peer.erl diff --git a/lib/diameter/examples/redirect.erl b/lib/diameter/examples/code/redirect.erl index b54701243f..b54701243f 100644 --- a/lib/diameter/examples/redirect.erl +++ b/lib/diameter/examples/code/redirect.erl diff --git a/lib/diameter/examples/redirect_cb.erl b/lib/diameter/examples/code/redirect_cb.erl index ea7ad38749..ea7ad38749 100644 --- a/lib/diameter/examples/redirect_cb.erl +++ b/lib/diameter/examples/code/redirect_cb.erl diff --git a/lib/diameter/examples/relay.erl b/lib/diameter/examples/code/relay.erl index deecb1cfc0..deecb1cfc0 100644 --- a/lib/diameter/examples/relay.erl +++ b/lib/diameter/examples/code/relay.erl diff --git a/lib/diameter/examples/relay_cb.erl b/lib/diameter/examples/code/relay_cb.erl index 9ed6517d5c..9ed6517d5c 100644 --- a/lib/diameter/examples/relay_cb.erl +++ b/lib/diameter/examples/code/relay_cb.erl diff --git a/lib/diameter/examples/sctp.erl b/lib/diameter/examples/code/sctp.erl index 2e0e9d8b0b..08de023571 100644 --- a/lib/diameter/examples/sctp.erl +++ b/lib/diameter/examples/code/sctp.erl @@ -1,3 +1,21 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010-2011. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% -module(sctp). diff --git a/lib/diameter/examples/server.erl b/lib/diameter/examples/code/server.erl index ebb408e501..ebb408e501 100644 --- a/lib/diameter/examples/server.erl +++ b/lib/diameter/examples/code/server.erl diff --git a/lib/diameter/examples/server_cb.erl b/lib/diameter/examples/code/server_cb.erl index 43b8e24b5c..43b8e24b5c 100644 --- a/lib/diameter/examples/server_cb.erl +++ b/lib/diameter/examples/code/server_cb.erl diff --git a/lib/diameter/examples/dict/rfc4004_mip.dia b/lib/diameter/examples/dict/rfc4004_mip.dia new file mode 100644 index 0000000000..575ad4394a --- /dev/null +++ b/lib/diameter/examples/dict/rfc4004_mip.dia @@ -0,0 +1,280 @@ +;; +;; %CopyrightBegin% +;; +;; Copyright Ericsson AB 2010-2011. All Rights Reserved. +;; +;; The contents of this file are subject to the Erlang Public License, +;; Version 1.1, (the "License"); you may not use this file except in +;; compliance with the License. You should have received a copy of the +;; Erlang Public License along with this software. If not, it can be +;; retrieved online at http://www.erlang.org/. +;; +;; Software distributed under the License is distributed on an "AS IS" +;; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +;; the License for the specific language governing rights and limitations +;; under the License. +;; +;; %CopyrightEnd% +;; + +;; +;; RFC 4004, Diameter Mobile IPv4 Application +;; +;; Edits: +;; +;; - MIP-nonce -> MIP-Nonce +;; - Session-ID -> Session-Id +;; - Omit MIP-HA-to-MN-SPI, MIP-MN-FA-SPI and MIP-MN-HA-SPI, none of +;; which are defined. +;; + +@id 2 + +@inherits rfc3588_base + +;; =========================================================================== + +@avp_types + + MIP-Reg-Request 320 OctetString M + MIP-Reg-Reply 321 OctetString M + MIP-MN-AAA-Auth 322 Grouped M + MIP-Mobile-Node-Address 333 Address M + MIP-Home-Agent-Address 334 Address M + MIP-Candidate-Home-Agent-Host 336 DiamIdent M + MIP-Feature-Vector 337 Unsigned32 M + MIP-Auth-Input-Data-Length 338 Unsigned32 M + MIP-Authenticator-Length 339 Unsigned32 M + MIP-Authenticator-Offset 340 Unsigned32 M + MIP-MN-AAA-SPI 341 Unsigned32 M + MIP-Filter-Rule 342 IPFilterRule M + MIP-FA-Challenge 344 OctetString M + MIP-Originating-Foreign-AAA 347 Grouped M + MIP-Home-Agent-Host 348 Grouped M + + MIP-FA-to-HA-SPI 318 Unsigned32 M + MIP-FA-to-MN-SPI 319 Unsigned32 M + MIP-HA-to-FA-SPI 323 Unsigned32 M + MIP-MN-to-FA-MSA 325 Grouped M + MIP-FA-to-MN-MSA 326 Grouped M + MIP-FA-to-HA-MSA 328 Grouped M + MIP-HA-to-FA-MSA 329 Grouped M + MIP-MN-to-HA-MSA 331 Grouped M + MIP-HA-to-MN-MSA 332 Grouped M + MIP-Nonce 335 OctetString M + MIP-Session-Key 343 OctetString M + MIP-Algorithm-Type 345 Enumerated M + MIP-Replay-Mode 346 Enumerated M + MIP-MSA-Lifetime 367 Unsigned32 M + +;; =========================================================================== + +@messages + + ;; 5.1. AA-Mobile-Node-Request + + AMR ::= < Diameter Header: 260, REQ, PXY > + + < Session-Id > + { Auth-Application-Id } + { User-Name } + { Destination-Realm } + { Origin-Host } + { Origin-Realm } + { MIP-Reg-Request } + { MIP-MN-AAA-Auth } + [ Acct-Multi-Session-Id ] + [ Destination-Host ] + [ Origin-State-Id ] + [ MIP-Mobile-Node-Address ] + [ MIP-Home-Agent-Address ] + [ MIP-Feature-Vector ] + [ MIP-Originating-Foreign-AAA ] + [ Authorization-Lifetime ] + [ Auth-Session-State ] + [ MIP-FA-Challenge ] + [ MIP-Candidate-Home-Agent-Host ] + [ MIP-Home-Agent-Host ] + [ MIP-HA-to-FA-SPI ] + * [ Proxy-Info ] + * [ Route-Record ] + * [ AVP ] + + ;; 5.2. AA-Mobile-Node-Answer + + AMA ::= < Diameter Header: 260, PXY > + + < Session-Id > + { Auth-Application-Id } + { Result-Code } + { Origin-Host } + { Origin-Realm } + [ Acct-Multi-Session-Id ] + [ User-Name ] + [ Authorization-Lifetime ] + [ Auth-Session-State ] + [ Error-Message ] + [ Error-Reporting-Host ] + [ Re-Auth-Request-Type ] + [ MIP-Feature-Vector ] + [ MIP-Reg-Reply ] + [ MIP-MN-to-FA-MSA ] + [ MIP-MN-to-HA-MSA ] + [ MIP-FA-to-MN-MSA ] + [ MIP-FA-to-HA-MSA ] + [ MIP-HA-to-MN-MSA ] + [ MIP-MSA-Lifetime ] + [ MIP-Home-Agent-Address ] + [ MIP-Mobile-Node-Address ] + * [ MIP-Filter-Rule ] + [ Origin-State-Id ] + * [ Proxy-Info ] + * [ AVP ] + + ;; 5.3. Home-Agent-MIP-Request + + HAR ::= < Diameter Header: 262, REQ, PXY > + + < Session-Id > + { Auth-Application-Id } + { Authorization-Lifetime } + { Auth-Session-State } + { MIP-Reg-Request } + { Origin-Host } + { Origin-Realm } + { User-Name } + { Destination-Realm } + { MIP-Feature-Vector } + [ Destination-Host ] + [ MIP-MN-to-HA-MSA ] + [ MIP-MN-to-FA-MSA ] + [ MIP-HA-to-MN-MSA ] + [ MIP-HA-to-FA-MSA ] + [ MIP-MSA-Lifetime ] + [ MIP-Originating-Foreign-AAA ] + [ MIP-Mobile-Node-Address ] + [ MIP-Home-Agent-Address ] + * [ MIP-Filter-Rule ] + [ Origin-State-Id ] + * [ Proxy-Info ] + * [ Route-Record ] + * [ AVP ] + + ;; 5.4. Home-Agent-MIP-Answer + + HAA ::= < Diameter Header: 262, PXY > + + < Session-Id > + { Auth-Application-Id } + { Result-Code } + { Origin-Host } + { Origin-Realm } + [ Acct-Multi-Session-Id ] + [ User-Name ] + [ Error-Reporting-Host ] + [ Error-Message ] + [ MIP-Reg-Reply ] + [ MIP-Home-Agent-Address ] + [ MIP-Mobile-Node-Address ] + [ MIP-FA-to-HA-SPI ] + [ MIP-FA-to-MN-SPI ] + [ Origin-State-Id ] + * [ Proxy-Info ] + * [ AVP ] + +;; =========================================================================== + +@grouped + + MIP-MN-AAA-Auth ::= < AVP Header: 322 > + + { MIP-MN-AAA-SPI } + { MIP-Auth-Input-Data-Length } + { MIP-Authenticator-Length } + { MIP-Authenticator-Offset } + * [ AVP ] + + + MIP-Originating-Foreign-AAA ::= < AVP Header: 347 > + + { Origin-Realm } + { Origin-Host } + * [ AVP ] + + MIP-Home-Agent-Host ::= < AVP Header: 348 > + + { Destination-Realm } + { Destination-Host } + * [ AVP ] + + MIP-FA-to-MN-MSA ::= < AVP Header: 326 > + + { MIP-FA-to-MN-SPI } + { MIP-Algorithm-Type } + { MIP-Session-Key } + * [ AVP ] + + MIP-FA-to-HA-MSA ::= < AVP Header: 328 > + + { MIP-FA-to-HA-SPI } + { MIP-Algorithm-Type } + { MIP-Session-Key } + * [ AVP ] + + MIP-HA-to-FA-MSA ::= < AVP Header: 329 > + + { MIP-HA-to-FA-SPI } + { MIP-Algorithm-Type } + { MIP-Session-Key } + * [ AVP ] + + MIP-HA-to-MN-MSA ::= < AVP Header: 332 > + + ; { MIP-HA-to-MN-SPI } + { MIP-Algorithm-Type } + { MIP-Replay-Mode } + { MIP-Session-Key } + * [ AVP ] + + MIP-MN-to-FA-MSA ::= < AVP Header: 325 > + + ; { MIP-MN-FA-SPI } + { MIP-Algorithm-Type } + { MIP-Nonce } + * [ AVP ] + + MIP-MN-to-HA-MSA ::= < AVP Header: 331 > + + ; { MIP-MN-HA-SPI } + { MIP-Algorithm-Type } + { MIP-Replay-Mode } + { MIP-Nonce } + * [ AVP ] + +;; =========================================================================== + +@enum MIP-Algorithm-Type + + HMAC-SHA-1 2 + +@enum MIP-Replay-Mode + + NONE 1 + TIMESTAMPS 2 + NONCES 3 + +;; =========================================================================== + +@define Result-Code + + ;; 6.1. Transient Failures + + MIP_REPLY_FAILURE 4005 + HA_NOT_AVAILABLE 4006 + BAD_KEY 4007 + MIP_FILTER_NOT_SUPPORTED 4008 + + ;; 6.2. Permanent Failures + + NO_FOREIGN_HA_SERVICE 5024 + END_TO_END_MIP_KEY_ENCRYPTION 5025 diff --git a/lib/diameter/examples/dict/rfc4005_nas.dia b/lib/diameter/examples/dict/rfc4005_nas.dia new file mode 100644 index 0000000000..a4b44e38bb --- /dev/null +++ b/lib/diameter/examples/dict/rfc4005_nas.dia @@ -0,0 +1,740 @@ +;; +;; %CopyrightBegin% +;; +;; Copyright Ericsson AB 2010-2011. All Rights Reserved. +;; +;; The contents of this file are subject to the Erlang Public License, +;; Version 1.1, (the "License"); you may not use this file except in +;; compliance with the License. You should have received a copy of the +;; Erlang Public License along with this software. If not, it can be +;; retrieved online at http://www.erlang.org/. +;; +;; Software distributed under the License is distributed on an "AS IS" +;; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +;; the License for the specific language governing rights and limitations +;; under the License. +;; +;; %CopyrightEnd% +;; + +;; +;; RFC 4005, Diameter Network Access Server Application +;; +;; Edits: +;; +;; - Acounting-Auth-Method -> Accounting-Auth-Method +;; - Connection-Info -> ConnectInfo +;; - Framed-Appletalk-Link -> Framed-AppleTalk-Link +;; - Framed-Appletalk-Network -> Framed-AppleTalk-Network +;; - Framed-Appletalk-Zone -> Framed-AppleTalk-Zone +;; - Qos-Filter-Rule -> QoS-Filter-Rule +;; - Redirect-Host-Usase -> Redirect-Host-Usage +;; - Redirected-Host -> Redirect-Host +;; - Redirected-Host-Usage -> Redirect-Host-Usage +;; - Redirected-Host-Cache-Time -> Redirect-Max-Cache-Time +;; - Redirected-Max-Cache-Time -> Redirect-Max-Cache-Time +;; + +@id 1 + +@inherits rfc3588_base + +;; =========================================================================== + +@avp_types + + ;; 4. NAS Session AVPs + + NAS-Port 5 Unsigned32 M + NAS-Port-Id 87 UTF8String M + NAS-Port-Type 61 Enumerated M + Called-Station-Id 30 UTF8String M + Calling-Station-Id 31 UTF8String M + Connect-Info 77 UTF8String M + Originating-Line-Info 94 OctetString - + Reply-Message 18 UTF8String M + + ;; 5. NAS Authentication AVPs + + User-Password 2 OctetString M + Password-Retry 75 Unsigned32 M + Prompt 76 Enumerated M + CHAP-Auth 402 Grouped M + CHAP-Algorithm 403 Enumerated M + CHAP-Ident 404 OctetString M + CHAP-Response 405 OctetString M + CHAP-Challenge 60 OctetString M + ARAP-Password 70 OctetString M + ARAP-Challenge-Response 84 OctetString M + ARAP-Security 73 Unsigned32 M + ARAP-Security-Data 74 OctetString M + + ;; 6. NAS Authorization AVPs + + Service-Type 6 Enumerated M + Callback-Number 19 UTF8String M + Callback-Id 20 UTF8String M + Idle-Timeout 28 Unsigned32 M + Port-Limit 62 Unsigned32 M + NAS-Filter-Rule 400 IPFilterRule M + Filter-Id 11 UTF8String M + Configuration-Token 78 OctetString M + QoS-Filter-Rule 407 QoSFilterRule - + Framed-Protocol 7 Enumerated M + Framed-Routing 10 Enumerated M + Framed-MTU 12 Unsigned32 M + Framed-Compression 13 Enumerated M + Framed-IP-Address 8 OctetString M + Framed-IP-Netmask 9 OctetString M + Framed-Route 22 UTF8String M + Framed-Pool 88 OctetString M + Framed-Interface-Id 96 Unsigned64 M + Framed-IPv6-Prefix 97 OctetString M + Framed-IPv6-Route 99 UTF8String M + Framed-IPv6-Pool 100 OctetString M + Framed-IPX-Network 23 UTF8String M + Framed-AppleTalk-Link 37 Unsigned32 M + Framed-AppleTalk-Network 38 Unsigned32 M + Framed-AppleTalk-Zone 39 OctetString M + ARAP-Features 71 OctetString M + ARAP-Zone-Access 72 Enumerated M + Login-IP-Host 14 OctetString M + Login-IPv6-Host 98 OctetString M + Login-Service 15 Enumerated M + Login-TCP-Port 16 Unsigned32 M + Login-LAT-Service 34 OctetString M + Login-LAT-Node 35 OctetString M + Login-LAT-Group 36 OctetString M + Login-LAT-Port 63 OctetString M + + ;; 7. NAS Tunneling + + Tunneling 401 Grouped M + Tunnel-Type 64 Enumerated M + Tunnel-Medium-Type 65 Enumerated M + Tunnel-Client-Endpoint 66 UTF8String M + Tunnel-Server-Endpoint 67 UTF8String M + Tunnel-Password 69 OctetString M + Tunnel-Private-Group-Id 81 OctetString M + Tunnel-Assignment-Id 82 OctetString M + Tunnel-Preference 83 Unsigned32 M + Tunnel-Client-Auth-Id 90 UTF8String M + Tunnel-Server-Auth-Id 91 UTF8String M + + ;; 8. NAS Accounting + + Accounting-Input-Octets 363 Unsigned64 M + Accounting-Output-Octets 364 Unsigned64 M + Accounting-Input-Packets 365 Unsigned64 M + Accounting-Output-Packets 366 Unsigned64 M + Acct-Session-Time 46 Unsigned32 M + Acct-Authentic 45 Enumerated M + Accounting-Auth-Method 406 Enumerated M + Acct-Delay-Time 41 Unsigned32 M + Acct-Link-Count 51 Unsigned32 M + Acct-Tunnel-Connection 68 OctetString M + Acct-Tunnel-Packets-Lost 86 Unsigned32 M + + ;; 9.3. AVPs Used Only for Compatibility + + NAS-Identifier 32 UTF8String M + NAS-IP-Address 4 OctetString M + NAS-IPv6-Address 95 OctetString M + State 24 OctetString M + ;;Termination-Cause 295 Enumerated M + Origin-AAA-Protocol 408 Enumerated M + +;; =========================================================================== + +@messages + + AAR ::= < Diameter Header: 265, REQ, PXY > + + < Session-Id > + { Auth-Application-Id } + { Origin-Host } + { Origin-Realm } + { Destination-Realm } + { Auth-Request-Type } + [ Destination-Host ] + [ NAS-Identifier ] + [ NAS-IP-Address ] + [ NAS-IPv6-Address ] + [ NAS-Port ] + [ NAS-Port-Id ] + [ NAS-Port-Type ] + [ Origin-AAA-Protocol ] + [ Origin-State-Id ] + [ Port-Limit ] + [ User-Name ] + [ User-Password ] + [ Service-Type ] + [ State ] + [ Authorization-Lifetime ] + [ Auth-Grace-Period ] + [ Auth-Session-State ] + [ Callback-Number ] + [ Called-Station-Id ] + [ Calling-Station-Id ] + [ Originating-Line-Info ] + [ Connect-Info ] + [ CHAP-Auth ] + [ CHAP-Challenge ] + * [ Framed-Compression ] + [ Framed-Interface-Id ] + [ Framed-IP-Address ] + * [ Framed-IPv6-Prefix ] + [ Framed-IP-Netmask ] + [ Framed-MTU ] + [ Framed-Protocol ] + [ ARAP-Password ] + [ ARAP-Security ] + * [ ARAP-Security-Data ] + * [ Login-IP-Host ] + * [ Login-IPv6-Host ] + [ Login-LAT-Group ] + [ Login-LAT-Node ] + [ Login-LAT-Port ] + [ Login-LAT-Service ] + * [ Tunneling ] + * [ Proxy-Info ] + * [ Route-Record ] + * [ AVP ] + + AAA ::= < Diameter Header: 265, PXY > + + < Session-Id > + { Auth-Application-Id } + { Auth-Request-Type } + { Result-Code } + { Origin-Host } + { Origin-Realm } + [ User-Name ] + [ Service-Type ] + * [ Class ] + * [ Configuration-Token ] + [ Acct-Interim-Interval ] + [ Error-Message ] + [ Error-Reporting-Host ] + * [ Failed-AVP ] + [ Idle-Timeout ] + [ Authorization-Lifetime ] + [ Auth-Grace-Period ] + [ Auth-Session-State ] + [ Re-Auth-Request-Type ] + [ Multi-Round-Time-Out ] + [ Session-Timeout ] + [ State ] + * [ Reply-Message ] + [ Origin-AAA-Protocol ] + [ Origin-State-Id ] + * [ Filter-Id ] + [ Password-Retry ] + [ Port-Limit ] + [ Prompt ] + [ ARAP-Challenge-Response ] + [ ARAP-Features ] + [ ARAP-Security ] + * [ ARAP-Security-Data ] + [ ARAP-Zone-Access ] + [ Callback-Id ] + [ Callback-Number ] + [ Framed-AppleTalk-Link ] + * [ Framed-AppleTalk-Network ] + [ Framed-AppleTalk-Zone ] + * [ Framed-Compression ] + [ Framed-Interface-Id ] + [ Framed-IP-Address ] + * [ Framed-IPv6-Prefix ] + [ Framed-IPv6-Pool ] + * [ Framed-IPv6-Route ] + [ Framed-IP-Netmask ] + * [ Framed-Route ] + [ Framed-Pool ] + [ Framed-IPX-Network ] + [ Framed-MTU ] + [ Framed-Protocol ] + [ Framed-Routing ] + * [ Login-IP-Host ] + * [ Login-IPv6-Host ] + [ Login-LAT-Group ] + [ Login-LAT-Node ] + [ Login-LAT-Port ] + [ Login-LAT-Service ] + [ Login-Service ] + [ Login-TCP-Port ] + * [ NAS-Filter-Rule ] + * [ QoS-Filter-Rule ] + * [ Tunneling ] + * [ Redirect-Host ] + [ Redirect-Host-Usage ] + [ Redirect-Max-Cache-Time ] + * [ Proxy-Info ] + * [ AVP ] + + RAR ::= < Diameter Header: 258, REQ, PXY > + + < Session-Id > + { Origin-Host } + { Origin-Realm } + { Destination-Realm } + { Destination-Host } + { Auth-Application-Id } + { Re-Auth-Request-Type } + [ User-Name ] + [ Origin-AAA-Protocol ] + [ Origin-State-Id ] + [ NAS-Identifier ] + [ NAS-IP-Address ] + [ NAS-IPv6-Address ] + [ NAS-Port ] + [ NAS-Port-Id ] + [ NAS-Port-Type ] + [ Service-Type ] + [ Framed-IP-Address ] + [ Framed-IPv6-Prefix ] + [ Framed-Interface-Id ] + [ Called-Station-Id ] + [ Calling-Station-Id ] + [ Originating-Line-Info ] + [ Acct-Session-Id ] + [ Acct-Multi-Session-Id ] + [ State ] + * [ Class ] + [ Reply-Message ] + * [ Proxy-Info ] + * [ Route-Record ] + * [ AVP ] + + RAA ::= < Diameter Header: 258, PXY > + + < Session-Id > + { Result-Code } + { Origin-Host } + { Origin-Realm } + [ User-Name ] + [ Origin-AAA-Protocol ] + [ Origin-State-Id ] + [ Error-Message ] + [ Error-Reporting-Host ] + * [ Failed-AVP ] + * [ Redirect-Host ] + [ Redirect-Host-Usage ] + [ Redirect-Max-Cache-Time ] + [ Service-Type ] + * [ Configuration-Token ] + [ Idle-Timeout ] + [ Authorization-Lifetime ] + [ Auth-Grace-Period ] + [ Re-Auth-Request-Type ] + [ State ] + * [ Class ] + * [ Reply-Message ] + [ Prompt ] + * [ Proxy-Info ] + * [ AVP ] + + STR ::= < Diameter Header: 275, REQ, PXY > + + < Session-Id > + { Origin-Host } + { Origin-Realm } + { Destination-Realm } + { Auth-Application-Id } + { Termination-Cause } + [ User-Name ] + [ Destination-Host ] + * [ Class ] + [ Origin-AAA-Protocol ] + [ Origin-State-Id ] + * [ Proxy-Info ] + * [ Route-Record ] + * [ AVP ] + + STA ::= < Diameter Header: 275, PXY > + + < Session-Id > + { Result-Code } + { Origin-Host } + { Origin-Realm } + [ User-Name ] + * [ Class ] + [ Error-Message ] + [ Error-Reporting-Host ] + * [ Failed-AVP ] + [ Origin-AAA-Protocol ] + [ Origin-State-Id ] + * [ Redirect-Host ] + [ Redirect-Host-Usage ] + [ Redirect-Max-Cache-Time ] + * [ Proxy-Info ] + * [ AVP ] + + ASR ::= < Diameter Header: 274, REQ, PXY > + + < Session-Id > + { Origin-Host } + { Origin-Realm } + { Destination-Realm } + { Destination-Host } + { Auth-Application-Id } + [ User-Name ] + [ Origin-AAA-Protocol ] + [ Origin-State-Id ] + [ NAS-Identifier ] + [ NAS-IP-Address ] + [ NAS-IPv6-Address ] + [ NAS-Port ] + [ NAS-Port-Id ] + [ NAS-Port-Type ] + [ Service-Type ] + [ Framed-IP-Address ] + [ Framed-IPv6-Prefix ] + [ Framed-Interface-Id ] + [ Called-Station-Id ] + [ Calling-Station-Id ] + [ Originating-Line-Info ] + [ Acct-Session-Id ] + [ Acct-Multi-Session-Id ] + [ State ] + * [ Class ] + * [ Reply-Message ] + * [ Proxy-Info ] + * [ Route-Record ] + * [ AVP ] + + ASA ::= < Diameter Header: 274, PXY > + + < Session-Id > + { Result-Code } + { Origin-Host } + { Origin-Realm } + [ User-Name ] + [ Origin-AAA-Protocol ] + [ Origin-State-Id ] + [ State] + [ Error-Message ] + [ Error-Reporting-Host ] + * [ Failed-AVP ] + * [ Redirect-Host ] + [ Redirect-Host-Usage ] + [ Redirect-Max-Cache-Time ] + * [ Proxy-Info ] + * [ AVP ] + + ACR ::= < Diameter Header: 271, REQ, PXY > + + < Session-Id > + { Origin-Host } + { Origin-Realm } + { Destination-Realm } + { Accounting-Record-Type } + { Accounting-Record-Number } + [ Acct-Application-Id ] + [ Vendor-Specific-Application-Id ] + [ User-Name ] + [ Accounting-Sub-Session-Id ] + [ Acct-Session-Id ] + [ Acct-Multi-Session-Id ] + [ Origin-AAA-Protocol ] + [ Origin-State-Id ] + [ Destination-Host ] + [ Event-Timestamp ] + [ Acct-Delay-Time ] + [ NAS-Identifier ] + [ NAS-IP-Address ] + [ NAS-IPv6-Address ] + [ NAS-Port ] + [ NAS-Port-Id ] + [ NAS-Port-Type ] + * [ Class ] + [ Service-Type ] + [ Termination-Cause ] + [ Accounting-Input-Octets ] + [ Accounting-Input-Packets ] + [ Accounting-Output-Octets ] + [ Accounting-Output-Packets ] + [ Acct-Authentic ] + [ Accounting-Auth-Method ] + [ Acct-Link-Count ] + [ Acct-Session-Time ] + [ Acct-Tunnel-Connection ] + [ Acct-Tunnel-Packets-Lost ] + [ Callback-Id ] + [ Callback-Number ] + [ Called-Station-Id ] + [ Calling-Station-Id ] + * [ Connect-Info ] + [ Originating-Line-Info ] + [ Authorization-Lifetime ] + [ Session-Timeout ] + [ Idle-Timeout ] + [ Port-Limit ] + [ Accounting-Realtime-Required ] + [ Acct-Interim-Interval ] + * [ Filter-Id ] + * [ NAS-Filter-Rule ] + * [ QoS-Filter-Rule ] + [ Framed-AppleTalk-Link ] + [ Framed-AppleTalk-Network ] + [ Framed-AppleTalk-Zone ] + [ Framed-Compression ] + [ Framed-Interface-Id ] + [ Framed-IP-Address ] + [ Framed-IP-Netmask ] + * [ Framed-IPv6-Prefix ] + [ Framed-IPv6-Pool ] + * [ Framed-IPv6-Route ] + [ Framed-IPX-Network ] + [ Framed-MTU ] + [ Framed-Pool ] + [ Framed-Protocol ] + * [ Framed-Route ] + [ Framed-Routing ] + * [ Login-IP-Host ] + * [ Login-IPv6-Host ] + [ Login-LAT-Group ] + [ Login-LAT-Node ] + [ Login-LAT-Port ] + [ Login-LAT-Service ] + [ Login-Service ] + [ Login-TCP-Port ] + * [ Tunneling ] + * [ Proxy-Info ] + * [ Route-Record ] + * [ AVP ] + + ACA ::= < Diameter Header: 271, PXY > + + < Session-Id > + { Result-Code } + { Origin-Host } + { Origin-Realm } + { Accounting-Record-Type } + { Accounting-Record-Number } + [ Acct-Application-Id ] + [ Vendor-Specific-Application-Id ] + [ User-Name ] + [ Accounting-Sub-Session-Id ] + [ Acct-Session-Id ] + [ Acct-Multi-Session-Id ] + [ Event-Timestamp ] + [ Error-Message ] + [ Error-Reporting-Host ] + * [ Failed-AVP ] + [ Origin-AAA-Protocol ] + [ Origin-State-Id ] + [ NAS-Identifier ] + [ NAS-IP-Address ] + [ NAS-IPv6-Address ] + [ NAS-Port ] + [ NAS-Port-Id ] + [ NAS-Port-Type ] + [ Service-Type ] + [ Termination-Cause ] + [ Accounting-Realtime-Required ] + [ Acct-Interim-Interval ] + * [ Class ] + * [ Proxy-Info ] + * [ Route-Record ] + * [ AVP ] + +;; =========================================================================== + +@grouped + + CHAP-Auth ::= < AVP Header: 402 > + + { CHAP-Algorithm } + { CHAP-Ident } + [ CHAP-Response ] + * [ AVP ] + + Tunneling ::= < AVP Header: 401 > + + { Tunnel-Type } + { Tunnel-Medium-Type } + { Tunnel-Client-Endpoint } + { Tunnel-Server-Endpoint } + [ Tunnel-Preference ] + [ Tunnel-Client-Auth-Id ] + [ Tunnel-Server-Auth-Id ] + [ Tunnel-Assignment-Id ] + [ Tunnel-Password ] + [ Tunnel-Private-Group-Id ] + +;; =========================================================================== + +@enum NAS-Port-Type + + ASYNC 0 + SYNC 1 + ISDN_SYNC 2 + ISDN_ASYNC_V120 3 + ISDN_ASYNC_V110 4 + VIRTUAL 5 + PIAFS 6 + HDLC_CLEAR_CHANNEL 7 + X25 8 + X75 9 + G3FAX 10 + SDSL 11 + ADSL-CAP 12 + ADSL-DMT 13 + IDSL 14 + ETHERNET 15 + XDSL 16 + CABLE 17 + WIRELESS_OTHER 18 + 'WIRELESS_802.11' 19 + TOKEN-RING 20 + FDDI 21 + WIRELESS_CDMA2000 22 + WIRELESS_UMTS 23 + WIRELESS_1X-EV 24 + IAPP 25 + +@enum Prompt + + NO_ECHO 0 + ECHO 1 + +@enum CHAP-Algorithm + + WITH_MD5 5 + +@enum Service-Type + + LOGIN 1 + FRAMED 2 + CALLBACK_LOGIN 3 + CALLBACK_FRAMED 4 + OUTBOUND 5 + ADMINISTRATIVE 6 + NAS_PROMPT 7 + AUTHENTICATE_ONLY 8 + CALLBACK_NAS_PROMPT 9 + CALL_CHECK 10 + CALLBACK_ADMINISTRATIVE 11 + VOICE 12 + FAX 13 + MODEM_RELAY 14 + IAPP-REGISTER 15 + IAPP-AP-CHECK 16 + AUTHORIZE_ONLY 17 + +@enum Framed-Protocol + + PPP 1 + SLIP 2 + ARAP 3 + GANDALF 4 + XYLOGICS 5 + X75 6 + +@enum Framed-Routing + + NONE 0 + SEND 1 + LISTEN 2 + SEND_AND_LISTEN 3 + +@enum Framed-Compression + + NONE 0 + VJ 1 + IPX 2 + STAC-LZS 3 + +@enum ARAP-Zone-Access + + DEFAULT 1 + FILTER_INCLUSIVELY 2 + FILTER_EXCLUSIVELY 4 + +@enum Login-Service + + TELNET 0 + RLOGIN 1 + TCP_CLEAR 2 + PORTMASTER 3 + LAT 4 + X25-PAD 5 + X25-T3POS 6 + TCP_CLEAR_QUIET 8 + +@enum Tunnel-Type + + PPTP 1 + L2F 2 + L2TP 3 + ATMP 4 + VTP 5 + AH 6 + IP-IP 7 + MIN-IP-IP 8 + ESP 9 + GRE 10 + DVS 11 + IP-IN-IP 12 + VLAN 13 + +@enum Tunnel-Medium-Type + + IPV4 1 + IPV6 2 + NSAP 3 + HDLC 4 + BBN_1822 5 + '802' 6 + E163 7 + E164 8 + F69 9 + X121 10 + IPX 11 + APPLETALK 12 + DECNET_IV 13 + BANYAN_VINES 14 + E164_NSAP 15 + + +@enum Acct-Authentic + + RADIUS 1 + LOCAL 2 + REMOTE 3 + DIAMETER 4 + +@enum Accounting-Auth-Method + + PAP 1 + CHAP 2 + MS-CHAP-1 3 + MS-CHAP-2 4 + EAP 5 + NONE 7 + +@enum Termination-Cause + + USER_REQUEST 11 + LOST_CARRIER 12 + LOST_SERVICE 13 + IDLE_TIMEOUT 14 + SESSION_TIMEOUT 15 + ADMIN_RESET 16 + ADMIN_REBOOT 17 + PORT_ERROR 18 + NAS_ERROR 19 + NAS_REQUEST 20 + NAS_REBOOT 21 + PORT_UNNEEDED 22 + PORT_PREEMPTED 23 + PORT_SUSPENDED 24 + SERVICE_UNAVAILABLE 25 + CALLBACK 26 + USER_ERROR 27 + HOST_REQUEST 28 + SUPPLICANT_RESTART 29 + REAUTHORIZATION_FAILURE 30 + PORT_REINIT 31 + PORT_DISABLED 32 diff --git a/lib/diameter/examples/dict/rfc4006_cc.dia b/lib/diameter/examples/dict/rfc4006_cc.dia new file mode 100644 index 0000000000..b723e4ddbb --- /dev/null +++ b/lib/diameter/examples/dict/rfc4006_cc.dia @@ -0,0 +1,349 @@ +;; +;; %CopyrightBegin% +;; +;; Copyright Ericsson AB 2010-2011. All Rights Reserved. +;; +;; The contents of this file are subject to the Erlang Public License, +;; Version 1.1, (the "License"); you may not use this file except in +;; compliance with the License. You should have received a copy of the +;; Erlang Public License along with this software. If not, it can be +;; retrieved online at http://www.erlang.org/. +;; +;; Software distributed under the License is distributed on an "AS IS" +;; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +;; the License for the specific language governing rights and limitations +;; under the License. +;; +;; %CopyrightEnd% +;; + +;; +;; RFC 4006, Diameter Credit-Control Application +;; + +@id 4 + +@inherits rfc3588_base +@inherits rfc4005_nas Filter-Id + +;; =========================================================================== + +@avp_types + + CC-Correlation-Id 411 OctetString - + CC-Input-Octets 412 Unsigned64 M + CC-Money 413 Grouped M + CC-Output-Octets 414 Unsigned64 M + CC-Request-Number 415 Unsigned32 M + CC-Request-Type 416 Enumerated M + CC-Service-Specific-Units 417 Unsigned64 M + CC-Session-Failover 418 Enumerated M + CC-Sub-Session-Id 419 Unsigned64 M + CC-Time 420 Unsigned32 M + CC-Total-Octets 421 Unsigned64 M + CC-Unit-Type 454 Enumerated M + Check-Balance-Result 422 Enumerated M + Cost-Information 423 Grouped M + Cost-Unit 424 UTF8String M + Credit-Control 426 Enumerated M + Credit-Control-Failure-Handling 427 Enumerated M + Currency-Code 425 Unsigned32 M + Direct-Debiting-Failure-Handling 428 Enumerated M + Exponent 429 Integer32 M + Final-Unit-Action 449 Enumerated M + Final-Unit-Indication 430 Grouped M + Granted-Service-Unit 431 Grouped M + G-S-U-Pool-Identifier 453 Unsigned32 M + G-S-U-Pool-Reference 457 Grouped M + Multiple-Services-Credit-Control 456 Grouped M + Multiple-Services-Indicator 455 Enumerated M + Rating-Group 432 Unsigned32 M + Redirect-Address-Type 433 Enumerated M + Redirect-Server 434 Grouped M + Redirect-Server-Address 435 UTF8String M + Requested-Action 436 Enumerated M + Requested-Service-Unit 437 Grouped M + Restriction-Filter-Rule 438 IPFilterRule M + Service-Context-Id 461 UTF8String M + Service-Identifier 439 Unsigned32 M + Service-Parameter-Info 440 Grouped - + Service-Parameter-Type 441 Unsigned32 - + Service-Parameter-Value 442 OctetString - + Subscription-Id 443 Grouped M + Subscription-Id-Data 444 UTF8String M + Subscription-Id-Type 450 Enumerated M + Tariff-Change-Usage 452 Enumerated M + Tariff-Time-Change 451 Time M + Unit-Value 445 Grouped M + Used-Service-Unit 446 Grouped M + User-Equipment-Info 458 Grouped - + User-Equipment-Info-Type 459 Enumerated - + User-Equipment-Info-Value 460 OctetString - + Value-Digits 447 Integer64 M + Validity-Time 448 Unsigned32 M + +;; =========================================================================== + +@messages + + CCR ::= < Diameter Header: 272, REQ, PXY > + + < Session-Id > + { Origin-Host } + { Origin-Realm } + { Destination-Realm } + { Auth-Application-Id } + { Service-Context-Id } + { CC-Request-Type } + { CC-Request-Number } + [ Destination-Host ] + [ User-Name ] + [ CC-Sub-Session-Id ] + [ Acct-Multi-Session-Id ] + [ Origin-State-Id ] + [ Event-Timestamp ] + * [ Subscription-Id ] + [ Service-Identifier ] + [ Termination-Cause ] + [ Requested-Service-Unit ] + [ Requested-Action ] + * [ Used-Service-Unit ] + [ Multiple-Services-Indicator ] + * [ Multiple-Services-Credit-Control ] + * [ Service-Parameter-Info ] + [ CC-Correlation-Id ] + [ User-Equipment-Info ] + * [ Proxy-Info ] + * [ Route-Record ] + * [ AVP ] + + CCA ::= < Diameter Header: 272, PXY > + + < Session-Id > + { Result-Code } + { Origin-Host } + { Origin-Realm } + { Auth-Application-Id } + { CC-Request-Type } + { CC-Request-Number } + [ User-Name ] + [ CC-Session-Failover ] + [ CC-Sub-Session-Id ] + [ Acct-Multi-Session-Id ] + [ Origin-State-Id ] + [ Event-Timestamp ] + [ Granted-Service-Unit ] + * [ Multiple-Services-Credit-Control ] + [ Cost-Information] + [ Final-Unit-Indication ] + [ Check-Balance-Result ] + [ Credit-Control-Failure-Handling ] + [ Direct-Debiting-Failure-Handling ] + [ Validity-Time] + * [ Redirect-Host] + [ Redirect-Host-Usage ] + [ Redirect-Max-Cache-Time ] + * [ Proxy-Info ] + * [ Route-Record ] + * [ Failed-AVP ] + * [ AVP ] + +;; =========================================================================== + +@grouped + + Cost-Information ::= < AVP Header: 423 > + + { Unit-Value } + { Currency-Code } + [ Cost-Unit ] + + Unit-Value ::= < AVP Header: 445 > + + { Value-Digits } + [ Exponent ] + + Multiple-Services-Credit-Control ::= < AVP Header: 456 > + + [ Granted-Service-Unit ] + [ Requested-Service-Unit ] + * [ Used-Service-Unit ] + [ Tariff-Change-Usage ] + * [ Service-Identifier ] + [ Rating-Group ] + * [ G-S-U-Pool-Reference ] + [ Validity-Time ] + [ Result-Code ] + [ Final-Unit-Indication ] + * [ AVP ] + + Granted-Service-Unit ::= < AVP Header: 431 > + + [ Tariff-Time-Change ] + [ CC-Time ] + [ CC-Money ] + [ CC-Total-Octets ] + [ CC-Input-Octets ] + [ CC-Output-Octets ] + [ CC-Service-Specific-Units ] + * [ AVP ] + + Requested-Service-Unit ::= < AVP Header: 437 > + + [ CC-Time ] + [ CC-Money ] + [ CC-Total-Octets ] + [ CC-Input-Octets ] + [ CC-Output-Octets ] + [ CC-Service-Specific-Units ] + * [ AVP ] + + Used-Service-Unit ::= < AVP Header: 446 > + + [ Tariff-Change-Usage ] + [ CC-Time ] + [ CC-Money ] + [ CC-Total-Octets ] + [ CC-Input-Octets ] + [ CC-Output-Octets ] + [ CC-Service-Specific-Units ] + * [ AVP ] + + CC-Money ::= < AVP Header: 413 > + + { Unit-Value } + [ Currency-Code ] + + G-S-U-Pool-Reference ::= < AVP Header: 457 > + + { G-S-U-Pool-Identifier } + { CC-Unit-Type } + { Unit-Value } + + Final-Unit-Indication ::= < AVP Header: 430 > + + { Final-Unit-Action } + * [ Restriction-Filter-Rule ] + * [ Filter-Id ] + [ Redirect-Server ] + + Redirect-Server ::= < AVP Header: 434 > + + { Redirect-Address-Type } + { Redirect-Server-Address } + + Service-Parameter-Info ::= < AVP Header: 440 > + + { Service-Parameter-Type } + { Service-Parameter-Value } + + Subscription-Id ::= < AVP Header: 443 > + + { Subscription-Id-Type } + { Subscription-Id-Data } + + User-Equipment-Info ::= < AVP Header: 458 > + + { User-Equipment-Info-Type } + { User-Equipment-Info-Value } + +;; =========================================================================== + +@enum CC-Request-Type + + INITIAL_REQUEST 1 + UPDATE_REQUEST 2 + TERMINATION_REQUEST 3 + EVENT_REQUEST 4 + +@enum CC-Session-Failover + + NOT_SUPPORTED 0 + SUPPORTED 1 + +@enum Check-Balance-Result + + ENOUGH_CREDIT 0 + NO_CREDIT 1 + +@enum Credit-Control + + AUTHORIZATION 0 + RE_AUTHORIZATION 1 + +@enum Credit-Control-Failure-Handling + + TERMINATE 0 + CONTINUE 1 + RETRY_AND_TERMINATE 2 + +@enum Direct-Debiting-Failure-Handling + + TERMINATE_OR_BUFFER 0 + CONTINUE 1 + +@enum Tariff-Change-Usage + + UNIT_BEFORE_TARIFF_CHANGE 0 + UNIT_AFTER_TARIFF_CHANGE 1 + UNIT_INDETERMINATE 2 + +@enum CC-Unit-Type + + TIME 0 + MONEY 1 + TOTAL-OCTETS 2 + INPUT-OCTETS 3 + OUTPUT-OCTETS 4 + SERVICE-SPECIFIC-UNITS 5 + +@enum Final-Unit-Action + + TERMINATE 0 + REDIRECT 1 + RESTRICT_ACCESS 2 + +@enum Redirect-Address-Type + + IPV4 0 + IPV6 1 + URL 2 + SIP_URI 3 + +@enum Multiple-Services-Indicator + + NOT_SUPPORTED 0 + SUPPORTED 1 + +@enum Requested-Action + + DIRECT_DEBITING 0 + REFUND_ACCOUNT 1 + CHECK_BALANCE 2 + PRICE_ENQUIRY 3 + +@enum Subscription-Id-Type + + END_USER_E164 0 + END_USER_IMSI 1 + END_USER_SIP_URI 2 + END_USER_NAI 3 + END_USER_PRIVATE 4 + +@enum User-Equipment-Info-Type + + IMEISV 0 + MAC 1 + EUI64 2 + MODIFIED_EUI64 3 + +;; =========================================================================== + +@define Result-Code + + END_USER_SERVICE_DENIED 4010 + CREDIT_CONTROL_NOT_APPLICABLE 4011 + CREDIT_LIMIT_REACHED 4012 + + USER_UNKNOWN 5030 + RATING_FAILED 5031 diff --git a/lib/diameter/examples/dict/rfc4072_eap.dia b/lib/diameter/examples/dict/rfc4072_eap.dia new file mode 100644 index 0000000000..111516b347 --- /dev/null +++ b/lib/diameter/examples/dict/rfc4072_eap.dia @@ -0,0 +1,150 @@ +;; +;; %CopyrightBegin% +;; +;; Copyright Ericsson AB 2010-2011. All Rights Reserved. +;; +;; The contents of this file are subject to the Erlang Public License, +;; Version 1.1, (the "License"); you may not use this file except in +;; compliance with the License. You should have received a copy of the +;; Erlang Public License along with this software. If not, it can be +;; retrieved online at http://www.erlang.org/. +;; +;; Software distributed under the License is distributed on an "AS IS" +;; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +;; the License for the specific language governing rights and limitations +;; under the License. +;; +;; %CopyrightEnd% +;; + +;; +;; RFC 4072, Diameter Extensible Authentication Protocol (EAP) Application +;; +;; Edits: +;; +;; - Move EAP-Payload to not break fixed/required/optional order +;; - Framed-Appletalk-Link -> Framed-AppleTalk-Link +;; - Framed-Appletalk-Network -> Framed-AppleTalk-Network +;; - Framed-Appletalk-Zone -> Framed-AppleTalk-Zone +;; + +@id 5 + +@inherits rfc3588_base +@inherits rfc4005_nas + +;; =========================================================================== + +@avp_types + + EAP-Master-Session-Key 464 OctetString - + EAP-Key-Name 102 OctetString - + EAP-Payload 462 OctetString - + EAP-Reissued-Payload 463 OctetString - + Accounting-EAP-Auth-Method 465 Unsigned64 - + +;; =========================================================================== + +@messages + + DER ::= < Diameter Header: 268, REQ, PXY > + + < Session-Id > + { Auth-Application-Id } + { Origin-Host } + { Origin-Realm } + { Destination-Realm } + { Auth-Request-Type } + { EAP-Payload } + [ Destination-Host ] + [ NAS-Identifier ] + [ NAS-IP-Address ] + [ NAS-IPv6-Address ] + [ NAS-Port ] + [ NAS-Port-Id ] + [ NAS-Port-Type ] + [ Origin-State-Id ] + [ Port-Limit ] + [ User-Name ] + [ EAP-Key-Name ] + [ Service-Type ] + [ State ] + [ Authorization-Lifetime ] + [ Auth-Grace-Period ] + [ Auth-Session-State ] + [ Callback-Number ] + [ Called-Station-Id ] + [ Calling-Station-Id ] + [ Originating-Line-Info ] + [ Connect-Info ] + * [ Framed-Compression ] + [ Framed-Interface-Id ] + [ Framed-IP-Address ] + * [ Framed-IPv6-Prefix ] + [ Framed-IP-Netmask ] + [ Framed-MTU ] + [ Framed-Protocol ] + * [ Tunneling ] + * [ Proxy-Info ] + * [ Route-Record ] + * [ AVP ] + + DEA ::= < Diameter Header: 268, PXY > + + < Session-Id > + { Auth-Application-Id } + { Auth-Request-Type } + { Result-Code } + { Origin-Host } + { Origin-Realm } + [ User-Name ] + [ EAP-Payload ] + [ EAP-Reissued-Payload ] + [ EAP-Master-Session-Key ] + [ EAP-Key-Name ] + [ Multi-Round-Time-Out ] + [ Accounting-EAP-Auth-Method ] + [ Service-Type ] + * [ Class ] + * [ Configuration-Token ] + [ Acct-Interim-Interval ] + [ Error-Message ] + [ Error-Reporting-Host ] + * [ Failed-AVP ] + [ Idle-Timeout ] + [ Authorization-Lifetime ] + [ Auth-Grace-Period ] + [ Auth-Session-State ] + [ Re-Auth-Request-Type ] + [ Session-Timeout ] + [ State ] + * [ Reply-Message ] + [ Origin-State-Id ] + * [ Filter-Id ] + [ Port-Limit ] + [ Callback-Id ] + [ Callback-Number ] + [ Framed-AppleTalk-Link ] + * [ Framed-AppleTalk-Network ] + [ Framed-AppleTalk-Zone ] + * [ Framed-Compression ] + [ Framed-Interface-Id ] + [ Framed-IP-Address ] + * [ Framed-IPv6-Prefix ] + [ Framed-IPv6-Pool ] + * [ Framed-IPv6-Route ] + [ Framed-IP-Netmask ] + * [ Framed-Route ] + [ Framed-Pool ] + [ Framed-IPX-Network ] + [ Framed-MTU ] + [ Framed-Protocol ] + [ Framed-Routing ] + * [ NAS-Filter-Rule ] + * [ QoS-Filter-Rule ] + * [ Tunneling ] + * [ Redirect-Host ] + [ Redirect-Host-Usage ] + [ Redirect-Max-Cache-Time ] + * [ Proxy-Info ] + * [ AVP ] diff --git a/lib/diameter/examples/dict/rfc4590_digest.dia b/lib/diameter/examples/dict/rfc4590_digest.dia new file mode 100644 index 0000000000..a4ebe0c456 --- /dev/null +++ b/lib/diameter/examples/dict/rfc4590_digest.dia @@ -0,0 +1,45 @@ +;; +;; %CopyrightBegin% +;; +;; Copyright Ericsson AB 2010-2011. All Rights Reserved. +;; +;; The contents of this file are subject to the Erlang Public License, +;; Version 1.1, (the "License"); you may not use this file except in +;; compliance with the License. You should have received a copy of the +;; Erlang Public License along with this software. If not, it can be +;; retrieved online at http://www.erlang.org/. +;; +;; Software distributed under the License is distributed on an "AS IS" +;; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +;; the License for the specific language governing rights and limitations +;; under the License. +;; +;; %CopyrightEnd% +;; + +;; +;; RFC 4590, RADIUS Extension for Digest Authentication +;; + +@avp_types + + Digest-Response 103 OctetString - + Digest-Realm 104 OctetString - + Digest-Nonce 105 OctetString - + Digest-Response-Auth 106 OctetString - + Digest-Nextnonce 107 OctetString - + Digest-Method 108 OctetString - + Digest-URI 109 OctetString - + Digest-Qop 110 OctetString - + Digest-Algorithm 111 OctetString - + Digest-Entity-Body-Hash 112 OctetString - + Digest-CNonce 113 OctetString - + Digest-Nonce-Count 114 OctetString - + Digest-Username 115 OctetString - + Digest-Opaque 116 OctetString - + Digest-Auth-Param 117 OctetString - + Digest-AKA-Auts 118 OctetString - + Digest-Domain 119 OctetString - + Digest-Stale 120 OctetString - + Digest-HA1 121 OctetString - + SIP-AOR 122 OctetString - diff --git a/lib/diameter/examples/dict/rfc4740_sip.dia b/lib/diameter/examples/dict/rfc4740_sip.dia new file mode 100644 index 0000000000..8c21882649 --- /dev/null +++ b/lib/diameter/examples/dict/rfc4740_sip.dia @@ -0,0 +1,446 @@ +;; +;; %CopyrightBegin% +;; +;; Copyright Ericsson AB 2010-2011. All Rights Reserved. +;; +;; The contents of this file are subject to the Erlang Public License, +;; Version 1.1, (the "License"); you may not use this file except in +;; compliance with the License. You should have received a copy of the +;; Erlang Public License along with this software. If not, it can be +;; retrieved online at http://www.erlang.org/. +;; +;; Software distributed under the License is distributed on an "AS IS" +;; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +;; the License for the specific language governing rights and limitations +;; under the License. +;; +;; %CopyrightEnd% +;; + +;; +;; RFC 4740, Diameter Session Initiation Protocol (SIP) Application +;; + +@id 6 + +@inherits rfc3588_base +@inherits rfc4590_digest + +;; =========================================================================== + +@avp_types + + SIP-Accounting-Information 368 Grouped M + SIP-Accounting-Server-URI 369 DiameterURI M + SIP-Credit-Control-Server-URI 370 DiameterURI M + SIP-Server-URI 371 UTF8String M + SIP-Server-Capabilities 372 Grouped M + SIP-Mandatory-Capability 373 Unsigned32 M + SIP-Optional-Capability 374 Unsigned32 M + SIP-Server-Assignment-Type 375 Enumerated M + SIP-Auth-Data-Item 376 Grouped M + SIP-Authentication-Scheme 377 Enumerated M + SIP-Item-Number 378 Unsigned32 M + SIP-Authenticate 379 Grouped M + SIP-Authorization 380 Grouped M + SIP-Authentication-Info 381 Grouped M + SIP-Number-Auth-Items 382 Unsigned32 M + SIP-Deregistration-Reason 383 Grouped M + SIP-Reason-Code 384 Enumerated M + SIP-Reason-Info 385 UTF8String M + SIP-Visited-Network-Id 386 UTF8String M + SIP-User-Authorization-Type 387 Enumerated M + SIP-Supported-User-Data-Type 388 UTF8String M + SIP-User-Data 389 Grouped M + SIP-User-Data-Type 390 UTF8String M + SIP-User-Data-Contents 391 OctetString M + SIP-User-Data-Already-Available 392 Enumerated M + SIP-Method 393 UTF8String M + +;; =========================================================================== + +@messages + + ;; 8.1. User-Authorization-Request + + UAR ::= < Diameter Header: 283, REQ, PXY > + + < Session-Id > + { Auth-Application-Id } + { Auth-Session-State } + { Origin-Host } + { Origin-Realm } + { Destination-Realm } + { SIP-AOR } + [ Destination-Host ] + [ User-Name ] + [ SIP-Visited-Network-Id ] + [ SIP-User-Authorization-Type ] + * [ Proxy-Info ] + * [ Route-Record ] + * [ AVP ] + + ;; 8.2. User-Authorization-Answer + + UAA ::= < Diameter Header: 283, PXY > + + < Session-Id > + { Auth-Application-Id } + { Auth-Session-State } + { Result-Code } + { Origin-Host } + { Origin-Realm } + [ SIP-Server-URI ] + [ SIP-Server-Capabilities ] + [ Authorization-Lifetime ] + [ Auth-Grace-Period ] + [ Redirect-Host ] + [ Redirect-Host-Usage ] + [ Redirect-Max-Cache-Time ] + * [ Proxy-Info ] + * [ Route-Record ] + * [ AVP ] + + ;; 8.3. Server-Assignment-Request + + SAR ::= < Diameter Header: 284, REQ, PXY > + + < Session-Id > + { Auth-Application-Id } + { Auth-Session-State } + { Origin-Host } + { Origin-Realm } + { Destination-Realm } + { SIP-Server-Assignment-Type } + { SIP-User-Data-Already-Available } + [ Destination-Host ] + [ User-Name ] + [ SIP-Server-URI ] + * [ SIP-Supported-User-Data-Type ] + * [ SIP-AOR ] + * [ Proxy-Info ] + * [ Route-Record ] + * [ AVP ] + + ;; 8.4. Server-Assignment-Answer + + SAA ::= < Diameter Header: 284, PXY > + + < Session-Id > + { Auth-Application-Id } + { Result-Code } + { Auth-Session-State } + { Origin-Host } + { Origin-Realm } + * [ SIP-User-Data ] + [ SIP-Accounting-Information ] + * [ SIP-Supported-User-Data-Type ] + [ User-Name ] + [ Auth-Grace-Period ] + [ Authorization-Lifetime ] + [ Redirect-Host ] + [ Redirect-Host-Usage ] + [ Redirect-Max-Cache-Time ] + * [ Proxy-Info ] + * [ Route-Record ] + * [ AVP ] + + ;; 8.5. Location-Info-Request + + LIR ::= < Diameter Header: 285, REQ, PXY > + + < Session-Id > + { Auth-Application-Id } + { Auth-Session-State } + { Origin-Host } + { Origin-Realm } + { Destination-Realm } + { SIP-AOR } + [ Destination-Host ] + * [ Proxy-Info ] + * [ Route-Record ] + * [ AVP ] + + ;; 8.6. Location-Info-Answer + + LIA ::= < Diameter Header: 285, PXY > + + < Session-Id > + { Auth-Application-Id } + { Result-Code } + { Auth-Session-State } + { Origin-Host } + { Origin-Realm } + [ SIP-Server-URI ] + [ SIP-Server-Capabilities ] + [ Auth-Grace-Period ] + [ Authorization-Lifetime ] + [ Redirect-Host ] + [ Redirect-Host-Usage ] + [ Redirect-Max-Cache-Time ] + * [ Proxy-Info ] + * [ Route-Record ] + * [ AVP ] + + ;; 8.7. Multimedia-Auth-Request + + MAR ::= < Diameter Header: 286, REQ, PXY > + + < Session-Id > + { Auth-Application-Id } + { Auth-Session-State } + { Origin-Host } + { Origin-Realm } + { Destination-Realm } + { SIP-AOR } + { SIP-Method } + [ Destination-Host ] + [ User-Name ] + [ SIP-Server-URI ] + [ SIP-Number-Auth-Items ] + [ SIP-Auth-Data-Item ] + * [ Proxy-Info ] + * [ Route-Record ] + * [ AVP ] + + ;; 8.8. Multimedia-Auth-Answer + + MAA ::= < Diameter Header: 286, PXY > + + < Session-Id > + { Auth-Application-Id } + { Result-Code } + { Auth-Session-State } + { Origin-Host } + { Origin-Realm } + [ User-Name ] + [ SIP-AOR ] + [ SIP-Number-Auth-Items ] + * [ SIP-Auth-Data-Item ] + [ Authorization-Lifetime ] + [ Auth-Grace-Period ] + [ Redirect-Host ] + [ Redirect-Host-Usage ] + [ Redirect-Max-Cache-Time ] + * [ Proxy-Info ] + * [ Route-Record ] + * [ AVP ] + + ;; 8.9. Registration-Termination-Request + + RTR ::= < Diameter Header: 287, REQ, PXY > + + < Session-Id > + { Auth-Application-Id } + { Auth-Session-State } + { Origin-Host } + { Origin-Realm } + { Destination-Host } + { SIP-Deregistration-Reason } + [ Destination-Realm ] + [ User-Name ] + * [ SIP-AOR ] + * [ Proxy-Info ] + * [ Route-Record ] + * [ AVP ] + + ;; 8.10. Registration-Termination-Answer + + RTA ::= < Diameter Header: 287, PXY > + + < Session-Id > + { Auth-Application-Id } + { Result-Code } + { Auth-Session-State } + { Origin-Host } + { Origin-Realm } + [ Authorization-Lifetime ] + [ Auth-Grace-Period ] + [ Redirect-Host ] + [ Redirect-Host-Usage ] + [ Redirect-Max-Cache-Time ] + * [ Proxy-Info ] + * [ Route-Record ] + * [ AVP ] + + ;; 8.11. Push-Profile-Request + + PPR ::= < Diameter Header: 288, REQ, PXY > + + < Session-Id > + { Auth-Application-Id } + { Auth-Session-State } + { Origin-Host } + { Origin-Realm } + { Destination-Realm } + { User-Name } + * [ SIP-User-Data ] + [ SIP-Accounting-Information ] + [ Destination-Host ] + [ Authorization-Lifetime ] + [ Auth-Grace-Period ] + * [ Proxy-Info ] + * [ Route-Record ] + * [ AVP ] + + ;; 8.12. Push-Profile-Answer + + PPA ::= < Diameter Header: 288, PXY > + + < Session-Id > + { Auth-Application-Id } + { Result-Code } + { Auth-Session-State } + { Origin-Host } + { Origin-Realm } + [ Redirect-Host ] + [ Redirect-Host-Usage ] + [ Redirect-Max-Cache-Time ] + * [ Proxy-Info ] + * [ Route-Record ] + * [ AVP ] + +;; =========================================================================== + +@grouped + + SIP-Accounting-Information ::= < AVP Header: 368 > + + * [ SIP-Accounting-Server-URI ] + * [ SIP-Credit-Control-Server-URI ] + * [ AVP] + + SIP-Server-Capabilities ::= < AVP Header: 372 > + + * [ SIP-Mandatory-Capability ] + * [ SIP-Optional-Capability ] + * [ SIP-Server-URI ] + * [ AVP ] + + SIP-Auth-Data-Item ::= < AVP Header: 376 > + + { SIP-Authentication-Scheme } + [ SIP-Item-Number ] + [ SIP-Authenticate ] + [ SIP-Authorization ] + [ SIP-Authentication-Info ] + * [ AVP ] + + SIP-Authenticate ::= < AVP Header: 379 > + + { Digest-Realm } + { Digest-Nonce } + [ Digest-Domain ] + [ Digest-Opaque ] + [ Digest-Stale ] + [ Digest-Algorithm ] + [ Digest-Qop ] + [ Digest-HA1] + * [ Digest-Auth-Param ] + * [ AVP ] + + SIP-Authorization ::= < AVP Header: 380 > + + { Digest-Username } + { Digest-Realm } + { Digest-Nonce } + { Digest-URI } + { Digest-Response } + [ Digest-Algorithm ] + [ Digest-CNonce ] + [ Digest-Opaque ] + [ Digest-Qop ] + [ Digest-Nonce-Count ] + [ Digest-Method] + [ Digest-Entity-Body-Hash ] + * [ Digest-Auth-Param ] + * [ AVP ] + + SIP-Authentication-Info ::= < AVP Header: 381 > + + [ Digest-Nextnonce ] + [ Digest-Qop ] + [ Digest-Response-Auth ] + [ Digest-CNonce ] + [ Digest-Nonce-Count ] + * [ AVP ] + + SIP-Deregistration-Reason ::= < AVP Header: 383 > + + { SIP-Reason-Code } + [ SIP-Reason-Info ] + * [ AVP ] + + SIP-User-Data ::= < AVP Header: 389 > + + { SIP-User-Data-Type } + { SIP-User-Data-Contents } + * [ AVP ] + +;; =========================================================================== + +@enum SIP-Server-Assignment-Type + + NO_ASSIGNMENT 0 + REGISTRATION 1 + RE_REGISTRATION 2 + UNREGISTERED_USER 3 + TIMEOUT_DEREGISTRATION 4 + USER_DEREGISTRATION 5 + TIMEOUT_DEREGISTRATION_STORE 6 + USER_DEREGISTRATION_STORE 7 + ADMINISTRATIVE_DEREGISTRATION 8 + AUTHENTICATION_FAILURE 9 + AUTHENTICATION_TIMEOUT 10 + DEREGISTRATION_TOO_MUCH_DATA 11 + +@enum SIP-Authentication-Scheme + + DIGEST 0 + +@enum SIP-Reason-Code + + PERMANENT_TERMINATION 0 + NEW_SIP_SERVER_ASSIGNED 1 + SIP_SERVER_CHANGE 2 + REMOVE_SIP_SERVER 3 + +@enum SIP-User-Authorization-Type + + REGISTRATION 0 + DEREGISTRATION 1 + REGISTRATION_AND_CAPABILITIES 2 + +@enum SIP-User-Data-Already-Available + + USER_DATA_NOT_AVAILABLE 0 + USER_DATA_ALREADY_AVAILABLE 1 + +;; =========================================================================== + +@define Result-Code + + ;; Success + + FIRST_REGISTRATION 2003 + SUBSEQUENT_REGISTRATION 2004 + UNREGISTERED_SERVICE 2005 + SUCCESS_SERVER_NAME_NOT_STORED 2006 + SERVER_SELECTION 2007 + SUCCESS_AUTH_SENT_SERVER_NOT_STORED 2008 + + ;; Transient Failures + + USER_NAME_REQUIRED 4013 + + ;; Permanent Failures + + USER_UNKNOWN 5032 + IDENTITIES_DONT_MATCH 5033 + IDENTITY_NOT_REGISTERED 5034 + ROAMING_NOT_ALLOWED 5035 + IDENTITY_ALREADY_REGISTERED 5036 + AUTH_SCHEME_NOT_SUPPORTED 5037 + IN_ASSIGNMENT_TYPE 5038 + TOO_MUCH_DATA 5039 + NOT_SUPPORTED_USER_DATA 5040 diff --git a/lib/diameter/src/Makefile b/lib/diameter/src/Makefile index 2ec016ecbc..dbfaa4e140 100644 --- a/lib/diameter/src/Makefile +++ b/lib/diameter/src/Makefile @@ -88,6 +88,9 @@ TARGET_FILES = \ # Subdirectories of src to release modules into. TARGET_DIRS = $(sort $(dir $(TARGET_MODULES))) +# Ditto for examples. +EXAMPLE_DIRS = $(sort $(dir $(EXAMPLES))) + APP_FILE = diameter.app APP_SRC = $(APP_FILE).src APP_TARGET = $(EBIN)/$(APP_FILE) @@ -169,6 +172,8 @@ info: @echo @$(call list,EXAMPLES) @echo + @$(call list,EXAMPLE_DIRS) + @echo @$(call list,BINS) @echo ======================================== @@ -189,23 +194,29 @@ endif # Can't $(INSTALL_DIR) more than one directory at a time on Solaris. release_spec: opt - for d in bin ebin examples include src/dict $(TARGET_DIRS:%/=src/%); do \ + for d in bin ebin include src/dict; do \ $(INSTALL_DIR) $(RELSYSDIR)/$$d; \ done $(INSTALL_SCRIPT) $(BINS:%=../bin/%) $(RELSYSDIR)/bin $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin - $(INSTALL_DATA) $(EXAMPLES:%=../examples/%) $(RELSYSDIR)/examples $(INSTALL_DATA) $(EXTERNAL_HRLS:%=../include/%) $(DICT_HRLS) \ $(RELSYSDIR)/include $(INSTALL_DATA) $(DICTS:%=dict/%.dia) $(RELSYSDIR)/src/dict $(MAKE) $(TARGET_DIRS:%/=release_src_%) + $(MAKE) $(EXAMPLE_DIRS:%/=release_examples_%) $(TARGET_DIRS:%/=release_src_%): release_src_%: + $(INSTALL_DIR) $(RELSYSDIR)/src/$* $(INSTALL_DATA) $(filter $*/%, $(TARGET_MODULES:%=%.erl) \ $(INTERNAL_HRLS)) \ $(filter $*/%, compiler/$(DICT_YRL).yrl) \ $(RELSYSDIR)/src/$* +$(EXAMPLE_DIRS:%/=release_examples_%): release_examples_%: + $(INSTALL_DIR) $(RELSYSDIR)/examples/$* + $(INSTALL_DATA) $(patsubst %, ../examples/%, $(filter $*/%, $(EXAMPLES))) \ + $(RELSYSDIR)/examples/$* + release_docs_spec: # ---------------------------------------------------- @@ -237,6 +248,7 @@ depend.mk: depend.sed $(MODULES:%=%.erl) Makefile .PHONY: app clean depend dict info release_subdir .PHONY: debug opt release_docs_spec release_spec .PHONY: $(TARGET_DIRS:%/=%) $(TARGET_DIRS:%/=release_src_%) +.PHONY: $(EXAMPLE_DIRS:%/=release_examples_%) # Keep intermediate files. .SECONDARY: $(DICT_ERLS) $(DICT_HRLS) gen/$(DICT_YRL:%=%.erl) diff --git a/lib/diameter/src/base/diameter_service.erl b/lib/diameter/src/base/diameter_service.erl index 0893956f97..3dfdcee2b2 100644 --- a/lib/diameter/src/base/diameter_service.erl +++ b/lib/diameter/src/base/diameter_service.erl @@ -629,10 +629,6 @@ insert(Tbl, Rec) -> ets:insert(Tbl, Rec), Rec. -monitor(Pid) -> - erlang:monitor(process, Pid), - Pid. - %% Using the process dictionary for the callback state was initially %% just a way to make what was horrendous trace (big state record and %% much else everywhere) somewhat more readable. There's not as much @@ -814,10 +810,10 @@ start(Ref, Type, Opts, #state{peerT = PeerT, service = Svc}) when Type == connect; Type == accept -> - Pid = monitor(s(Type, Ref, {ConnT, - Opts, - SvcName, - merge_service(Opts, Svc)})), + Pid = s(Type, Ref, {ConnT, + Opts, + SvcName, + merge_service(Opts, Svc)}), insert(PeerT, #peer{pid = Pid, type = Type, ref = Ref, @@ -830,7 +826,13 @@ start(Ref, Type, Opts, #state{peerT = PeerT, %% callbacks. s(Type, Ref, T) -> - diameter_watchdog:start({Type, Ref}, T). + case diameter_watchdog:start({Type, Ref}, T) of + {_MRef, Pid} -> + Pid; + Pid when is_pid(Pid) -> %% from old code + erlang:monitor(process, Pid), + Pid + end. %% merge_service/2 diff --git a/lib/diameter/src/base/diameter_watchdog.erl b/lib/diameter/src/base/diameter_watchdog.erl index 6dc53d9f31..fb22fd8275 100644 --- a/lib/diameter/src/base/diameter_watchdog.erl +++ b/lib/diameter/src/base/diameter_watchdog.erl @@ -59,10 +59,19 @@ message_data}). %% term passed into diameter_service with message %% start/2 +%% +%% Start a monitor before the watchdog is allowed to proceed to ensure +%% that a failed capabilities exchange produces the desired exit +%% reason. start({_,_} = Type, T) -> - {ok, Pid} = diameter_watchdog_sup:start_child({Type, self(), T}), - Pid. + Ref = make_ref(), + {ok, Pid} = diameter_watchdog_sup:start_child({Ref, {Type, self(), T}}), + try + {erlang:monitor(process, Pid), Pid} + after + Pid ! Ref + end. start_link(T) -> {ok, _} = proc_lib:start_link(?MODULE, @@ -80,14 +89,29 @@ init(T) -> proc_lib:init_ack({ok, self()}), gen_server:enter_loop(?MODULE, [], i(T)). -i({T, Pid, {ConnT, Opts, SvcName, #diameter_service{applications = Apps, - capabilities = Caps} - = Svc}}) -> - {M,S,U} = now(), - random:seed(M,S,U), +i({Ref, {_, Pid, _} = T}) -> + MRef = erlang:monitor(process, Pid), + receive + Ref -> + make_state(T); + {'DOWN', MRef, process, _, _} = D -> + exit({shutdown, D}) + end; + +i({_, Pid, _} = T) -> %% from old code + erlang:monitor(process, Pid), + make_state(T). + +make_state({T, Pid, {ConnT, + Opts, + SvcName, + #diameter_service{applications = Apps, + capabilities = Caps} + = Svc}}) -> + random:seed(now()), putr(restart, {T, Opts, Svc}), %% save seeing it in trace putr(dwr, dwr(Caps)), %% - #watchdog{parent = monitor(Pid), + #watchdog{parent = Pid, transport = monitor(diameter_peer_fsm:start(T, Opts, Svc)), tw = proplists:get_value(watchdog_timer, Opts, diff --git a/lib/diameter/src/compiler/diameter_dict_util.erl b/lib/diameter/src/compiler/diameter_dict_util.erl index e4cd29ab7f..36a6efa294 100644 --- a/lib/diameter/src/compiler/diameter_dict_util.erl +++ b/lib/diameter/src/compiler/diameter_dict_util.erl @@ -630,13 +630,28 @@ reset(K, Dict, Opts) -> opt({inherits = Key, "-"}, Dict) -> dict:erase(Key, Dict); + opt({inherits = Key, Mod}, Dict) -> - dict:append(Key, [0, {word, 0, Mod}], Dict); + case lists:splitwith(fun(C) -> C /= $/ end, Mod) of + {Mod, ""} -> + dict:append(Key, [0, {word, 0, Mod}], Dict); + {From, [$/|To]} -> + dict:store(Key, + [reinherit(From, To, M) || M <- find(Key, Dict)], + Dict) + end; + opt({Key, Val}, Dict) -> - dict:store(Key, [0, {word, 0, Val}], Dict); + dict:store(Key, [[0, {word, 0, Val}]], Dict); + opt(_, Dict) -> Dict. +reinherit(From, To, [L, {word, _, From} = T | Avps]) -> + [L, setelement(3, T, To) | Avps]; +reinherit(_, _, T) -> + T. + %% =========================================================================== %% pass1/1 %% diff --git a/lib/diameter/src/modules.mk b/lib/diameter/src/modules.mk index 11d354e57e..7a700a6d53 100644 --- a/lib/diameter/src/modules.mk +++ b/lib/diameter/src/modules.mk @@ -88,11 +88,17 @@ BINS = \ # Released files relative to ../examples. EXAMPLES = \ - GNUmakefile \ - peer.erl \ - client.erl \ - client_cb.erl \ - server.erl \ - server_cb.erl \ - relay.erl \ - relay_cb.erl + code/GNUmakefile \ + code/peer.erl \ + code/client.erl \ + code/client_cb.erl \ + code/server.erl \ + code/server_cb.erl \ + code/relay.erl \ + code/relay_cb.erl \ + dict/rfc4004_mip.dia \ + dict/rfc4005_nas.dia \ + dict/rfc4006_cc.dia \ + dict/rfc4072_eap.dia \ + dict/rfc4590_digest.dia \ + dict/rfc4740_sip.dia diff --git a/lib/diameter/test/Makefile b/lib/diameter/test/Makefile index 97d9069f4a..ab5b45ff3d 100644 --- a/lib/diameter/test/Makefile +++ b/lib/diameter/test/Makefile @@ -50,6 +50,8 @@ TARGET_FILES = $(MODULES:%=%.$(EMULATOR)) SUITE_MODULES = $(filter diameter_%_SUITE, $(MODULES)) SUITES = $(SUITE_MODULES:diameter_%_SUITE=%) +DATA_DIRS = $(sort $(dir $(DATA))) + # ---------------------------------------------------- # FLAGS # ---------------------------------------------------- @@ -121,12 +123,12 @@ help: # diameter_ct:run/1 itself can't tell (it seems). The absolute -pa is # because ct will change directories. $(SUITES): log opt - $(ERL) -noshell \ + $(ERL) -noinput \ -pa $(realpath ../ebin) \ -sname diameter_test_$@ \ -s diameter_ct run diameter_$@_SUITE \ -s init stop \ - | awk '1{rc=0} {print} / FAILED /{rc=1} END{exit rc}' + | awk '{print} / FAILED /{rc=1} END{exit rc}' rc=0 # Shorter in sed but requires a GNU extension (ie. Q). log: @@ -147,9 +149,7 @@ else include $(ERL_TOP)/make/otp_release_targets.mk endif -release_spec: - -release_docs_spec: +release_spec release_docs_spec: release_tests_spec: $(INSTALL_DIR) $(RELSYSDIR) @@ -157,12 +157,18 @@ release_tests_spec: $(COVER_SPEC_FILE) \ $(HRL_FILES) \ $(RELSYSDIR) + $(MAKE) $(DATA_DIRS:%/=release_data_%) $(MAKE) $(ERL_FILES:%=/%) +$(DATA_DIRS:%/=release_data_%): release_data_%: + $(INSTALL_DIR) $(RELSYSDIR)/$* + $(INSTALL_DATA) $(filter $*/%, $(DATA)) $(RELSYSDIR)/$* + force: .PHONY: release_spec release_docs_spec release_test_specs .PHONY: force +.PHONY: $(DATA_DIRS:%/=release_data_%) # Can't just make $(ERL_FILES:%=/%) phony since then implicit rule # searching is skipped. diff --git a/lib/diameter/test/diameter_capx_SUITE.erl b/lib/diameter/test/diameter_capx_SUITE.erl index e6b1558bf6..54a161d606 100644 --- a/lib/diameter/test/diameter_capx_SUITE.erl +++ b/lib/diameter/test/diameter_capx_SUITE.erl @@ -27,8 +27,6 @@ -export([suite/0, all/0, groups/0, - init_per_group/2, - end_per_group/2, init_per_testcase/2, end_per_testcase/2]). @@ -93,30 +91,26 @@ -define(cea, #diameter_base_CEA). -define(answer_message, #'diameter_base_answer-message'). +-define(fail(T), erlang:error({T, process_info(self(), messages)})). + +-define(TIMEOUT, 2000). + %% =========================================================================== suite() -> [{timetrap, {seconds, 10}}]. -all() -> - [start, start_services, add_listeners - | [{group, N} || {N, _, _} <- groups()]] - ++ [remove_listeners, stop_services, stop]. +all() -> [start, + start_services, + add_listeners, + {group, all}, + {group, all, [parallel]}, + remove_listeners, + stop_services, + stop]. groups() -> - Ts = testcases(), - [{grp(P), P, Ts} || P <- [[], [parallel]]]. - -grp([]) -> - sequential; -grp([parallel = P]) -> - P. - -init_per_group(_Name, Config) -> - Config. - -end_per_group(_, _) -> - ok. + [{all, [], lists:flatmap(fun tc/1, tc())}]. %% Generate a unique hostname for each testcase so that watchdogs %% don't prevent a connection from being brought up immediately. @@ -137,9 +131,6 @@ end_per_testcase(Name, Config) -> ok = diameter:remove_transport(?CLIENT, CRef). %% Testcases all come in two flavours, client and server. -testcases() -> - lists:flatmap(fun tc/1, tc()). - tc(Name) -> [?A([C,$_|?L(Name)]) || C <- "cs"]. @@ -270,8 +261,8 @@ s_client_reject(Config) -> ?packet{}}} = Info -> Info - after 2000 -> - fail({LRef, OH}) + after ?TIMEOUT -> + ?fail({LRef, OH}) end. c_client_reject(Config) -> @@ -307,12 +298,12 @@ server_closed(Config, F, RC) -> = Reason, {listen, _}}} -> Reason - after 2000 -> - fail({LRef, OH}) + after ?TIMEOUT -> + ?fail({LRef, OH}) end. %% server_reject/3 - + server_reject(Config, F, RC) -> true = diameter:subscribe(?SERVER), OH = host(Config), @@ -328,8 +319,8 @@ server_reject(Config, F, RC) -> = Reason, {listen, _}}} -> Reason - after 2000 -> - fail({LRef, OH}) + after ?TIMEOUT -> + ?fail({LRef, OH}) end. %% cliient_closed/4 @@ -345,13 +336,13 @@ client_closed(Config, Host, F, RC) -> %% client_recv/1 -client_recv(CRef) -> +client_recv(CRef) -> receive ?event{service = ?CLIENT, info = {closed, CRef, Reason, {connect, _}}} -> Reason - after 2000 -> - fail(CRef) + after ?TIMEOUT -> + ?fail(CRef) end. %% server_capx/3 @@ -373,9 +364,6 @@ client_capx(_, ?caps{origin_host = {[_,$_|"client_reject." ++ _], _}}) -> %% =========================================================================== -fail(T) -> - erlang:error({T, process_info(self(), messages)}). - host(Config) -> {_, H} = lists:keyfind(host, 1, Config), ?HOST(H). diff --git a/lib/diameter/test/diameter_codec_SUITE.erl b/lib/diameter/test/diameter_codec_SUITE.erl index 30c60be8e9..2e219bbb10 100644 --- a/lib/diameter/test/diameter_codec_SUITE.erl +++ b/lib/diameter/test/diameter_codec_SUITE.erl @@ -35,7 +35,8 @@ %% testcases -export([base/1, gen/1, - lib/1]). + lib/1, + unknown/1]). -include("diameter_ct.hrl"). @@ -47,7 +48,7 @@ suite() -> [{timetrap, {seconds, 10}}]. all() -> - [base, gen, lib]. + [base, gen, lib, unknown]. init_per_testcase(gen, Config) -> [{application, ?APP, App}] = diameter_util:consult(?APP, app), @@ -74,3 +75,26 @@ gen([{dicts, Ms} | _]) -> lib(_Config) -> diameter_codec_test:lib(). + +%% Have a separate AVP dictionary just to exercise more code. +unknown(Config) -> + Priv = proplists:get_value(priv_dir, Config), + Data = proplists:get_value(data_dir, Config), + ok = make(Data, "recv.dia"), + ok = make(Data, "avps.dia"), + {ok, _, _} = compile("diameter_test_avps.erl"), + ok = make(Data, "send.dia"), + {ok, _, _} = compile("diameter_test_send.erl"), + {ok, _, _} = compile("diameter_test_recv.erl"), + {ok, _, _} = compile(filename:join([Data, "diameter_test_unknown.erl"]), + [{i, Priv}]), + diameter_test_unknown:run(). + +make(Dir, File) -> + diameter_make:codec(filename:join([Dir, File])). + +compile(File) -> + compile(File, []). + +compile(File, Opts) -> + compile:file(File, [return | Opts]). diff --git a/lib/diameter/test/diameter_codec_SUITE_data/avps.dia b/lib/diameter/test/diameter_codec_SUITE_data/avps.dia new file mode 100644 index 0000000000..c9d80a37a9 --- /dev/null +++ b/lib/diameter/test/diameter_codec_SUITE_data/avps.dia @@ -0,0 +1,25 @@ +;; +;; %CopyrightBegin% +;; +;; Copyright Ericsson AB 2010-2011. All Rights Reserved. +;; +;; The contents of this file are subject to the Erlang Public License, +;; Version 1.1, (the "License"); you may not use this file except in +;; compliance with the License. You should have received a copy of the +;; Erlang Public License along with this software. If not, it can be +;; retrieved online at http://www.erlang.org/. +;; +;; Software distributed under the License is distributed on an "AS IS" +;; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +;; the License for the specific language governing rights and limitations +;; under the License. +;; +;; %CopyrightEnd% +;; + +@name diameter_test_avps + +@avp_types + + XXX 111 Unsigned32 M + YYY 222 Unsigned32 - 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 new file mode 100644 index 0000000000..bce3d78a37 --- /dev/null +++ b/lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl @@ -0,0 +1,76 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010-2011. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(diameter_test_unknown). + +-compile(export_all). + +%% +%% Test reception of unknown AVP's. +%% + +-include_lib("diameter/include/diameter.hrl"). +-include("diameter_test_send.hrl"). +-include("diameter_test_recv.hrl"). + +-define(HOST, "test.erlang.org"). +-define(REALM, "erlang.org"). + +%% Patterns to match decoded AVP's. +-define(MANDATORY_XXX, #diameter_avp{code = 111}). +-define(NOT_MANDATORY_YYY, #diameter_avp{code = 222}). + +%% Ensure that an unknown AVP with an M flag is regarded as an error +%% while one without an M flag is returned as 'AVP'. + +run() -> + H = #diameter_header{version = 1, + end_to_end_id = 1, + hop_by_hop_id = 1}, + Vs = [{'Origin-Host', ?HOST}, + {'Origin-Realm', ?REALM}, + {'XXX', [0]}, + {'YYY', [1]}], + Pkt = #diameter_packet{header = H, + msg = Vs}, + + [] = diameter_util:run([{?MODULE, [run, M, enc(M, Pkt)]} + || M <- ['AR','BR']]). + +enc(M, #diameter_packet{msg = Vs} = P) -> + diameter_codec:encode(diameter_test_send, + P#diameter_packet{msg = [M|Vs]}). + +run(M, Pkt) -> + dec(M, diameter_codec:decode(diameter_test_recv, Pkt)). +%% Note that the recv dictionary defines neither XXX nor YYY. + +dec('AR', #diameter_packet + {msg = #recv_AR{'Origin-Host' = ?HOST, + 'Origin-Realm' = ?REALM, + 'AVP' = [?NOT_MANDATORY_YYY]}, + errors = [{5001, ?MANDATORY_XXX}]}) -> + ok; + +dec('BR', #diameter_packet + {msg = #recv_BR{'Origin-Host' = ?HOST, + 'Origin-Realm' = ?REALM}, + errors = [{5008, ?NOT_MANDATORY_YYY}, + {5001, ?MANDATORY_XXX}]}) -> + ok. diff --git a/lib/diameter/test/diameter_codec_SUITE_data/recv.dia b/lib/diameter/test/diameter_codec_SUITE_data/recv.dia new file mode 100644 index 0000000000..15fec5a5dd --- /dev/null +++ b/lib/diameter/test/diameter_codec_SUITE_data/recv.dia @@ -0,0 +1,51 @@ +;; +;; %CopyrightBegin% +;; +;; Copyright Ericsson AB 2010-2011. All Rights Reserved. +;; +;; The contents of this file are subject to the Erlang Public License, +;; Version 1.1, (the "License"); you may not use this file except in +;; compliance with the License. You should have received a copy of the +;; Erlang Public License along with this software. If not, it can be +;; retrieved online at http://www.erlang.org/. +;; +;; Software distributed under the License is distributed on an "AS IS" +;; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +;; the License for the specific language governing rights and limitations +;; under the License. +;; +;; %CopyrightEnd% +;; + +@id 17 +@name diameter_test_recv +@prefix recv + +@inherits diameter_gen_base_rfc3588 + + Origin-Host + Origin-Realm + Result-Code + +@messages + + AR ::= < Diameter Header: 123, REQ > + { Origin-Host } + { Origin-Realm } + * [ AVP ] + + AA ::= < Diameter Header: 123 > + { Result-Code } + { Origin-Host } + { Origin-Realm } + * [ AVP ] + + BR ::= < Diameter Header: 124, REQ > + { Origin-Host } + { Origin-Realm } + + BA ::= < Diameter Header: 124 > + { Result-Code } + { Origin-Host } + { Origin-Realm } + * [ AVP ] diff --git a/lib/diameter/test/diameter_codec_SUITE_data/send.dia b/lib/diameter/test/diameter_codec_SUITE_data/send.dia new file mode 100644 index 0000000000..1472f146ae --- /dev/null +++ b/lib/diameter/test/diameter_codec_SUITE_data/send.dia @@ -0,0 +1,56 @@ +;; +;; %CopyrightBegin% +;; +;; Copyright Ericsson AB 2010-2011. All Rights Reserved. +;; +;; The contents of this file are subject to the Erlang Public License, +;; Version 1.1, (the "License"); you may not use this file except in +;; compliance with the License. You should have received a copy of the +;; Erlang Public License along with this software. If not, it can be +;; retrieved online at http://www.erlang.org/. +;; +;; Software distributed under the License is distributed on an "AS IS" +;; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +;; the License for the specific language governing rights and limitations +;; under the License. +;; +;; %CopyrightEnd% +;; + +@id 17 +@name diameter_test_send +@prefix send + +@inherits diameter_gen_base_rfc3588 + + Origin-Host + Origin-Realm + Result-Code + +@inherits diameter_test_avps + +@messages + + AR ::= < Diameter Header: 123, REQ > + { Origin-Host } + { Origin-Realm } + [ XXX ] + [ YYY ] + + AA ::= < Diameter Header: 123 > + { Result-Code } + { Origin-Host } + { Origin-Realm } + * [ AVP ] + + BR ::= < Diameter Header: 124, REQ > + { Origin-Host } + { Origin-Realm } + [ XXX ] + [ YYY ] + + BA ::= < Diameter Header: 124 > + { Result-Code } + { Origin-Host } + { Origin-Realm } + * [ AVP ] diff --git a/lib/diameter/test/diameter_compiler_SUITE.erl b/lib/diameter/test/diameter_compiler_SUITE.erl index 66d788f6ec..3b4c9706e0 100644 --- a/lib/diameter/test/diameter_compiler_SUITE.erl +++ b/lib/diameter/test/diameter_compiler_SUITE.erl @@ -29,9 +29,10 @@ end_per_suite/1]). %% testcases --export([format/1, format/2, - replace/1, replace/2, - generate/1, generate/4, generate/0]). +-export([format/1, format/2, + replace/1, replace/2, + generate/1, generate/4, generate/0, + examples/1, examples/0]). -export([dict/0]). %% fake dictionary module @@ -327,6 +328,14 @@ "@codecs mymod " "Origin-Host Origin-Realm\n&"}]}]). +%% Standard dictionaries in examples/dict. +-define(EXAMPLES, [rfc4004_mip, + rfc4005_nas, + rfc4006_cc, + rfc4072_eap, + rfc4590_digest, + rfc4740_sip]). + %% =========================================================================== suite() -> @@ -335,7 +344,8 @@ suite() -> all() -> [format, replace, - generate]. + generate, + examples]. %% Error handling testcases will make an erroneous dictionary out of %% the base dictionary and check that the expected error results. @@ -349,8 +359,6 @@ end_per_suite(_Config) -> ok. %% =========================================================================== -%% testcases - %% format/1 %% %% Ensure that parse o format is the identity map. @@ -367,6 +375,7 @@ format(Mods, Bin) -> {ok, D} = diameter_dict_util:parse(diameter_dict_util:format(Dict), []), {Dict, Dict} = {Dict, D}. +%% =========================================================================== %% replace/1 %% %% Ensure the expected success/error when parsing a morphed common @@ -393,12 +402,13 @@ replace({E, Mods}, Bin) -> re({RE, Repl}, Bin) -> re:replace(Bin, RE, Repl, [multiline]). +%% =========================================================================== %% generate/1 %% %% Ensure success when generating code and compiling. generate() -> - [{timetrap, {seconds, length(?REPLACE)}}]. + [{timetrap, {seconds, 2*length(?REPLACE)}}]. generate(Config) -> Bin = proplists:get_value(base, Config), @@ -422,6 +432,44 @@ generate(Mods, Bin, N, Mode) -> andalso ({ok, _} = compile:file(File ++ ".erl", [return_errors])). %% =========================================================================== +%% examples/1 +%% +%% Compile dictionaries extracted from various standards. + +examples() -> + [{timetrap, {seconds, 3*length(?EXAMPLES)}}]. + +examples(_Config) -> + Dir = filename:join([code:lib_dir(diameter, examples), "dict"]), + [D || D <- ?EXAMPLES, _ <- [examples(?S(D), Dir)]]. + +examples(Dict, Dir) -> + {Name, Pre} = make_name(Dict), + ok = diameter_make:codec(filename:join([Dir, Dict ++ ".dia"]), + [{name, Name}, + {prefix, Pre}, + inherits("rfc3588_base") + | opts(Dict)]), + {ok, _, _} = compile:file(Name ++ ".erl", [return]). + +opts(M) + when M == "rfc4006_cc"; + M == "rfc4072_eap" -> + [inherits("rfc4005_nas")]; +opts("rfc4740_sip") -> + [inherits("rfc4590_digest")]; +opts(_) -> + []. + +inherits(File) -> + {Name, _} = make_name(File), + {inherits, File ++ "/" ++ Name}. + +make_name(File) -> + {R, [$_|N]} = lists:splitwith(fun(C) -> C /= $_ end, File), + {string:join(["diameter_gen", N, R], "_"), "diameter_" ++ N}. + +%% =========================================================================== modify(Bin, Mods) -> lists:foldl(fun re/2, Bin, Mods). diff --git a/lib/diameter/test/diameter_dict_SUITE.erl b/lib/diameter/test/diameter_dict_SUITE.erl index 87bb9727fe..5cf8506d3f 100644 --- a/lib/diameter/test/diameter_dict_SUITE.erl +++ b/lib/diameter/test/diameter_dict_SUITE.erl @@ -25,9 +25,7 @@ -export([suite/0, all/0, - groups/0, - init_per_group/2, - end_per_group/2]). + groups/0]). %% testcases -export([append/1, @@ -53,10 +51,11 @@ suite() -> [{timetrap, {seconds, 10}}]. all() -> - [{group, all} | tc()]. + [{group, all}, + {group, all, [parallel]}]. groups() -> - [{all, [parallel], tc()}]. + [{all, [], tc()}]. tc() -> [append, @@ -71,12 +70,6 @@ tc() -> update, update_counter]. -init_per_group(_, Config) -> - Config. - -end_per_group(_, _) -> - ok. - %% =========================================================================== -define(KV100, [{N,[N]} || N <- lists:seq(1,100)]). diff --git a/lib/diameter/test/diameter_failover_SUITE.erl b/lib/diameter/test/diameter_failover_SUITE.erl index 429b6328e6..53398dd93e 100644 --- a/lib/diameter/test/diameter_failover_SUITE.erl +++ b/lib/diameter/test/diameter_failover_SUITE.erl @@ -174,7 +174,7 @@ realm(Host) -> call(Req, Opts) -> diameter:call(?CLIENT, ?APP_ALIAS, Req, Opts). - + set([H|T], Vs) -> [H | Vs ++ T]. diff --git a/lib/diameter/test/diameter_gen_sctp_SUITE.erl b/lib/diameter/test/diameter_gen_sctp_SUITE.erl new file mode 100644 index 0000000000..7f435a6b7a --- /dev/null +++ b/lib/diameter/test/diameter_gen_sctp_SUITE.erl @@ -0,0 +1,354 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010-2011. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%% Some gen_sctp-specific tests demonstrating problems that were +%% encountered during diameter development but have nothing +%% specifically to do with diameter. At least one of them can cause +%% diameter_transport_SUITE testcases to fail. +%% + +-module(diameter_gen_sctp_SUITE). + +-export([suite/0, + all/0, + init_per_suite/1, + end_per_suite/1]). + +%% testcases +-export([send_not_from_controlling_process/1, + send_from_multiple_clients/1, + receive_what_was_sent/1]). + +-include_lib("kernel/include/inet_sctp.hrl"). + +%% Message from gen_sctp are of this form. +-define(SCTP(Sock, Data), {sctp, Sock, _, _, Data}). + +%% Open sockets on the loopback address. +-define(ADDR, {127,0,0,1}). + +%% Snooze, nap, siesta. +-define(SLEEP(T), receive after T -> ok end). + +%% An indescribably long number of milliseconds after which everthing +%% that should have happened has. +-define(FOREVER, 2000). + +%% The first byte in each message we send as a simple guard against +%% not receiving what was sent. +-define(MAGIC, 42). + +%% =========================================================================== + +suite() -> + [{timetrap, {minutes, 2}}]. + +all() -> + [send_not_from_controlling_process, + send_from_multiple_clients, + receive_what_was_sent]. + +init_per_suite(Config) -> + case gen_sctp:open() of + {ok, Sock} -> + gen_sctp:close(Sock), + Config; + {error, E} when E == eprotonosupport; + E == esocktnosupport -> + {skip, no_sctp} + end. + +end_per_suite(_Config) -> + ok. + +%% =========================================================================== + +%% send_not_from_controlling_process/1 +%% +%% This testcase failing shows gen_sctp:send/4 hanging when called +%% outside the controlling process of the socket in question. + +send_not_from_controlling_process(_) -> + Pids = send_not_from_controlling_process(), + ?SLEEP(?FOREVER), + try + [] = [{P,I} || P <- Pids, I <- [process_info(P)], I /= undefined] + after + lists:foreach(fun(P) -> exit(P, kill) end, Pids) + end. + +%% send_not_from_controlling_process/0 +%% +%% Returns the pids of three spawned processes: a listening process, a +%% connecting process and a sending process. +%% +%% The expected behaviour is that all three processes exit: +%% +%% - The listening process exits upon receiving an SCTP message +%% sent by the sending process. +%% - The connecting process exits upon listening process exit. +%% - The sending process exits upon gen_sctp:send/4 return. +%% +%% The observed behaviour is that all three processes remain alive +%% indefinitely: +%% +%% - The listening process never receives the SCTP message sent +%% by the sending process. +%% - The connecting process has an inet_reply message in its mailbox +%% as a consequence of the call to gen_sctp:send/4 call from the +%% sending process. +%% - The call to gen_sctp:send/4 in the sending process doesn't return, +%% hanging in prim_inet:getopts/2. + +send_not_from_controlling_process() -> + FPid = self(), + {L, MRef} = spawn_monitor(fun() -> listen(FPid) end),%% listening process + receive + {?MODULE, C, S} -> + erlang:demonitor(MRef, [flush]), + [L,C,S]; + {'DOWN', MRef, process, _, _} = T -> + error(T) + end. + +%% listen/1 + +listen(FPid) -> + {ok, Sock} = open(), + ok = gen_sctp:listen(Sock, true), + {ok, PortNr} = inet:port(Sock), + LPid = self(), + spawn(fun() -> connect1(PortNr, FPid, LPid) end), %% connecting process + Id = assoc(Sock), + ?SCTP(Sock, {[#sctp_sndrcvinfo{assoc_id = Id}], _Bin}) + = recv(). %% Waits with this as current_function. + +%% recv/0 + +recv() -> + receive T -> T end. + +%% connect1/3 + +connect1(PortNr, FPid, LPid) -> + {ok, Sock} = open(), + ok = gen_sctp:connect_init(Sock, ?ADDR, PortNr, []), + Id = assoc(Sock), + FPid ! {?MODULE, + self(), + spawn(fun() -> send(Sock, Id) end)}, %% sending process + MRef = erlang:monitor(process, LPid), + down(MRef). %% Waits with this as current_function. + +%% down/1 + +down(MRef) -> + receive {'DOWN', MRef, process, _, Reason} -> Reason end. + +%% send/2 + +send(Sock, Id) -> + ok = gen_sctp:send(Sock, Id, 0, <<0:32>>). + +%% =========================================================================== + +%% send_from_multiple_clients/0 +%% +%% Demonstrates sluggish delivery of messages. + +send_from_multiple_clients(_) -> + {S, Rs} = T = send_from_multiple_clients(8, 1024), + {false, [], _} = {?FOREVER < S, + Rs -- [OI || {O,_} = OI <- Rs, is_integer(O)], + T}. + +%% send_from_multiple_clients/2 +%% +%% Opens a listening socket and then spawns a specified number of +%% processes, each of which connects to the listening socket. Each +%% connecting process then sends a message, whose size in bytes is +%% passed as an argument, the listening process sends a reply +%% containing the time at which the message was received, and the +%% connecting process then exits upon reception of this reply. +%% +%% Returns the elapsed time for all connecting process to exit +%% together with a list of exit reasons for the connecting processes. +%% In the successful case a connecting process exits with the +%% outbound/inbound transit times for the sent/received message as +%% reason. +%% +%% The observed behaviour is that some outbound messages (that is, +%% from a connecting process to the listening process) can take an +%% unexpectedly long time to complete their journey. The more +%% connecting processes, the longer the possible delay it seems. +%% +%% eg. (With F = fun send_from_multiple_clients/2.) +%% +%% 5> F(2, 1024). +%% {875,[{128,116},{113,139}]} +%% 6> F(4, 1024). +%% {2995290,[{2994022,250},{2994071,80},{200,130},{211,113}]} +%% 7> F(8, 1024). +%% {8997461,[{8996161,116}, +%% {2996471,86}, +%% {2996278,116}, +%% {2996360,95}, +%% {246,112}, +%% {213,159}, +%% {373,173}, +%% {376,118}]} +%% 8> F(8, 1024). +%% {21001891,[{20999968,128}, +%% {8997891,172}, +%% {8997927,91}, +%% {2995716,164}, +%% {2995860,87}, +%% {134,100}, +%% {117,98}, +%% {149,125}]} + +send_from_multiple_clients(N, Sz) + when is_integer(N), 0 < N, is_integer(Sz), 0 < Sz -> + timer:tc(fun listen/2, [N, <<?MAGIC, 0:Sz/unit:8>>]). + +%% listen/2 + +listen(N, Bin) -> + {ok, Sock} = open(), + ok = gen_sctp:listen(Sock, true), + {ok, PortNr} = inet:port(Sock), + + %% Spawn a middleman that in turn spawns N connecting processes, + %% collects a list of exit reasons and then exits with the list as + %% reason. loop/3 returns when we receive this list from the + %% middleman's 'DOWN'. + + Self = self(), + Fun = fun() -> exit(connect2(Self, PortNr, Bin)) end, + {_, MRef} = spawn_monitor(fun() -> exit(fold(N, Fun)) end), + loop(Sock, MRef, Bin). + +%% fold/2 +%% +%% Spawn N processes and collect their exit reasons in a list. + +fold(N, Fun) -> + start(N, Fun), + acc(N, []). + +start(0, _) -> + ok; +start(N, Fun) -> + spawn_monitor(Fun), + start(N-1, Fun). + +acc(0, Acc) -> + Acc; +acc(N, Acc) -> + receive + {'DOWN', _MRef, process, _, RC} -> + acc(N-1, [RC | Acc]) + end. + +%% loop/3 + +loop(Sock, MRef, Bin) -> + receive + ?SCTP(Sock, {[#sctp_sndrcvinfo{assoc_id = Id}], B}) -> + Sz = size(Bin), + {Sz, Bin} = {size(B), B}, %% assert + ok = send(Sock, Id, mark(Bin)), + loop(Sock, MRef, Bin); + ?SCTP(Sock, _) -> + loop(Sock, MRef, Bin); + {'DOWN', MRef, process, _, Reason} -> + Reason + end. + +%% connect2/3 + +connect2(Pid, PortNr, Bin) -> + erlang:monitor(process, Pid), + + {ok, Sock} = open(), + ok = gen_sctp:connect_init(Sock, ?ADDR, PortNr, []), + Id = assoc(Sock), + + %% T1 = time before send + %% T2 = time after listening process received our message + %% T3 = time after reply is received + + T1 = now(), + ok = send(Sock, Id, Bin), + T2 = unmark(recv(Sock, Id)), + T3 = now(), + {timer:now_diff(T2, T1), timer:now_diff(T3, T2)}. %% {Outbound, Inbound} + +%% recv/2 + +recv(Sock, Id) -> + receive + ?SCTP(Sock, {[#sctp_sndrcvinfo{assoc_id = Id}], Bin}) -> + Bin; + T -> %% eg. 'DOWN' + exit(T) + end. + +%% send/3 + +send(Sock, Id, Bin) -> + gen_sctp:send(Sock, Id, 0, Bin). + +%% mark/1 + +mark(Bin) -> + Info = term_to_binary(now()), + <<Info/binary, Bin/binary>>. + +%% unmark/1 + +unmark(Bin) -> + {_,_,_} = binary_to_term(Bin). + +%% =========================================================================== + +%% receive_what_was_sent/1 +%% +%% Demonstrates reception of a message that differs from that sent. + +receive_what_was_sent(_Config) -> + send_from_multiple_clients(1, 1024*32). %% fails + +%% =========================================================================== + +%% open/0 + +open() -> + gen_sctp:open([{ip, ?ADDR}, {port, 0}, {active, true}, binary]). + +%% assoc/1 + +assoc(Sock) -> + receive + ?SCTP(Sock, {[], #sctp_assoc_change{state = S, + assoc_id = Id}}) -> + comm_up = S, %% assert + Id + end. diff --git a/lib/diameter/test/diameter_reg_SUITE.erl b/lib/diameter/test/diameter_reg_SUITE.erl index ade824c9dd..ec6a0ca731 100644 --- a/lib/diameter/test/diameter_reg_SUITE.erl +++ b/lib/diameter/test/diameter_reg_SUITE.erl @@ -26,8 +26,6 @@ -export([suite/0, all/0, groups/0, - init_per_group/2, - end_per_group/2, init_per_suite/1, end_per_suite/1]). @@ -48,10 +46,11 @@ suite() -> [{timetrap, {seconds, 10}}]. all() -> - [{group, all} | tc()]. + [{group, all}, + {group, all, [parallel]}]. groups() -> - [{all, [parallel], tc()}]. + [{all, [], tc()}]. tc() -> [add, @@ -61,12 +60,6 @@ tc() -> terms, pids]. -init_per_group(_, Config) -> - Config. - -end_per_group(_, _) -> - ok. - init_per_suite(Config) -> ok = diameter:start(), Config. diff --git a/lib/diameter/test/diameter_relay_SUITE.erl b/lib/diameter/test/diameter_relay_SUITE.erl index c0351f8cf2..70e1866791 100644 --- a/lib/diameter/test/diameter_relay_SUITE.erl +++ b/lib/diameter/test/diameter_relay_SUITE.erl @@ -35,9 +35,7 @@ -export([suite/0, all/0, - groups/0, - init_per_group/2, - end_per_group/2]). + groups/0]). %% testcases -export([start/1, @@ -117,21 +115,17 @@ suite() -> [{timetrap, {seconds, 10}}]. all() -> - [start, start_services, connect] - ++ tc() - ++ [{group, all}, - disconnect, - stop_services, - stop]. + [start, + start_services, + connect, + {group, all}, + {group, all, [parallel]}, + disconnect, + stop_services, + stop]. groups() -> - [{all, [parallel], tc()}]. - -init_per_group(_, Config) -> - Config. - -end_per_group(_, _) -> - ok. + [{all, [], tc()}]. %% Traffic cases run when services are started and connections %% established. @@ -248,7 +242,7 @@ call(Server) -> call(Req, Opts) -> diameter:call(?CLIENT, ?APP_ALIAS, Req, Opts). - + set([H|T], Vs) -> [H | Vs ++ T]. diff --git a/lib/diameter/test/diameter_stats_SUITE.erl b/lib/diameter/test/diameter_stats_SUITE.erl index e50a0050a6..e7807fd360 100644 --- a/lib/diameter/test/diameter_stats_SUITE.erl +++ b/lib/diameter/test/diameter_stats_SUITE.erl @@ -26,8 +26,6 @@ -export([suite/0, all/0, groups/0, - init_per_group/2, - end_per_group/2, init_per_suite/1, end_per_suite/1]). @@ -44,21 +42,16 @@ suite() -> [{timetrap, {seconds, 10}}]. all() -> - [{group, all} | tc()]. + [{group, all}, + {group, all, [parallel]}]. groups() -> - [{all, [parallel], tc()}]. + [{all, [], tc()}]. tc() -> [an, twa]. -init_per_group(_, Config) -> - Config. - -end_per_group(_, _) -> - ok. - init_per_suite(Config) -> ok = diameter:start(), Config. diff --git a/lib/diameter/test/diameter_sync_SUITE.erl b/lib/diameter/test/diameter_sync_SUITE.erl index 84f77b6066..ab629fb1c1 100644 --- a/lib/diameter/test/diameter_sync_SUITE.erl +++ b/lib/diameter/test/diameter_sync_SUITE.erl @@ -26,8 +26,6 @@ -export([suite/0, all/0, groups/0, - init_per_group/2, - end_per_group/2, init_per_suite/1, end_per_suite/1]). @@ -48,10 +46,11 @@ suite() -> [{timetrap, {seconds, 10}}]. all() -> - [{group, all} | tc()]. + [{group, all}, + {group, all, [parallel]}]. groups() -> - [{all, [parallel], tc()}]. + [{all, [], tc()}]. tc() -> [call, @@ -59,12 +58,6 @@ tc() -> timeout, flush]. -init_per_group(_, Config) -> - Config. - -end_per_group(_, _) -> - ok. - init_per_suite(Config) -> ok = diameter:start(), Config. diff --git a/lib/diameter/test/diameter_tls_SUITE.erl b/lib/diameter/test/diameter_tls_SUITE.erl index 38282282b8..85b953dc1a 100644 --- a/lib/diameter/test/diameter_tls_SUITE.erl +++ b/lib/diameter/test/diameter_tls_SUITE.erl @@ -36,8 +36,6 @@ -export([suite/0, all/0, groups/0, - init_per_group/2, - end_per_group/2, init_per_suite/1, end_per_suite/1]). @@ -136,20 +134,16 @@ all() -> start_diameter, make_certs, start_services, - add_transports] - ++ [{group, N} || {N, _, _} <- groups()] - ++ [remove_transports, stop_services, stop_diameter, stop_ssl]. + add_transports, + {group, all}, + {group, all, [parallel]}, + remove_transports, + stop_services, + stop_diameter, + stop_ssl]. groups() -> - Ts = tc(), - [{all, [], Ts}, - {p, [parallel], Ts}]. - -init_per_group(_, Config) -> - Config. - -end_per_group(_, _) -> - ok. + [{all, [], tc()}]. %% Shouldn't really have to know about crypto here but 'ok' from %% ssl:start() isn't enough to guarantee that TLS is available. diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl index 78131b4ec4..6eed8d3b5d 100644 --- a/lib/diameter/test/diameter_traffic_SUITE.erl +++ b/lib/diameter/test/diameter_traffic_SUITE.erl @@ -162,27 +162,16 @@ suite() -> [{timetrap, {seconds, 10}}]. all() -> - [start, start_services, add_transports, result_codes - | [{group, N} || {N, _, _} <- groups()]] + [start, start_services, add_transports, result_codes] + ++ [{group, E, P} || E <- ?ENCODINGS, P <- [[], [parallel]]] ++ [remove_transports, stop_services, stop]. groups() -> Ts = tc(), - [{grp(E,P), P, Ts} || E <- ?ENCODINGS, P <- [[], [parallel]]]. - -grp(E, []) -> - E; -grp(E, [parallel]) -> - ?P(E). + [{E, [], Ts} || E <- ?ENCODINGS]. init_per_group(Name, Config) -> - E = case ?L(Name) of - "p_" ++ Rest -> - ?A(Rest); - _ -> - Name - end, - [{encode, E} | Config]. + [{encode, Name} | Config]. end_per_group(_, _) -> ok. @@ -516,10 +505,10 @@ send_multiple_filters(Config, Fs) -> %% Ensure that we can pass a request in any form to diameter:call/4, %% only the return value from the prepare_request callback being %% significant. -send_anything(Config) -> +send_anything(Config) -> #diameter_base_STA{'Result-Code' = ?SUCCESS} = call(Config, anything). - + %% =========================================================================== call(Config, Req) -> diff --git a/lib/diameter/test/diameter_transport_SUITE.erl b/lib/diameter/test/diameter_transport_SUITE.erl index df7161fd1e..893b7ba2f9 100644 --- a/lib/diameter/test/diameter_transport_SUITE.erl +++ b/lib/diameter/test/diameter_transport_SUITE.erl @@ -27,8 +27,6 @@ -export([suite/0, all/0, groups/0, - init_per_group/2, - end_per_group/2, init_per_suite/1, end_per_suite/1]). @@ -92,10 +90,13 @@ suite() -> [{timetrap, {minutes, 2}}]. all() -> - [start | tc()] ++ [{group, all}, stop]. + [start, + {group, all}, + {group, all, [parallel]}, + stop]. groups() -> - [{all, [parallel], tc()}]. + [{all, [], tc()}]. tc() -> [tcp_accept, @@ -103,12 +104,6 @@ tc() -> sctp_accept, sctp_connect]. -init_per_group(_, Config) -> - Config. - -end_per_group(_, _) -> - ok. - init_per_suite(Config) -> [{sctp, have_sctp()} | Config]. @@ -175,16 +170,13 @@ connect(Prot) -> %% have_sctp/0 have_sctp() -> - try gen_sctp:open() of + case gen_sctp:open() of {ok, Sock} -> gen_sctp:close(Sock), true; {error, E} when E == eprotonosupport; E == esocktnosupport -> %% fail on any other reason false - catch - error: badarg -> - false end. %% if_sctp/2 @@ -220,7 +212,7 @@ init(gen_connect, {Prot, Ref}) -> [PortNr] = ?util:lport(Prot, Ref, 20), %% Connect, send a message and receive it back. - {ok, Sock} = gen_connect(Prot, PortNr, Ref), + {ok, Sock} = gen_connect(Prot, PortNr), Bin = make_msg(), ok = gen_send(Prot, Sock, Bin), Bin = gen_recv(Prot, Sock); @@ -359,20 +351,7 @@ tmod(tcp) -> %% =========================================================================== -%% gen_connect/3 - -gen_connect(Prot, PortNr, Ref) -> - Pid = sync(connect, Ref), - - %% Stagger connect attempts to avoid the situation that no - %% transport process is accepting yet. - receive after 250 -> ok end, - - try - gen_connect(Prot, PortNr) - after - Pid ! Ref - end. +%% gen_connect/2 gen_connect(sctp = P, PortNr) -> {ok, Sock} = Ok = gen_sctp:open([{ip, ?ADDR}, {port, 0} | ?SCTP_OPTS]), diff --git a/lib/diameter/test/diameter_util.erl b/lib/diameter/test/diameter_util.erl index 6b1dc1f0c9..0c42f955ad 100644 --- a/lib/diameter/test/diameter_util.erl +++ b/lib/diameter/test/diameter_util.erl @@ -212,7 +212,7 @@ read_priv(Config, Name) -> read(Path) -> {ok, Bin} = file:read_file(Path), binary_to_term(Bin). - + %% map_priv/3 %% %% Modify a term in a file and return both old and new values. diff --git a/lib/diameter/test/diameter_watchdog_SUITE.erl b/lib/diameter/test/diameter_watchdog_SUITE.erl index b40d7c104d..ff40326947 100644 --- a/lib/diameter/test/diameter_watchdog_SUITE.erl +++ b/lib/diameter/test/diameter_watchdog_SUITE.erl @@ -306,11 +306,8 @@ watchdog(Type, Ref, TPid, Wd) -> Opts = [{transport_module, ?MODULE}, {transport_config, TPid}, {watchdog_timer, Wd}], - monitor(diameter_watchdog:start({Type, Ref}, - {false, Opts, false, ?SERVICE})). - -monitor(Pid) -> - erlang:monitor(process, Pid), + {_MRef, Pid} = diameter_watchdog:start({Type, Ref}, + {false, Opts, false, ?SERVICE}), Pid. %% =========================================================================== @@ -350,6 +347,10 @@ init(_, _, TPid, _) -> monitor(TPid), 3. +monitor(Pid) -> + erlang:monitor(process, Pid), + Pid. + %% Generate a unique hostname for the faked peer. hostname() -> lists:flatten(io_lib:format("~p-~p-~p", tuple_to_list(now()))). diff --git a/lib/diameter/test/modules.mk b/lib/diameter/test/modules.mk index 54978d820c..7f163536fb 100644 --- a/lib/diameter/test/modules.mk +++ b/lib/diameter/test/modules.mk @@ -33,6 +33,7 @@ MODULES = \ diameter_sync_SUITE \ diameter_stats_SUITE \ diameter_watchdog_SUITE \ + diameter_gen_sctp_SUITE \ diameter_transport_SUITE \ diameter_capx_SUITE \ diameter_traffic_SUITE \ @@ -42,3 +43,9 @@ MODULES = \ HRL_FILES = \ diameter_ct.hrl + +DATA = \ + diameter_codec_SUITE_data/avps.dia \ + diameter_codec_SUITE_data/send.dia \ + diameter_codec_SUITE_data/recv.dia \ + diameter_codec_SUITE_data/diameter_test_unknown.erl diff --git a/lib/erl_docgen/priv/xsl/db_html.xsl b/lib/erl_docgen/priv/xsl/db_html.xsl index bdef7bfd3d..3f662327e6 100644 --- a/lib/erl_docgen/priv/xsl/db_html.xsl +++ b/lib/erl_docgen/priv/xsl/db_html.xsl @@ -1854,18 +1854,24 @@ <xsl:choose> <xsl:when test="string-length($filepart) > 0"> - <xsl:variable name="modulepart"><xsl:value-of select="substring-before($filepart, ':')"/></xsl:variable> + <!-- "Filepart#Linkpart" (or "Filepart#") --> + <xsl:variable name="app_part"><xsl:value-of select="substring-before($filepart, ':')"/></xsl:variable> <xsl:choose> - <xsl:when test="string-length($modulepart) > 0"> - <xsl:variable name="filepart1"><xsl:value-of select="substring-after($filepart, ':')"/></xsl:variable> - <span class="bold_code"><a href="javascript:erlhref('{$topdocdir}/../','{$modulepart}','{$filepart1}.html#{$linkpart}');"><xsl:apply-templates/></a></span> + <xsl:when test="string-length($app_part) > 0"> + <!-- "AppPart:ModPart#Linkpart" --> + <xsl:variable name="mod_part"><xsl:value-of select="substring-after($filepart, ':')"/></xsl:variable> + <span class="bold_code"><a href="javascript:erlhref('{$topdocdir}/../','{$app_part}','{$mod_part}.html#{$linkpart}');"><xsl:apply-templates/></a></span> </xsl:when> <xsl:otherwise> + <!-- "Filepart#Linkpart (there is no ':' in Filepart) --> + <xsl:variable name="minus_prefix" + select="substring-before($linkpart, '-')"/> <xsl:choose> - <!-- Dialyzer seealso (the application is unknown) --> - <xsl:when test="string-length($specs_file) > 0 + <xsl:when test="$minus_prefix = 'type' + and string-length($specs_file) > 0 and count($i/specs/module[@name=$filepart]) = 0"> - <!-- Deemed to slow; use key() instead + <!-- Dialyzer seealso (the application is unknown) --> + <!-- Following code deemed too slow; use key() instead <xsl:variable name="app" select="$m2a/mod2app/module[@name=$filepart]"/> --> @@ -1877,41 +1883,45 @@ <span class="bold_code"><a href="javascript:erlhref('{$topdocdir}/../','{$app}','{$filepart}.html#{$linkpart}');"><xsl:value-of select="$this"/></a></span> </xsl:when> <xsl:otherwise> - <!-- Unknown application; no link --> - <xsl:value-of select="$this"/> + <!-- Unknown application --> + <xsl:message terminate="yes"> + Error <xsl:value-of select="$filepart"/>: cannot find module exporting type + </xsl:message> </xsl:otherwise> </xsl:choose> </xsl:for-each> </xsl:when> <xsl:when test="string-length($linkpart) > 0"> + <!-- Still Filepart#Linkpart (there is no ':' in Filepart --> <span class="bold_code"><a href="{$filepart}.html#{$linkpart}"><xsl:apply-templates/></a></span> </xsl:when> <xsl:otherwise> + <!-- "Filepart#" (there is no ':' in Filepart --> <span class="bold_code"><a href="{$filepart}.html"><xsl:apply-templates/></a></span> </xsl:otherwise> </xsl:choose> </xsl:otherwise> </xsl:choose> + </xsl:when> <!-- string-length($filepart) > 0 --> + <xsl:when test="string-length($linkpart) > 0"> + <!-- "#Linkpart" --> + <span class="bold_code"><a href="#{$linkpart}"><xsl:apply-templates/></a></span> </xsl:when> <xsl:otherwise> - <xsl:choose> - <xsl:when test="string-length($linkpart) > 0"> - <span class="bold_code"><a href="#{$linkpart}"><xsl:apply-templates/></a></span> - </xsl:when> - <xsl:otherwise> - <xsl:variable name="modulepart"><xsl:value-of select="substring-before(@marker, ':')"/></xsl:variable> + <!-- "AppPart:Mod" or "Mod" (there is no '#') --> + <xsl:variable name="app_part"><xsl:value-of select="substring-before(@marker, ':')"/></xsl:variable> - <xsl:choose> - <xsl:when test="string-length($modulepart) > 0"> - <xsl:variable name="filepart1"><xsl:value-of select="substring-after(@marker, ':')"/></xsl:variable> - <span class="bold_code"><a href="javascript:erlhref('{$topdocdir}/../','{$modulepart}','{$filepart1}.html');"><xsl:apply-templates/></a></span> - </xsl:when> - <xsl:otherwise> - <span class="bold_code"><a href="{@marker}.html"><xsl:apply-templates/></a></span> - </xsl:otherwise> - </xsl:choose> - </xsl:otherwise> - </xsl:choose> + <xsl:choose> + <xsl:when test="string-length($app_part) > 0"> + <!-- "App:Mod" --> + <xsl:variable name="mod_part"><xsl:value-of select="substring-after(@marker, ':')"/></xsl:variable> + <span class="bold_code"><a href="javascript:erlhref('{$topdocdir}/../','{$app_part}','{$mod_part}.html');"><xsl:apply-templates/></a></span> + </xsl:when> + <xsl:otherwise> + <!-- "Mod" --> + <span class="bold_code"><a href="{@marker}.html"><xsl:apply-templates/></a></span> + </xsl:otherwise> + </xsl:choose> </xsl:otherwise> </xsl:choose> diff --git a/lib/erl_interface/src/misc/ei_format.c b/lib/erl_interface/src/misc/ei_format.c index cf50f12451..c1e5d998e4 100644 --- a/lib/erl_interface/src/misc/ei_format.c +++ b/lib/erl_interface/src/misc/ei_format.c @@ -149,7 +149,7 @@ static int pdigit(const char** fmt, ei_x_buff* x) { const char* start = *fmt; char c; - int len, dotp=0; + int dotp=0; double d; long l; @@ -166,7 +166,6 @@ static int pdigit(const char** fmt, ei_x_buff* x) break; } --(*fmt); - len = *fmt - start; if (dotp) { sscanf(start, "%lf", &d); return ei_x_encode_double(x, d); diff --git a/lib/hipe/flow/Makefile b/lib/hipe/flow/Makefile index 02f610587b..bbe8ef8666 100644 --- a/lib/hipe/flow/Makefile +++ b/lib/hipe/flow/Makefile @@ -65,7 +65,7 @@ DOC_FILES= $(MODULES:%=$(DOCS)/%.html) include ../native.mk -ERL_COMPILE_FLAGS += +warn_exported_vars +warn_missing_spec +warn_untyped_record +ERL_COMPILE_FLAGS += +warn_exported_vars +warn_missing_spec # +warn_untyped_record # ---------------------------------------------------- # Targets diff --git a/lib/hipe/icode/Makefile b/lib/hipe/icode/Makefile index eced90b0ec..bd6436c8b3 100644 --- a/lib/hipe/icode/Makefile +++ b/lib/hipe/icode/Makefile @@ -83,7 +83,7 @@ DOC_FILES= $(DOC_MODULES:%=$(DOCS)/%.html) include ../native.mk -ERL_COMPILE_FLAGS += +warn_unused_import +warn_missing_spec +warn_untyped_record +ERL_COMPILE_FLAGS += +warn_unused_import +warn_missing_spec # +warn_untyped_record # ---------------------------------------------------- # Targets diff --git a/lib/hipe/opt/Makefile b/lib/hipe/opt/Makefile index 74fde26c0b..4596201801 100644 --- a/lib/hipe/opt/Makefile +++ b/lib/hipe/opt/Makefile @@ -63,7 +63,7 @@ DOC_FILES= $(MODULES:%=$(DOCS)/%.html) include ../native.mk -ERL_COMPILE_FLAGS += +warn_exported_vars +warn_missing_spec +warn_untyped_record +ERL_COMPILE_FLAGS += +warn_exported_vars +warn_missing_spec # +warn_untyped_record # ---------------------------------------------------- # Targets diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java index 71a419497a..d6f319d378 100644 --- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java +++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java @@ -31,7 +31,7 @@ package com.ericsson.otp.erlang; * the recipient of the message. When sending messages to other mailboxes, the * recipient can only respond if the sender includes the pid as part of the * message contents. The sender can determine his own pid by calling - * {@link #self self()}. + * {@link #self() self()}. * </p> * * <p> diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpNode.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpNode.java index d499fae3fb..be7c8e5b1a 100644 --- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpNode.java +++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpNode.java @@ -182,7 +182,7 @@ public class OtpNode extends OtpLocalNode { * Create an unnamed {@link OtpMbox mailbox} that can be used to send and * receive messages with other, similar mailboxes and with Erlang processes. * Messages can be sent to this mailbox by using its associated - * {@link OtpMbox#self pid}. + * {@link OtpMbox#self() pid}. * * @return a mailbox. */ @@ -248,7 +248,7 @@ public class OtpNode extends OtpLocalNode { * Create an named mailbox that can be used to send and receive messages * with other, similar mailboxes and with Erlang processes. Messages can be * sent to this mailbox by using its registered name or the associated - * {@link OtpMbox#self pid}. + * {@link OtpMbox#self() pid}. * * @param name * a name to register for this mailbox. The name must be unique diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk index 76c62ece67..76d3003ff4 100644 --- a/lib/kernel/vsn.mk +++ b/lib/kernel/vsn.mk @@ -1 +1 @@ -KERNEL_VSN = 2.15 +KERNEL_VSN = 2.15.1 diff --git a/lib/orber/src/orber_tb.erl b/lib/orber/src/orber_tb.erl index eee67296d7..d3e3a8497d 100644 --- a/lib/orber/src/orber_tb.erl +++ b/lib/orber/src/orber_tb.erl @@ -209,7 +209,7 @@ check_illegal_tcp_options([binary |T], IllegalOpts) -> check_illegal_tcp_options(T,[binary |IllegalOpts]); check_illegal_tcp_options([{reuseaddr, V} |T], IllegalOpts) -> check_illegal_tcp_options(T,[{reuseaddr, V} |IllegalOpts]); -check_illegal_tcp_options([H|T], IllegalOpts) -> +check_illegal_tcp_options([_H|T], IllegalOpts) -> check_illegal_tcp_options(T, IllegalOpts). %%---------------------------------------------------------------------- diff --git a/lib/orber/test/orber_acl_SUITE.erl b/lib/orber/test/orber_acl_SUITE.erl index b43a00be19..49107cde84 100644 --- a/lib/orber/test/orber_acl_SUITE.erl +++ b/lib/orber/test/orber_acl_SUITE.erl @@ -80,7 +80,7 @@ end_per_group(_GroupName, Config) -> %%----------------------------------------------------------------- init_per_suite(Config) -> if - list(Config) -> + is_list(Config) -> Config; true -> exit("Config not a list") diff --git a/lib/public_key/.gitignore b/lib/public_key/.gitignore index db24906676..d30fe62c9d 100644 --- a/lib/public_key/.gitignore +++ b/lib/public_key/.gitignore @@ -1,7 +1,7 @@ # public_key -/lib/public_key/asn1/*.asn1db -/lib/public_key/asn1/*.erl -/lib/public_key/asn1/*.hrl -/lib/public_key/include/OTP-PUB-KEY.hrl -/lib/public_key/include/PKCS-FRAME.hrl +asn1/*.asn1db +asn1/*.erl +asn1/*.hrl +include/OTP-PUB-KEY.hrl +include/PKCS-FRAME.hrl diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml index 821e7a2300..0b6673e826 100644 --- a/lib/public_key/doc/src/public_key.xml +++ b/lib/public_key/doc/src/public_key.xml @@ -453,7 +453,7 @@ <desc> <p>Encodes a list of ssh file entries (public keys and attributes) to a binary. Possible attributes depends on the file type, see <seealso - marker="ssh_decode"> ssh_decode/2 </seealso></p> + marker="#ssh_decode-2"> ssh_decode/2 </seealso></p> </desc> </func> diff --git a/lib/runtime_tools/c_src/trace_ip_drv.c b/lib/runtime_tools/c_src/trace_ip_drv.c index 5396b8afa9..7ae6c1b329 100644 --- a/lib/runtime_tools/c_src/trace_ip_drv.c +++ b/lib/runtime_tools/c_src/trace_ip_drv.c @@ -212,11 +212,11 @@ static TraceIpData *lookup_data_by_port(int portno); static int set_nonblocking(SOCKET sock); static TraceIpMessage *make_buffer(int datasiz, unsigned char op, unsigned number); -static void enque_message(TraceIpData *data, unsigned char *buff, int bufflen, +static void enque_message(TraceIpData *data, char *buff, int bufflen, int byteswritten); static void clean_que(TraceIpData *data); static void close_client(TraceIpData *data); -static int trywrite(TraceIpData *data, unsigned char *buff, int bufflen); +static int trywrite(TraceIpData *data, char *buff, int bufflen); static SOCKET my_accept(SOCKET sock); static void close_unlink_port(TraceIpData *data); enum MySelectOp { SELECT_ON, SELECT_OFF, SELECT_CLOSE }; @@ -518,7 +518,7 @@ static void trace_ip_ready_output(ErlDrvData handle, ErlDrvEvent fd) tim = data->que[data->questart]; towrite = tim->siz - tim->written; while((res = write_until_done(data->fd, - tim->bin + tim->written, towrite)) + (char *)tim->bin + tim->written, towrite)) == towrite) { driver_free(tim); data->que[data->questart] = NULL; @@ -561,7 +561,7 @@ static ErlDrvSSizeT trace_ip_control(ErlDrvData handle, TraceIpData *data = (TraceIpData *) handle; ErlDrvBinary *b = my_alloc_binary(3); b->orig_bytes[0] = '\0'; /* OK */ - put_be16(data->listen_portno, &(b->orig_bytes[1])); + put_be16(data->listen_portno, (unsigned char *)&(b->orig_bytes[1])); *res = void_ptr = b; return 0; } @@ -696,7 +696,7 @@ static TraceIpMessage *make_buffer(int datasiz, unsigned char op, ** Add message to que, discarding in a politically correct way... ** The FLAG_DROP_OLDEST is currently ingored... */ -static void enque_message(TraceIpData *data, unsigned char *buff, int bufflen, +static void enque_message(TraceIpData *data, char *buff, int bufflen, int byteswritten) { int diff = data->questop - data->questart; @@ -763,13 +763,13 @@ static void close_client(TraceIpData *data) ** Try to write a message from erlang directly (only called when que is empty ** and client is connected) */ -static int trywrite(TraceIpData *data, unsigned char *buff, int bufflen) +static int trywrite(TraceIpData *data, char *buff, int bufflen) { - unsigned char op[5]; + char op[5]; int res; op[0] = OP_BINARY; - put_be32(bufflen, op + 1); + put_be32(bufflen, (unsigned char *)op + 1); if ((res = write_until_done(data->fd, op, 5)) < 0) { close_client(data); @@ -793,7 +793,11 @@ static int trywrite(TraceIpData *data, unsigned char *buff, int bufflen) static SOCKET my_accept(SOCKET sock) { struct sockaddr_in sin; - int sin_size = sizeof(sin); +#ifdef HAVE_SOCKLEN_T + socklen_t sin_size = sizeof(sin); +#else + int sin_size = (int) sizeof(sin); +#endif return accept(sock, (struct sockaddr *) &sin, &sin_size); } diff --git a/lib/sasl/doc/src/appup.xml b/lib/sasl/doc/src/appup.xml index 195f9fe1d3..770b7c2492 100644 --- a/lib/sasl/doc/src/appup.xml +++ b/lib/sasl/doc/src/appup.xml @@ -332,7 +332,7 @@ restart_new_emulator <p>An info report will be written when the upgrade is completed. To programatically find out if the upgrade is complete, - call <seealso marker="release_handler#which_release/0"> + call <seealso marker="release_handler#which_releases/0"> release_handler:which_releases</seealso> and check if the expected release has status <c>current</c>.</p> <p>The new release must still be made permanent after the upgrade diff --git a/lib/sasl/doc/src/systools.xml b/lib/sasl/doc/src/systools.xml index 32c2149a8d..84fed0a25f 100644 --- a/lib/sasl/doc/src/systools.xml +++ b/lib/sasl/doc/src/systools.xml @@ -196,6 +196,10 @@ <p>The applications are sorted according to the dependencies between the applications. Where there are no dependencies, the order in the <c>.rel</c> file is kept.</p> + <p>The function will fail if the mandatory + applications <c>kernel</c> and <c>stdlib</c> are not + included in the <c>.rel</c> file and have start + type <c>permanent</c> (default).</p> <p>If <c>sasl</c> is not included as an application in the <c>.rel</c> file, a warning is emitted because such a release can not be used in an upgrade. To turn off this diff --git a/lib/sasl/src/systools_make.erl b/lib/sasl/src/systools_make.erl index 8fd90c50f9..12ba2a5476 100644 --- a/lib/sasl/src/systools_make.erl +++ b/lib/sasl/src/systools_make.erl @@ -463,30 +463,35 @@ check_appl(Appl) -> end, Appl) of [] -> - {ok,Ws} = mandatory_applications(Appl), - {split_app_incl(Appl),Ws}; + {ApplsNoIncls,Incls} = split_app_incl(Appl), + {ok,Ws} = mandatory_applications(ApplsNoIncls,undefined, + undefined,undefined), + {{ApplsNoIncls,Incls},Ws}; Illegal -> throw({error, {illegal_applications,Illegal}}) end. -mandatory_applications(Appl) -> - AppNames = map(fun(AppT) -> element(1, AppT) end, - Appl), - Mand = mandatory_applications(), - case filter(fun(X) -> member(X, AppNames) end, Mand) of - Mand -> - case member(sasl,AppNames) of - true -> - {ok,[]}; - _ -> - {ok, [{warning,missing_sasl}]} - end; - _ -> - throw({error, {missing_mandatory_app, Mand}}) - end. - -mandatory_applications() -> - [kernel, stdlib]. +mandatory_applications([{kernel,_,Type}|Apps],undefined,Stdlib,Sasl) -> + mandatory_applications(Apps,Type,Stdlib,Sasl); +mandatory_applications([{stdlib,_,Type}|Apps],Kernel,undefined,Sasl) -> + mandatory_applications(Apps,Kernel,Type,Sasl); +mandatory_applications([{sasl,_,Type}|Apps],Kernel,Stdlib,undefined) -> + mandatory_applications(Apps,Kernel,Stdlib,Type); +mandatory_applications([_|Apps],Kernel,Stdlib,Sasl) -> + mandatory_applications(Apps,Kernel,Stdlib,Sasl); +mandatory_applications([],Type,_,_) when Type=/=permanent -> + error_mandatory_application(kernel,Type); +mandatory_applications([],_,Type,_) when Type=/=permanent -> + error_mandatory_application(sasl,Type); +mandatory_applications([],_,_,undefined) -> + {ok, [{warning,missing_sasl}]}; +mandatory_applications([],_,_,_) -> + {ok,[]}. + +error_mandatory_application(App,undefined) -> + throw({error, {missing_mandatory_app, App}}); +error_mandatory_application(App,Type) -> + throw({error, {mandatory_app, App, Type}}). split_app_incl(Appl) -> split_app_incl(Appl, [], []). @@ -1677,6 +1682,7 @@ add_system_files(Tar, RelName, Release, Path1) -> false -> ignore; Relup -> + check_relup(Relup), add_to_tar(Tar, Relup, filename:join(RelVsnDir, "relup")) end, @@ -1684,6 +1690,7 @@ add_system_files(Tar, RelName, Release, Path1) -> false -> ignore; Sys -> + check_sys_config(Sys), add_to_tar(Tar, Sys, filename:join(RelVsnDir, "sys.config")) end, @@ -1700,6 +1707,44 @@ lookup_file(Name, [Dir|Path]) -> lookup_file(_Name, []) -> false. +%% Check that relup can be parsed and has expected format +check_relup(File) -> + case file:consult(File) of + {ok,[{Vsn,UpFrom,DownTo}]} when is_list(Vsn), is_integer(hd(Vsn)), + is_list(UpFrom), is_list(DownTo) -> + ok; + {ok,_} -> + throw({error,{tar_error,{add,"relup",[invalid_format]}}}); + Other -> + throw({error,{tar_error,{add,"relup",[Other]}}}) + end. + +%% Check that sys.config can be parsed and has expected format +check_sys_config(File) -> + case file:consult(File) of + {ok,[SysConfig]} -> + case lists:all(fun({App,KeyVals}) when is_atom(App), + is_list(KeyVals)-> + true; + (OtherConfig) when is_list(OtherConfig), + is_integer(hd(OtherConfig)) -> + true; + (_) -> + false + end, + SysConfig) of + true -> + ok; + false -> + throw({error,{tar_error, + {add,"sys.config",[invalid_format]}}}) + end; + {ok,_} -> + throw({error,{tar_error,{add,"sys.config",[invalid_format]}}}); + Other -> + throw({error,{tar_error,{add,"sys.config",[Other]}}}) + end. + %%______________________________________________________________________ %% Add either a application located under a variable dir or all other %% applications to a tar file. @@ -2187,9 +2232,12 @@ format_error({missing_parameter,Par}) -> format_error({illegal_applications,Names}) -> io_lib:format("Illegal applications in the release file: ~p~n", [Names]); -format_error({missing_mandatory_app,Names}) -> - io_lib:format("Mandatory applications (~p) must be specified in the release file~n", - [Names]); +format_error({missing_mandatory_app,Name}) -> + io_lib:format("Mandatory application ~p must be specified in the release file~n", + [Name]); +format_error({mandatory_app,Name,Type}) -> + io_lib:format("Mandatory application ~p must be of type 'permanent' in the release file. Is '~p'.~n", + [Name,Type]); format_error({duplicate_register,Dups}) -> io_lib:format("Duplicated register names: ~n~s", [map(fun({{Reg,App1,_,_},{Reg,App2,_,_}}) -> diff --git a/lib/sasl/test/systools_SUITE.erl b/lib/sasl/test/systools_SUITE.erl index 43366d8917..4cf7364d74 100644 --- a/lib/sasl/test/systools_SUITE.erl +++ b/lib/sasl/test/systools_SUITE.erl @@ -46,9 +46,11 @@ included_script/1, included_override_script/1, included_fail_script/1, included_bug_script/1, exref_script/1, otp_3065_circular_dependenies/1]). --export([tar_options/1, normal_tar/1, no_mod_vsn_tar/1, variable_tar/1, - src_tests_tar/1, var_tar/1, - exref_tar/1, link_tar/1, otp_9507_path_ebin/1]). +-export([tar_options/1, normal_tar/1, no_mod_vsn_tar/1, system_files_tar/1, + system_files_tar/2, invalid_system_files_tar/1, + invalid_system_files_tar/2, variable_tar/1, + src_tests_tar/1, var_tar/1, exref_tar/1, link_tar/1, + otp_9507_path_ebin/1]). -export([normal_relup/1, restart_relup/1, abnormal_relup/1, no_sasl_relup/1, no_appup_relup/1, bad_appup_relup/1, app_start_type_relup/1, regexp_relup/1]). @@ -80,7 +82,8 @@ groups() -> included_fail_script, included_bug_script, exref_script, otp_3065_circular_dependenies]}, {tar, [], - [tar_options, normal_tar, no_mod_vsn_tar, variable_tar, + [tar_options, normal_tar, no_mod_vsn_tar, system_files_tar, + invalid_system_files_tar, variable_tar, src_tests_tar, var_tar, exref_tar, link_tar, otp_9507_path_ebin]}, {relup, [], [normal_relup, restart_relup, abnormal_relup, no_sasl_relup, @@ -146,7 +149,10 @@ init_per_testcase(_Case, Config) -> Dog = test_server:timetrap(?default_timeout), [{watchdog, Dog}|Config]. -end_per_testcase(_Case, Config) -> +end_per_testcase(Case, Config) -> + try apply(?MODULE,Case,[cleanup,Config]) + catch error:undef -> ok + end, Dog=?config(watchdog, Config), test_server:timetrap_cancel(Dog), case {?config(path,Config),?config(cwd,Config)} of @@ -483,9 +489,17 @@ crazy_script(Config) when is_list(Config) -> ok = file:set_cwd(LatestDir2), error = systools:make_script(LatestName2), - {error, _, {missing_mandatory_app,[kernel,stdlib]}} = + {error, _, {missing_mandatory_app,kernel}} = systools:make_script(LatestName2, [silent,{path,P}]), + %% Run with .rel file with non-permanent kernel + {LatestDir3, LatestName3} = create_script(latest_kernel_start_type, Config), + ok = file:set_cwd(LatestDir3), + + error = systools:make_script(LatestName3), + {error, _, {mandatory_app,kernel,load}} = + systools:make_script(LatestName3, [silent,{path,P}]), + ok = file:set_cwd(OldDir), ok. @@ -756,6 +770,102 @@ no_mod_vsn_tar(Config) when is_list(Config) -> ok = file:set_cwd(OldDir), ok. + +%% make_tar: Check that relup or sys.config are included if they exist +system_files_tar(Config) -> + {ok, OldDir} = file:get_cwd(), + + {LatestDir, LatestName} = create_script(latest,Config), + + DataDir = filename:absname(?copydir), + LibDir = fname([DataDir, d_normal, lib]), + P = [fname([LibDir, 'db-2.1', ebin]), + fname([LibDir, 'fe-3.1', ebin])], + + ok = file:set_cwd(LatestDir), + + %% Add dummy relup and sys.config + ok = file:write_file("sys.config","[].\n"), + ok = file:write_file("relup","{\"LATEST\",[],[]}.\n"), + + {ok, _, _} = systools:make_script(LatestName, [silent, {path, P}]), + ok = systools:make_tar(LatestName, [{path, P}]), + ok = check_tar(fname(["releases","LATEST","sys.config"]), LatestName), + ok = check_tar(fname(["releases","LATEST","relup"]), LatestName), + {ok, _, _} = systools:make_tar(LatestName, [{path, P}, silent]), + ok = check_tar(fname(["releases","LATEST","sys.config"]), LatestName), + ok = check_tar(fname(["releases","LATEST","relup"]), LatestName), + + ok = file:set_cwd(OldDir), + + ok. + +system_files_tar(cleanup,Config) -> + Dir = ?privdir, + file:delete(filename:join(Dir,"sys.config")), + file:delete(filename:join(Dir,"relup")), + ok. + + +%% make_tar: Check that make_tar fails if relup or sys.config exist +%% but do not have valid content +invalid_system_files_tar(Config) -> + {ok, OldDir} = file:get_cwd(), + + {LatestDir, LatestName} = create_script(latest,Config), + + DataDir = filename:absname(?copydir), + LibDir = fname([DataDir, d_normal, lib]), + P = [fname([LibDir, 'db-2.1', ebin]), + fname([LibDir, 'fe-3.1', ebin])], + + ok = file:set_cwd(LatestDir), + + {ok, _, _} = systools:make_script(LatestName, [silent, {path, P}]), + + %% Add dummy relup and sys.config - faulty sys.config + ok = file:write_file("sys.config","[]\n"), %!!! syntax error - missing '.' + ok = file:write_file("relup","{\"LATEST\",[],[]}.\n"), + + error = systools:make_tar(LatestName, [{path, P}]), + {error,_,{tar_error,{add,"sys.config",[{error,_}]}}} = + systools:make_tar(LatestName, [{path, P}, silent]), + + %% Add dummy relup and sys.config - faulty sys.config + ok = file:write_file("sys.config","[x,y].\n"), %!!! faulty format + ok = file:write_file("relup","{\"LATEST\",[],[]}.\n"), + + error = systools:make_tar(LatestName, [{path, P}]), + {error,_,{tar_error,{add,"sys.config",[invalid_format]}}} = + systools:make_tar(LatestName, [{path, P}, silent]), + + %% Add dummy relup and sys.config - faulty relup + ok = file:write_file("sys.config","[]\n"), + ok = file:write_file("relup","{\"LATEST\"\n"), %!!! syntax error - truncated + + error = systools:make_tar(LatestName, [{path, P}]), + {error,_,{tar_error,{add,"relup",[{error,_}]}}} = + systools:make_tar(LatestName, [{path, P}, silent]), + + %% Add dummy relup and sys.config - faulty relup + ok = file:write_file("sys.config","[]\n"), + ok = file:write_file("relup","[].\n"), %!!! faulty format + + error = systools:make_tar(LatestName, [{path, P}]), + {error,_,{tar_error,{add,"relup",[invalid_format]}}} = + systools:make_tar(LatestName, [{path, P}, silent]), + + ok = file:set_cwd(OldDir), + + ok. + +invalid_system_files_tar(cleanup,Config) -> + Dir = ?privdir, + file:delete(filename:join(Dir,"sys.config")), + file:delete(filename:join(Dir,"relup")), + ok. + + %% make_tar: Use variable and create separate tar (included in generated tar). variable_tar(Config) when is_list(Config) -> {ok, OldDir} = file:get_cwd(), @@ -1915,6 +2025,9 @@ create_script(latest_small2,Config) -> create_script(latest_nokernel,Config) -> Apps = [{db,"2.1"},{fe,"3.1"}], do_create_script(latest_nokernel,Config,"4.4",Apps); +create_script(latest_kernel_start_type,Config) -> + Apps = [{kernel,"1.0",load},{db,"2.1"},{fe,"3.1"}], + do_create_script(latest_kernel_start_type,Config,"4.4",Apps); create_script(latest_app_start_type1,Config) -> Apps = core_apps(current), do_create_script(latest_app_start_type1,Config,current,Apps); diff --git a/lib/stdlib/doc/src/io.xml b/lib/stdlib/doc/src/io.xml index 667d758e29..e6d262466c 100644 --- a/lib/stdlib/doc/src/io.xml +++ b/lib/stdlib/doc/src/io.xml @@ -70,7 +70,7 @@ <desc> <p>Either <c>standard_io</c>, <c>standard_error</c>, a registered name, or a pid handling IO protocols (returned from - <seealso marker="file#open/2">file:open/2</seealso>).</p> + <seealso marker="kernel:file#open/2">file:open/2</seealso>).</p> </desc> </datatype> <datatype> diff --git a/lib/stdlib/doc/src/supervisor.xml b/lib/stdlib/doc/src/supervisor.xml index cddb55e5c5..33a7f5bb6a 100644 --- a/lib/stdlib/doc/src/supervisor.xml +++ b/lib/stdlib/doc/src/supervisor.xml @@ -127,25 +127,18 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules} <p><c>StartFunc</c> defines the function call used to start the child process. It should be a module-function-arguments tuple <c>{M,F,A}</c> used as <c>apply(M,F,A)</c>.</p> - <p> <br></br> -</p> <p>The start function <em>must create and link to</em> the child process, and should return <c>{ok,Child}</c> or <c>{ok,Child,Info}</c> where <c>Child</c> is the pid of the child process and <c>Info</c> an arbitrary term which is ignored by the supervisor.</p> - <p> <br></br> -</p> <p>The start function can also return <c>ignore</c> if the child process for some reason cannot be started, in which case - the child specification will be kept by the supervisor but - the non-existing child process will be ignored.</p> - <p> <br></br> -</p> + the child specification will be kept by the supervisor + (unless it is a temporary child) but the non-existing child + process will be ignored.</p> <p>If something goes wrong, the function may also return an error tuple <c>{error,Error}</c>.</p> - <p> <br></br> -</p> <p>Note that the <c>start_link</c> functions of the different behaviour modules fulfill the above requirements.</p> </item> diff --git a/lib/stdlib/src/supervisor.erl b/lib/stdlib/src/supervisor.erl index 42ea42f42e..ac5b078c29 100644 --- a/lib/stdlib/src/supervisor.erl +++ b/lib/stdlib/src/supervisor.erl @@ -270,6 +270,8 @@ start_children(Children, SupName) -> start_children(Children, [], SupName). start_children([Child|Chs], NChildren, SupName) -> case do_start_child(SupName, Child) of + {ok, undefined} when Child#child.restart_type =:= temporary -> + start_children(Chs, NChildren, SupName); {ok, Pid} -> start_children(Chs, [Child#child{pid = Pid}|NChildren], SupName); {ok, Pid, _Extra} -> @@ -325,6 +327,8 @@ handle_call({start_child, EArgs}, _From, State) when ?is_simple(State) -> #child{mfargs = {M, F, A}} = Child, Args = A ++ EArgs, case do_start_child_i(M, F, Args) of + {ok, undefined} when Child#child.restart_type =:= temporary -> + {reply, {ok, undefined}, State}; {ok, Pid} -> NState = save_dynamic_child(Child#child.restart_type, Pid, Args, State), {reply, {ok, Pid}, NState}; @@ -611,12 +615,12 @@ handle_start_child(Child, State) -> case get_child(Child#child.name, State) of false -> case do_start_child(State#state.name, Child) of + {ok, undefined} when Child#child.restart_type =:= temporary -> + {{ok, undefined}, State}; {ok, Pid} -> - {{ok, Pid}, - save_child(Child#child{pid = Pid}, State)}; + {{ok, Pid}, save_child(Child#child{pid = Pid}, State)}; {ok, Pid, Extra} -> - {{ok, Pid, Extra}, - save_child(Child#child{pid = Pid}, State)}; + {{ok, Pid, Extra}, save_child(Child#child{pid = Pid}, State)}; {error, What} -> {{error, {What, Child}}, State} end; diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl index 0e8849b5b3..101828fdef 100644 --- a/lib/stdlib/test/ets_SUITE.erl +++ b/lib/stdlib/test/ets_SUITE.erl @@ -74,7 +74,7 @@ -export([bad_table/1, types/1]). -export([otp_9423/1]). --export([init_per_testcase/2]). +-export([init_per_testcase/2, end_per_testcase/2]). %% Convenience for manual testing -export([random_test/0]). @@ -2385,6 +2385,8 @@ setopts_do(Opts) -> ?line {'EXIT',{badarg,_}} = (catch ets:setopts(T,{protection,private,false})), ?line {'EXIT',{badarg,_}} = (catch ets:setopts(T,protection)), ?line ets:delete(T), + unlink(Heir), + exit(Heir, bang), ok. bad_table(doc) -> ["All kinds of operations with bad table argument"]; @@ -5645,7 +5647,8 @@ spawn_logger(Procs) -> true -> exit(Proc, kill); _ -> ok end, - erlang:display(process_info(Proc)), + erlang:display({"Waiting for 'DOWN' from", Proc, + process_info(Proc), pid_status(Proc)}), receive {'DOWN', Mon, _, _, _} -> ok @@ -5656,6 +5659,15 @@ spawn_logger(Procs) -> spawn_logger([From]) end. +pid_status(Pid) -> + try + erts_debug:get_internal_state({process_status, Pid}) + catch + error:undef -> + erts_debug:set_internal_state(available_internal_state, true), + pid_status(Pid) + end. + start_spawn_logger() -> case whereis(ets_test_spawn_logger) of Pid when is_pid(Pid) -> true; diff --git a/lib/stdlib/test/supervisor_SUITE.erl b/lib/stdlib/test/supervisor_SUITE.erl index fa6faa66f2..71b76c093f 100644 --- a/lib/stdlib/test/supervisor_SUITE.erl +++ b/lib/stdlib/test/supervisor_SUITE.erl @@ -34,8 +34,10 @@ %% API tests -export([ sup_start_normal/1, sup_start_ignore_init/1, - sup_start_ignore_child/1, sup_start_error_return/1, - sup_start_fail/1, sup_stop_infinity/1, + sup_start_ignore_child/1, sup_start_ignore_temporary_child/1, + sup_start_ignore_temporary_child_start_child/1, + sup_start_ignore_temporary_child_start_child_simple/1, + sup_start_error_return/1, sup_start_fail/1, sup_stop_infinity/1, sup_stop_timeout/1, sup_stop_brutal_kill/1, child_adm/1, child_adm_simple/1, child_specs/1, extra_return/1]). @@ -85,8 +87,10 @@ all() -> groups() -> [{sup_start, [], [sup_start_normal, sup_start_ignore_init, - sup_start_ignore_child, sup_start_error_return, - sup_start_fail]}, + sup_start_ignore_child, sup_start_ignore_temporary_child, + sup_start_ignore_temporary_child_start_child, + sup_start_ignore_temporary_child_start_child_simple, + sup_start_error_return, sup_start_fail]}, {sup_stop, [], [sup_stop_infinity, sup_stop_timeout, sup_stop_brutal_kill]}, @@ -191,6 +195,59 @@ sup_start_ignore_child(Config) when is_list(Config) -> [2,1,0,2] = get_child_counts(sup_test). %%------------------------------------------------------------------------- +%% Tests what happens if child's init-callback returns ignore for a +%% temporary child when ChildSpec is returned directly from supervisor +%% init callback. +%% Child spec shall NOT be saved!!! +sup_start_ignore_temporary_child(Config) when is_list(Config) -> + process_flag(trap_exit, true), + Child1 = {child1, {supervisor_1, start_child, [ignore]}, + temporary, 1000, worker, []}, + Child2 = {child2, {supervisor_1, start_child, []}, temporary, + 1000, worker, []}, + {ok, _Pid} = start_link({ok, {{one_for_one, 2, 3600}, [Child1,Child2]}}), + + [{child2, CPid2, worker, []}] = supervisor:which_children(sup_test), + true = is_pid(CPid2), + [1,1,0,1] = get_child_counts(sup_test). + +%%------------------------------------------------------------------------- +%% Tests what happens if child's init-callback returns ignore for a +%% temporary child when child is started with start_child/2. +%% Child spec shall NOT be saved!!! +sup_start_ignore_temporary_child_start_child(Config) when is_list(Config) -> + process_flag(trap_exit, true), + {ok, _Pid} = start_link({ok, {{one_for_one, 2, 3600}, []}}), + Child1 = {child1, {supervisor_1, start_child, [ignore]}, + temporary, 1000, worker, []}, + Child2 = {child2, {supervisor_1, start_child, []}, temporary, + 1000, worker, []}, + + {ok, undefined} = supervisor:start_child(sup_test, Child1), + {ok, CPid2} = supervisor:start_child(sup_test, Child2), + + [{child2, CPid2, worker, []}] = supervisor:which_children(sup_test), + [1,1,0,1] = get_child_counts(sup_test). + +%%------------------------------------------------------------------------- +%% Tests what happens if child's init-callback returns ignore for a +%% temporary child when child is started with start_child/2, and the +%% supervisor is simple_one_for_one. +%% Child spec shall NOT be saved!!! +sup_start_ignore_temporary_child_start_child_simple(Config) + when is_list(Config) -> + process_flag(trap_exit, true), + Child1 = {child1, {supervisor_1, start_child, [ignore]}, + temporary, 1000, worker, []}, + {ok, _Pid} = start_link({ok, {{simple_one_for_one, 2, 3600}, [Child1]}}), + + {ok, undefined} = supervisor:start_child(sup_test, []), + {ok, CPid2} = supervisor:start_child(sup_test, []), + + [{undefined, CPid2, worker, []}] = supervisor:which_children(sup_test), + [1,1,0,1] = get_child_counts(sup_test). + +%%------------------------------------------------------------------------- %% Tests what happens if init-callback returns a invalid value. sup_start_error_return(Config) when is_list(Config) -> process_flag(trap_exit, true), diff --git a/lib/stdlib/vsn.mk b/lib/stdlib/vsn.mk index 2f0ecd3863..694d39ce9c 100644 --- a/lib/stdlib/vsn.mk +++ b/lib/stdlib/vsn.mk @@ -1 +1 @@ -STDLIB_VSN = 1.18 +STDLIB_VSN = 1.18.1 diff --git a/lib/syntax_tools/src/Makefile b/lib/syntax_tools/src/Makefile index 50369e633e..bac138e95a 100644 --- a/lib/syntax_tools/src/Makefile +++ b/lib/syntax_tools/src/Makefile @@ -26,7 +26,7 @@ EBIN = ../ebin ifeq ($(NATIVE_LIBS_ENABLED),yes) ERL_COMPILE_FLAGS += +native endif -ERL_COMPILE_FLAGS += +warn_unused_vars +nowarn_shadow_vars +warn_unused_import +warn_missing_spec +warn_untyped_record +ERL_COMPILE_FLAGS += +warn_unused_vars +nowarn_shadow_vars +warn_unused_import # +warn_missing_spec +warn_untyped_record SOURCES=erl_syntax.erl erl_prettypr.erl erl_syntax_lib.erl \ erl_comment_scan.erl erl_recomment.erl erl_tidy.erl \ diff --git a/lib/syntax_tools/src/erl_syntax.erl b/lib/syntax_tools/src/erl_syntax.erl index 7f58fda519..32fd3722d6 100644 --- a/lib/syntax_tools/src/erl_syntax.erl +++ b/lib/syntax_tools/src/erl_syntax.erl @@ -6100,8 +6100,9 @@ implicit_fun_name(Node) -> arity_qualifier( set_pos(atom(Atom), Pos), set_pos(integer(Arity), Pos))); - {'fun', Pos, {function, Module, Atom, Arity}} -> + {'fun', _Pos, {function, Module, Atom, Arity}} -> %% New in R15: fun M:F/A. + %% XXX: Perhaps set position for this as well? module_qualifier(Module, arity_qualifier(Atom, Arity)); Node1 -> data(Node1) diff --git a/lib/tools/c_src/erl_memory.c b/lib/tools/c_src/erl_memory.c index 872d55e789..5239176d03 100644 --- a/lib/tools/c_src/erl_memory.c +++ b/lib/tools/c_src/erl_memory.c @@ -1224,7 +1224,7 @@ print_main_footer(em_state *state) switch (state->info.stop_reason) { case EMTP_STOP: - p += sprintf(p, stop_str); + p += sprintf(p, "%s", stop_str); break; case EMTP_EXIT: p += sprintf(p, exit_str, state->info.exit_status); @@ -2339,7 +2339,7 @@ usage(char *sw, char *error) if (error) exit(1); else { - char *help_str = + fprintf(filep, "\n" " [] - switch is allowed any number of times\n" " {} - switch is allowed at most one time\n" @@ -2370,8 +2370,7 @@ usage(char *sw, char *error) " " SW_CHAR "o - display operation count values\n" " " SW_CHAR "p <P> - set listen port to <P>\n" " " SW_CHAR "t - display info about total values\n" - " " SW_CHAR "v - verbose output\n"; - fprintf(filep, help_str); + " " SW_CHAR "v - verbose output\n"); exit(0); } diff --git a/lib/xmerl/src/xmerl_uri.erl b/lib/xmerl/src/xmerl_uri.erl index a0c6f1c2a7..1864651491 100644 --- a/lib/xmerl/src/xmerl_uri.erl +++ b/lib/xmerl/src/xmerl_uri.erl @@ -358,7 +358,7 @@ scan_host(C0) -> %% Hex3=<?HEX; %% Hex4=<?HEX -> %% {C1,lists:reverse(lists:append(IPv6address))}; - {C1,Hostname,[A|_HostF]} -> + {C1,Hostname,[_A|_HostF]} -> {C1,lists:reverse(lists:append(Hostname))} %% _ -> %% {error,no_host} |