diff options
Diffstat (limited to 'lib')
94 files changed, 1517 insertions, 1212 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/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/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl index 85346762ac..6cab40d49d 100644 --- a/lib/kernel/test/file_SUITE.erl +++ b/lib/kernel/test/file_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2011. All Rights Reserved. +%% Copyright Ericsson AB 1996-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 @@ -78,7 +78,7 @@ -export([altname/1]). --export([large_file/1]). +-export([large_file/1, large_write/1]). -export([read_line_1/1, read_line_2/1, read_line_3/1,read_line_4/1]). @@ -92,6 +92,8 @@ -export([bytes/2, iterate/3]). +%% System probe functions that might be handy to check from the shell +-export([unix_free/1, memsize/0, bsd_memsize/1]). -include_lib("test_server/include/test_server.hrl"). -include_lib("kernel/include/file.hrl"). @@ -106,7 +108,7 @@ all() -> {group, compression}, {group, links}, copy, delayed_write, read_ahead, segment_read, segment_write, ipread, pid2name, interleaved_read_write, otp_5814, - large_file, read_line_1, read_line_2, read_line_3, + large_file, large_write, read_line_1, read_line_2, read_line_3, read_line_4, standard_io]. groups() -> @@ -394,6 +396,7 @@ make_del_dir(Config) when is_list(Config) -> %% Don't worry ;-) the parent directory should never be empty, right? ?line case ?FILE_MODULE:del_dir('..') of {error, eexist} -> ok; + {error, eacces} -> ok; %OpenBSD {error, einval} -> ok %FreeBSD end, ?line {error, enoent} = ?FILE_MODULE:del_dir(""), @@ -3287,50 +3290,13 @@ large_file(suite) -> large_file(doc) -> ["Tests positioning in large files (> 4G)"]; large_file(Config) when is_list(Config) -> - case {os:type(),os:version()} of - {{win32,nt},_} -> - do_large_file(Config); - {{unix,sunos},{A,B,C}} - when A == 5, B == 5, C >= 1; A == 5, B >= 6; A >= 6 -> - do_large_file(Config); - {{unix,Unix},_} when Unix =/= sunos -> - N = unix_free(Config), - io:format("Free: ~w KByte~n", [N]), - if N < 5 * (1 bsl 20) -> - %% Less than 5 GByte free - {skipped,"Less than 5 GByte free"}; - true -> - do_large_file(Config) - end; - _ -> - {skipped,"Only supported on Win32, Unix or SunOS >= 5.5.1"} - end. + run_large_file_test(Config, + fun(Name) -> do_large_file(Name) end, + "_large_file"). -unix_free(Config) -> - Cmd = ["df -k '",?config(priv_dir, Config),"'"], - DF0 = os:cmd(Cmd), - io:format("$ ~s~n~s", [Cmd,DF0]), - [$\n|DF1] = lists:dropwhile(fun ($\n) -> false; (_) -> true end, DF0), - {ok,[N],_} = io_lib:fread(" ~*s ~d", DF1), - N. +do_large_file(Name) -> + ?line Watchdog = ?t:timetrap(?t:minutes(20)), -do_large_file(Config) -> - ?line Watchdog = ?t:timetrap(?t:minutes(5)), - %% - ?line Name = filename:join(?config(priv_dir, Config), - ?MODULE_STRING ++ "_large_file"), - ?line Tester = self(), - Deleter = - spawn( - fun() -> - Mref = erlang:monitor(process, Tester), - receive - {'DOWN',Mref,_,_,_} -> ok; - {Tester,done} -> ok - end, - ?FILE_MODULE:delete(Name) - end), - %% ?line S = "1234567890", L = length(S), R = lists:reverse(S), @@ -3366,15 +3332,36 @@ do_large_file(Config) -> ?line {ok,R} = ?FILE_MODULE:read(F1, L+1), ?line ok = ?FILE_MODULE:close(F1), %% - ?line Mref = erlang:monitor(process, Deleter), - ?line Deleter ! {Tester,done}, - ?line receive {'DOWN',Mref,_,_,_} -> ok end, - %% ?line ?t:timetrap_cancel(Watchdog), ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +large_write(Config) when is_list(Config) -> + run_large_file_test(Config, + fun(Name) -> do_large_write(Name) end, + "_large_write"). + +do_large_write(Name) -> + Memsize = memsize(), + io:format("Memsize = ~w Bytes~n", [Memsize]), + case {erlang:system_info(wordsize),Memsize} of + {4,_} -> + {skip,"Needs a 64-bit emulator"}; + {8,N} when N < 6 bsl 30 -> + {skip, + "This machine has < 6 GB memory: " + ++integer_to_list(N)}; + {8,_} -> + Size = 4*1024*1024*1024+1, + Bin = <<0:Size/unit:8>>, + ok = file:write_file(Name, Bin), + {ok,#file_info{size=Size}} = file:read_file_info(Name), + ok + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + response_analysis(Module, Function, Arguments) -> @@ -3950,3 +3937,110 @@ flush(Msgs) -> after 0 -> lists:reverse(Msgs) end. + +%%% +%%% Support for testing large files. +%%% + +run_large_file_test(Config, Run, Name) -> + case {os:type(),os:version()} of + {{win32,nt},_} -> + do_run_large_file_test(Config, Run, Name); + {{unix,sunos},OsVersion} when OsVersion < {5,5,1} -> + {skip,"Only supported on Win32, Unix or SunOS >= 5.5.1"}; + {{unix,_},_} -> + N = unix_free(?config(priv_dir, Config)), + io:format("Free disk: ~w KByte~n", [N]), + if N < 5 * (1 bsl 20) -> + %% Less than 5 GByte free + {skip,"Less than 5 GByte free"}; + true -> + do_run_large_file_test(Config, Run, Name) + end; + _ -> + {skip,"Only supported on Win32, Unix or SunOS >= 5.5.1"} + end. + + +do_run_large_file_test(Config, Run, Name0) -> + Name = filename:join(?config(priv_dir, Config), + ?MODULE_STRING ++ Name0), + + %% Set up a process that will delete this file. + Tester = self(), + Deleter = + spawn( + fun() -> + Mref = erlang:monitor(process, Tester), + receive + {'DOWN',Mref,_,_,_} -> ok; + {Tester,done} -> ok + end, + ?FILE_MODULE:delete(Name) + end), + + %% Run the test case. + Res = Run(Name), + + %% Delete file and finish deleter process. + Mref = erlang:monitor(process, Deleter), + Deleter ! {Tester,done}, + receive {'DOWN',Mref,_,_,_} -> ok end, + + Res. + +unix_free(Path) -> + Cmd = ["df -k '",Path,"'"], + DF0 = os:cmd(Cmd), + io:format("$ ~s~n~s", [Cmd,DF0]), + Lines = re:split(DF0, "\n", [trim,{return,list}]), + Last = lists:last(Lines), + RE = "^[^\\s]*\\s+\\d+\\s+\\d+\\s+(\\d+)", + {match,[Avail]} = re:run(Last, RE, [{capture,all_but_first,list}]), + list_to_integer(Avail). + +memsize() -> + case os:type() of + {unix,openbsd} -> + bsd_memsize("hw.physmem"); + {unix,freebsd} -> + bsd_memsize("hw.physmem"); + {unix,darwin} -> + bsd_memsize("hw.memsize"); + {unix,linux} -> + Meminfo = os:cmd("cat /proc/meminfo"), + Re = "^MemTotal:\\s+(\\d+)\\s+kB\$", + ReOpts = [multiline,{capture,all_but_first,list}], + case re:run(Meminfo, Re, ReOpts) of + {match,[Str]} -> + list_to_integer(Str) bsl 10; + nomatch -> + 0 + end; + {win32,_} -> + enough; % atom() > integer(); assume (64-bit) windows have enough + _ -> + 0 + end. + +bsd_memsize(MIB) -> + Reply = os:cmd(["sysctl ",MIB]), + try strip_prefix(MIB, Reply) of + Str -> + Re = "^\\s*(?::|=)\\s*(\\d+)", + ReOpts = [{capture,all_but_first,list}], + case re:run(Str, Re, ReOpts) of + {match,[SizeStr]} -> + list_to_integer(SizeStr); + nomatch -> + 0 + end + catch + error:_ -> + 0 + end. + +strip_prefix([X|Prefix], [X|List]) -> + strip_prefix(Prefix, List); +strip_prefix([], List) -> + List. diff --git a/lib/kernel/test/inet_res_SUITE_data/run-named b/lib/kernel/test/inet_res_SUITE_data/run-named index 619e456b3f..211d2c7af7 100755 --- a/lib/kernel/test/inet_res_SUITE_data/run-named +++ b/lib/kernel/test/inet_res_SUITE_data/run-named @@ -2,7 +2,7 @@ ## ## %CopyrightBegin% ## -## Copyright Ericsson AB 2009-2011. All Rights Reserved. +## Copyright Ericsson AB 2009-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 @@ -159,17 +159,17 @@ echo "Command: $NAMED $NAMED_FG -c $CONF_FILE" $NAMED $NAMED_FG -c "$CONF_FILE" >"$LOG_FILE" 2>&1 </dev/null & NAMED_PID=$! echo "Pid: $NAMED_PID" -trap "kill -TERM $NAMED_PID >/dev/null 2>&1; wait $NAMED_PID >/dev/null 2>&1" \ +trap "kill $NAMED_PID >/dev/null 2>&1; wait $NAMED_PID >/dev/null 2>&1" \ 0 1 2 3 15 sleep 5 # Give name server time to load its zone files -if ps p $NAMED_PID; then +if ps -p $NAMED_PID >/dev/null 2>&1 || ps p $NAMED_PID >/dev/null 2>&1; then echo "Running: Enter \`\`quit'' to terminate nameserver[$NAMED_PID]..." while read LINE; do test :"$LINE" = :'quit' && break done + echo "Closing: Terminating nameserver..." else - wait $NAMED_PID; error "$NAMED failed to start" + error "$NAMED failed to start" fi -echo "Closing: Terminating nameserver..." diff --git a/lib/kernel/test/prim_file_SUITE.erl b/lib/kernel/test/prim_file_SUITE.erl index ccf26ee034..3e2202922c 100644 --- a/lib/kernel/test/prim_file_SUITE.erl +++ b/lib/kernel/test/prim_file_SUITE.erl @@ -52,6 +52,10 @@ list_dir_limit/1]). -export([advise/1]). +-export([large_write/1]). + +%% System probe functions that might be handy to check from the shell +-export([unix_free/1]). -include_lib("test_server/include/test_server.hrl"). -include_lib("kernel/include/file.hrl"). @@ -83,7 +87,7 @@ groups() -> cur_dir_1a, cur_dir_1b]}, {files, [], [{group, open}, {group, pos}, {group, file_info}, - truncate, sync, datasync, advise]}, + truncate, sync, datasync, advise, large_write]}, {open, [], [open1, modes, close, access, read_write, pread_write, append, exclusive]}, @@ -290,6 +294,7 @@ make_del_dir(Config, Handle, Suffix) -> %% Don't worry ;-) the parent directory should never be empty, right? ?line case ?PRIM_FILE_call(del_dir, Handle, [".."]) of {error, eexist} -> ok; + {error, eacces} -> ok; %OpenBSD {error, einval} -> ok %FreeBSD end, ?line {error, enoent} = ?PRIM_FILE_call(del_dir, Handle, [""]), @@ -1322,6 +1327,41 @@ advise(Config) when is_list(Config) -> ?line test_server:timetrap_cancel(Dog), ok. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +large_write(Config) when is_list(Config) -> + run_large_file_test(Config, + fun(Name) -> do_large_write(Name) end, + "_large_write"). + +do_large_write(Name) -> + Dog = test_server:timetrap(test_server:minutes(60)), + ChunkSize = (256 bsl 20) + 1, % 256 M + 1 + Chunks = 16, % times 16 -> 4 G + 16 + Base = 100, + Interleave = lists:seq(Base+1, Base+Chunks), + Chunk = <<0:ChunkSize/unit:8>>, + Data = zip_data(lists:duplicate(Chunks, Chunk), Interleave), + Size = Chunks * ChunkSize + Chunks, % 4 G + 32 + Wordsize = erlang:system_info(wordsize), + case prim_file:write_file(Name, Data) of + ok when Wordsize =:= 8 -> + {ok,#file_info{size=Size}} = file:read_file_info(Name), + {ok,Fd} = prim_file:open(Name, [read]), + check_large_write(Dog, Fd, ChunkSize, 0, Interleave); + {error,einval} when Wordsize =:= 4 -> + ok + end. + +check_large_write(Dog, Fd, ChunkSize, Pos, [X|Interleave]) -> + Pos1 = Pos + ChunkSize, + {ok,Pos1} = prim_file:position(Fd, {cur,ChunkSize}), + {ok,[X]} = prim_file:read(Fd, 1), + check_large_write(Dog, Fd, ChunkSize, Pos1+1, Interleave); +check_large_write(Dog, Fd, _, _, []) -> + eof = prim_file:read(Fd, 1), + test_server:timetrap_cancel(Dog), + ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -2044,3 +2084,70 @@ list_dir_limit_cleanup(Dir, Handle, N, Cnt) -> ?PRIM_FILE:delete(Handle, filename:join(Dir, Name)), list_dir_limit_cleanup(Dir, Handle, N, Cnt+1). +%%% +%%% Support for testing large files. +%%% + +run_large_file_test(Config, Run, Name) -> + case {os:type(),os:version()} of + {{win32,nt},_} -> + do_run_large_file_test(Config, Run, Name); + {{unix,sunos},OsVersion} when OsVersion < {5,5,1} -> + {skip,"Only supported on Win32, Unix or SunOS >= 5.5.1"}; + {{unix,_},_} -> + N = unix_free(?config(priv_dir, Config)), + io:format("Free disk: ~w KByte~n", [N]), + if N < 5 bsl 20 -> + %% Less than 5 GByte free + {skip,"Less than 5 GByte free disk"}; + true -> + do_run_large_file_test(Config, Run, Name) + end; + _ -> + {skip,"Only supported on Win32, Unix or SunOS >= 5.5.1"} + end. + + +do_run_large_file_test(Config, Run, Name0) -> + Name = filename:join(?config(priv_dir, Config), + ?MODULE_STRING ++ Name0), + + %% Set up a process that will delete this file. + Tester = self(), + Deleter = + spawn( + fun() -> + Mref = erlang:monitor(process, Tester), + receive + {'DOWN',Mref,_,_,_} -> ok; + {Tester,done} -> ok + end, + prim_file:delete(Name) + end), + + %% Run the test case. + Res = Run(Name), + + %% Delete file and finish deleter process. + Mref = erlang:monitor(process, Deleter), + Deleter ! {Tester,done}, + receive {'DOWN',Mref,_,_,_} -> ok end, + + Res. + +unix_free(Path) -> + Cmd = ["df -k '",Path,"'"], + DF0 = os:cmd(Cmd), + io:format("$ ~s~n~s", [Cmd,DF0]), + Lines = re:split(DF0, "\n", [trim,{return,list}]), + Last = lists:last(Lines), + RE = "^[^\\s]*\\s+\\d+\\s+\\d+\\s+(\\d+)", + {match,[Avail]} = re:run(Last, RE, [{capture,all_but_first,list}]), + list_to_integer(Avail). + +zip_data([A|As], [B|Bs]) -> + [[A,B]|zip_data(As, Bs)]; +zip_data([], Bs) -> + Bs; +zip_data(As, []) -> + As. 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/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml index 64a0d1a13f..071b16a8f6 100644 --- a/lib/snmp/doc/src/notes.xml +++ b/lib/snmp/doc/src/notes.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>1996</year><year>2011</year> + <year>1996</year><year>2012</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -34,7 +34,71 @@ <section> + <title>SNMP Development Toolkit 4.21.5</title> + <p>Version 4.21.5 supports code replacement in runtime from/to + version 4.21.4, 4.21.3, 4.21.2, 4.21.1, 4.21, 4.20.1 and 4.20. </p> + + <section> + <title>Improvements and new features</title> +<!-- + <p>-</p> +--> + + <list type="bulleted"> + <item> + <p>[agent] Removed (more) use of old style tuple funs. </p> + <p>Own Id: OTP-9783</p> + </item> + + </list> + + </section> + + <section> + <title>Fixed Bugs and Malfunctions</title> +<!-- + <p>-</p> +--> + + <list type="bulleted"> + <item> + <p>[agent] Repeated vacm table dumping fails due to file name + conflict. When dumping the vacm table to disk, a temoporary + file with a fixed name was used. If the table dumping + (snmpa_vacm:dump_table/0) was initiated from several different + processes in rapid succesion, the dumping could fail because the + different processes was simultaniously trying to write to the + same file. This problem has been eliminated by creating a unique + name for the temporary file. </p> + <p>Own Id: OTP-9851</p> + <p>Aux Id: Seq 11980</p> + </item> + + </list> + </section> + + <section> + <title>Incompatibilities</title> + <p>-</p> + +<!-- + <list type="bulleted"> + <item> + <p>foo. </p> + <p>Own Id: OTP-9718</p> + </item> + + </list> +--> + + </section> + + </section> <!-- 4.21.5 --> + + + <section> <title>SNMP Development Toolkit 4.21.4</title> + <p>This version has never been released for R14B.</p> <p>Version 4.21.4 supports code replacement in runtime from/to version 4.21.3, 4.21.2, 4.21.1, 4.21, 4.20.1, 4.20 and 4.19. </p> @@ -46,7 +110,7 @@ <list type="bulleted"> <item> <p>[compiler] Improved version info printout from the - <seealso marker="snmpc(command)#">MIB compiler frontend escript</seealso>. </p> + <seealso marker="snmpc(command)#">MIB compiler frontend escript</seealso>. </p> <p>Own Id: OTP-9618</p> </item> @@ -70,7 +134,6 @@ </list> </section> - <section> <title>Incompatibilities</title> <p>-</p> @@ -78,7 +141,7 @@ <!-- <list type="bulleted"> <item> - <p>foo. </p> + <p>foo. </p> <p>Own Id: OTP-9718</p> </item> @@ -989,7 +1052,6 @@ snmp_view_basec_acm_mib:vacmAccessTable(set, RowIndex, Cols). </section> <!-- 4.15 --> - <!-- section> <title>Release notes history</title> <p>For information about older versions see diff --git a/lib/snmp/doc/src/notes_history.xml b/lib/snmp/doc/src/notes_history.xml index e833335ffb..d0b912d0fe 100644 --- a/lib/snmp/doc/src/notes_history.xml +++ b/lib/snmp/doc/src/notes_history.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2004</year><year>2011</year> + <year>2004</year><year>2012</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/snmp/src/agent/snmp_generic_mnesia.erl b/lib/snmp/src/agent/snmp_generic_mnesia.erl index a73aad5b33..ce42af404b 100644 --- a/lib/snmp/src/agent/snmp_generic_mnesia.erl +++ b/lib/snmp/src/agent/snmp_generic_mnesia.erl @@ -121,7 +121,7 @@ table_func(set, RowIndex, Cols, Name) -> fun() -> snmp_generic:table_set_row( {Name, mnesia}, nofunc, - {snmp_generic_mnesia, table_try_make_consistent}, + fun table_try_make_consistent/2, RowIndex, Cols) end) of {atomic, Value} -> @@ -368,7 +368,8 @@ table_set_elements(Name, RowIndex, Cols) -> _ -> false end. table_set_elements(Name, RowIndex, Cols, ConsFunc) -> - #table_info{index_types = Indexes, first_own_index = FirstOwnIndex} = + #table_info{index_types = Indexes, + first_own_index = FirstOwnIndex} = snmp_generic:table_info(Name), AddCol = if FirstOwnIndex == 0 -> 2; diff --git a/lib/snmp/src/agent/snmp_view_based_acm_mib.erl b/lib/snmp/src/agent/snmp_view_based_acm_mib.erl index 37f6dd3f26..2cee91b081 100644 --- a/lib/snmp/src/agent/snmp_view_based_acm_mib.erl +++ b/lib/snmp/src/agent/snmp_view_based_acm_mib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2011. All Rights Reserved. +%% Copyright Ericsson AB 1999-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 @@ -203,18 +203,16 @@ init_sec2group_table([Row | T]) -> init_sec2group_table(T); init_sec2group_table([]) -> true. -init_access_table([{GN, Prefix, Model, Level, Row} | T]) -> -%% ?vtrace("init access table: " -%% "~n GN: ~p" -%% "~n Prefix: ~p" -%% "~n Model: ~p" -%% "~n Level: ~p" -%% "~n Row: ~p",[GN, Prefix, Model, Level, Row]), - Key = [length(GN) | GN] ++ [length(Prefix) | Prefix] ++ [Model, Level], - snmpa_vacm:insert([{Key, Row}], false), - init_access_table(T); -init_access_table([]) -> - snmpa_vacm:dump_table(). +make_access_key(GN, Prefix, Model, Level) -> + [length(GN) | GN] ++ [length(Prefix) | Prefix] ++ [Model, Level]. + +make_access_entry({GN, Prefix, Model, Level, Row}) -> + Key = make_access_key(GN, Prefix, Model, Level), + {Key, Row}. + +init_access_table(TableData) -> + TableData2 = [make_access_entry(E) || E <- TableData], + snmpa_vacm:insert(TableData2, true). init_view_table([Row | T]) -> %% ?vtrace("init view table: " @@ -276,10 +274,7 @@ add_access(GroupName, Prefix, SecModel, SecLevel, Match, RV, WV, NV) -> Match, RV, WV, NV}, case (catch check_vacm(Access)) of {ok, {vacmAccess, {GN, Pref, SM, SL, Row}}} -> - Key1 = [length(GN) | GN], - Key2 = [length(Pref) | Pref], - Key3 = [SM, SL], - Key = Key1 ++ Key2 ++ Key3, + Key = make_access_key(GN, Pref, SM, SL), snmpa_vacm:insert([{Key, Row}], false), snmpa_agent:invalidate_ca_cache(), {ok, Key}; diff --git a/lib/snmp/src/agent/snmpa_agent.erl b/lib/snmp/src/agent/snmpa_agent.erl index 46c634969d..d3eeca2290 100644 --- a/lib/snmp/src/agent/snmpa_agent.erl +++ b/lib/snmp/src/agent/snmpa_agent.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2011. All Rights Reserved. +%% Copyright Ericsson AB 1996-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 @@ -934,6 +934,7 @@ handle_info({'EXIT', Pid, Reason}, S) -> end, {noreply, S} end; + handle_info({'DOWN', Ref, process, Pid, {mibs_cache_reply, Reply}}, #state{mibs_cache_request = {Pid, Ref, From}} = S) -> ?vlog("reply from the mibs cache request handler (~p): ~n~p", @@ -1283,27 +1284,27 @@ handle_call({me_of, Oid}, _From, S) -> {reply, Reply, S}; handle_call(get_log_type, _From, S) -> - ?vlog("get_log_type", []), + ?vlog("handle_call(get_log_type) -> entry with", []), Reply = handle_get_log_type(S), {reply, Reply, S}; handle_call({set_log_type, NewType}, _From, S) -> - ?vlog("set_log_type -> " + ?vlog("handle_call(set_log_type) -> entry with" "~n NewType: ~p", [NewType]), Reply = handle_set_log_type(S, NewType), {reply, Reply, S}; handle_call(get_request_limit, _From, S) -> - ?vlog("get_request_limit", []), + ?vlog("handle_call(get_request_limit) -> entry with", []), Reply = handle_get_request_limit(S), {reply, Reply, S}; handle_call({set_request_limit, NewLimit}, _From, S) -> - ?vlog("set_request_limit -> " + ?vlog("handle_call(set_request_limit) -> entry with" "~n NewLimit: ~p", [NewLimit]), Reply = handle_set_request_limit(S, NewLimit), {reply, Reply, S}; - + handle_call(stop, _From, S) -> {stop, normal, ok, S}; @@ -3859,6 +3860,7 @@ mapfoldl(F, Eas, Accu0, [Hd|Tail]) -> {Accu2,[R|Rs]}; mapfoldl(_F, _Eas, Accu, []) -> {Accu,[]}. + %%----------------------------------------------------------------- %% Runtime debugging of the agent. %%----------------------------------------------------------------- @@ -3983,7 +3985,7 @@ handle_set_request_limit(_, _) -> {error, not_supported}. -agent_info(#state{worker = W, set_worker = SW}) -> +agent_info(#state{worker = W, set_worker = SW}) -> case (catch get_agent_info(W, SW)) of Info when is_list(Info) -> Info; diff --git a/lib/snmp/src/agent/snmpa_vacm.erl b/lib/snmp/src/agent/snmpa_vacm.erl index 892dc265f1..2cbc11d280 100644 --- a/lib/snmp/src/agent/snmpa_vacm.erl +++ b/lib/snmp/src/agent/snmpa_vacm.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2010. All Rights Reserved. +%% Copyright Ericsson AB 1999-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 @@ -266,9 +266,10 @@ dump_table(true) -> dump_table(_) -> ok. + dump_table() -> [{_, FName}] = ets:lookup(snmp_agent_table, snmpa_vacm_file), - TmpName = FName ++ ".tmp", + TmpName = unique_table_name(FName), case ets:tab2file(snmpa_vacm, TmpName) of ok -> case file:rename(TmpName, FName) of @@ -283,6 +284,35 @@ dump_table() -> [FName, Reason]) end. +%% This little thing is an attempt to create a "unique" filename +%% in order to minimize the risk of two processes at the same +%% time dumping the table. +unique_table_name(Pre) -> + %% We want something that is guaranteed to be unique, + %% therefor we use erlang:now() instead of os:timestamp() + unique_table_name(Pre, erlang:now()). + +unique_table_name(Pre, {_A, _B, C} = Now) -> + {Date, Time} = calendar:now_to_datetime(Now), + {YYYY, MM, DD} = Date, + {Hour, Min, Sec} = Time, + FormatDate = + io_lib:format("~.4w~.2.0w~.2.0w_~.2.0w~.2.0w~.2.0w_~w", + [YYYY, MM, DD, Hour, Min, Sec, round(C/1000)]), + unique_table_name2(Pre, FormatDate). + +unique_table_name2(Pre, FormatedDate) -> + PidPart = unique_table_name_pid(), + lists:flatten(io_lib:format("~s.~s~s.tmp", [Pre, PidPart, FormatedDate])). + +unique_table_name_pid() -> + case string:tokens(pid_to_list(self()), [$<,$.,$>]) of + [A, B, C] -> + A ++ B ++ C ++ "."; + _ -> + "" + end. + %%----------------------------------------------------------------- %% Alg. diff --git a/lib/snmp/src/app/snmp.appup.src b/lib/snmp/src/app/snmp.appup.src index 219ac62a73..589b728dc5 100644 --- a/lib/snmp/src/app/snmp.appup.src +++ b/lib/snmp/src/app/snmp.appup.src @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2011. All Rights Reserved. +%% Copyright Ericsson AB 1999-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 @@ -22,43 +22,65 @@ %% ----- U p g r a d e ------------------------------------------------------- [ + {"4.21.4", + [ + {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []}, + {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []}, + {load_module, snmpa_vacm, soft_purge, soft_purge, []}, + {update, snmpa_agent, soft, soft_purge, soft_purge, []} + ] + }, {"4.21.3", [ - {update, snmpa_local_db, soft, soft_purge, soft_purge, []} + {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []}, + {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []}, + {load_module, snmpa_vacm, soft_purge, soft_purge, []}, + {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, + {update, snmpa_agent, soft, soft_purge, soft_purge, []} ] }, {"4.21.2", [ + {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []}, + {load_module, snmpa_vacm, soft_purge, soft_purge, []}, {load_module, snmpa_mpd, soft_purge, soft_purge, []}, {load_module, snmpa_set_lib, soft_purge, soft_purge, []}, {load_module, snmpa_trap, soft_purge, soft_purge, []}, - {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, + {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []}, + {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, {update, snmpa_agent, soft, soft_purge, soft_purge, []} ] }, {"4.21.1", [ + {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []}, + {load_module, snmpa_vacm, soft_purge, soft_purge, []}, {load_module, snmpa_mpd, soft_purge, soft_purge, []}, {load_module, snmpa_set_lib, soft_purge, soft_purge, []}, {load_module, snmpa_trap, soft_purge, soft_purge, []}, - {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, + {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []}, + {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, {update, snmpa_agent, soft, soft_purge, soft_purge, []}, {update, snmp_note_store, soft, soft_purge, soft_purge, []} ] }, {"4.21", [ + {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []}, + {load_module, snmpa_vacm, soft_purge, soft_purge, []}, {load_module, snmpa_mpd, soft_purge, soft_purge, []}, {load_module, snmpa_set_lib, soft_purge, soft_purge, []}, {load_module, snmpa_trap, soft_purge, soft_purge, []}, {load_module, snmp_target_mib, soft_purge, soft_purge, []}, - {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, + {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []}, + {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, {update, snmpa_agent, soft, soft_purge, soft_purge, []}, {update, snmp_note_store, soft, soft_purge, soft_purge, []} ] }, {"4.20.1", [ + {load_module, snmpa_vacm, soft_purge, soft_purge, []}, {load_module, snmpa_set_lib, soft_purge, soft_purge, []}, {load_module, snmpa_trap, soft_purge, soft_purge, []}, {load_module, snmp_target_mib, soft_purge, soft_purge, []}, @@ -73,7 +95,8 @@ [snmp_conf, snmp_config]}, {load_module, snmpa_conf, soft_purge, soft_purge, [snmp_config]}, {update, snmp_note_store, soft, soft_purge, soft_purge, []}, - {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, + {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []}, + {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mpd]}, {update, snmpm_config, soft, soft_purge, soft_purge, [snmp_conf]}, {update, snmpm_server, soft, soft_purge, soft_purge, @@ -84,6 +107,7 @@ }, {"4.20", [ + {load_module, snmpa_vacm, soft_purge, soft_purge, []}, {load_module, snmpa_set_lib, soft_purge, soft_purge, []}, {load_module, snmpa_trap, soft_purge, soft_purge, []}, {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []}, @@ -98,7 +122,8 @@ [snmp_conf, snmp_config]}, {load_module, snmpa_conf, soft_purge, soft_purge, [snmp_config]}, {update, snmp_note_store, soft, soft_purge, soft_purge, []}, - {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, + {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []}, + {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mpd]}, {update, snmpm_config, soft, soft_purge, soft_purge, [snmp_conf]}, {update, snmpm_server, soft, soft_purge, soft_purge, @@ -106,93 +131,71 @@ {update, snmpm_net_if, soft, soft_purge, soft_purge, [snmp_conf, snmpm_mpd, snmpm_config]} ] - }, - {"4.19", - [ - {load_module, snmpa_set_lib, soft_purge, soft_purge, []}, - {load_module, snmpa, soft_purge, soft_purge, []}, - {load_module, snmpm, soft_purge, soft_purge, - [snmpm_server, snmpm_config, snmp_config]}, - {load_module, snmpa_usm, soft_purge, soft_purge, []}, - {load_module, snmpm_usm, soft_purge, soft_purge, []}, - {load_module, snmp_log, soft_purge, soft_purge, []}, - {load_module, snmp_pdus, soft_purge, soft_purge, []}, - {load_module, snmp_conf, soft_purge, soft_purge, []}, - {load_module, snmpa_conf, soft_purge, soft_purge, - [snmp_conf, snmp_config]}, - {load_module, snmp_misc, soft_purge, soft_purge, []}, - {load_module, snmp_config, soft_purge, soft_purge, []}, - {load_module, snmpa_mpd, soft_purge, soft_purge, - [snmp_conf, snmp_config]}, - {load_module, snmpm_mpd, soft_purge, soft_purge, - [snmp_conf, snmp_config, snmpm_config]}, - {load_module, snmpa_trap, soft_purge, soft_purge, - [snmpa_mpd, snmp_notification_mib, snmp_target_mib, snmpa_net_if]}, - {load_module, snmpa_acm, soft_purge, soft_purge, - [snmp_conf, snmpa_mpd, snmp_target_mib]}, - {load_module, snmpa_conf, soft_purge, soft_purge, - [snmp_config, snmp_notification_mib]}, - {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []}, - {load_module, snmp_notification_mib, soft_purge, soft_purge, - [snmp_conf, snmp_target_mib]}, - {load_module, snmp_community_mib, soft_purge, soft_purge, []}, - {load_module, snmp_target_mib, soft_purge, soft_purge, - [snmp_conf]}, - {update, snmp_note_store, soft, soft_purge, soft_purge, []}, - {update, snmpm_net_if, soft, soft_purge, soft_purge, - [snmp_conf, snmpm_mpd, snmpm_config]}, - {update, snmpm_config, soft, soft_purge, soft_purge, [snmp_conf]}, - {update, snmpm_server, soft, soft_purge, soft_purge, - [snmpm_net_if, snmpm_mpd, snmpm_config]}, - {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, - {update, snmpa_net_if, soft, soft_purge, soft_purge, - [snmp_conf, snmpa_mpd]}, - {update, snmpa_agent, soft, soft_purge, soft_purge, - [snmpa_acm, snmpa_mpd, snmpa_trap]} - ] } ], %% ------D o w n g r a d e --------------------------------------------------- [ + {"4.21.4", + [ + {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []}, + {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []}, + {load_module, snmpa_vacm, soft_purge, soft_purge, []}, + {update, snmpa_agent, soft, soft_purge, soft_purge, []} + ] + }, {"4.21.3", [ - {update, snmpa_local_db, soft, soft_purge, soft_purge, []} + {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []}, + {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []}, + {load_module, snmpa_vacm, soft_purge, soft_purge, []}, + {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, + {update, snmpa_agent, soft, soft_purge, soft_purge, []} ] }, {"4.21.2", [ + {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []}, + {load_module, snmpa_vacm, soft_purge, soft_purge, []}, {load_module, snmpa_mpd, soft_purge, soft_purge, []}, {load_module, snmpa_set_lib, soft_purge, soft_purge, []}, {load_module, snmpa_trap, soft_purge, soft_purge, []}, - {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, + {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []}, + {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, {update, snmpa_agent, soft, soft_purge, soft_purge, []} ] }, {"4.21.1", [ + {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []}, + {load_module, snmpa_vacm, soft_purge, soft_purge, []}, {load_module, snmpa_mpd, soft_purge, soft_purge, []}, {load_module, snmpa_set_lib, soft_purge, soft_purge, []}, {load_module, snmpa_trap, soft_purge, soft_purge, []}, - {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, + {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []}, + {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, {update, snmpa_agent, soft, soft_purge, soft_purge, []}, {update, snmp_note_store, soft, soft_purge, soft_purge, []} ] }, {"4.21", [ + {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []}, + {load_module, snmpa_vacm, soft_purge, soft_purge, []}, {load_module, snmpa_mpd, soft_purge, soft_purge, []}, {load_module, snmpa_set_lib, soft_purge, soft_purge, []}, {load_module, snmpa_trap, soft_purge, soft_purge, []}, {load_module, snmp_target_mib, soft_purge, soft_purge, []}, - {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, + {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []}, + {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, {update, snmpa_agent, soft, soft_purge, soft_purge, []}, {update, snmp_note_store, soft, soft_purge, soft_purge, []} ] }, {"4.20.1", [ + {load_module, snmpa_vacm, soft_purge, soft_purge, []}, {load_module, snmpa_set_lib, soft_purge, soft_purge, []}, {load_module, snmpa_trap, soft_purge, soft_purge, []}, {load_module, snmp_target_mib, soft_purge, soft_purge, []}, @@ -207,7 +210,8 @@ [snmp_conf, snmp_config]}, {load_module, snmpa_conf, soft_purge, soft_purge, [snmp_config]}, {update, snmp_note_store, soft, soft_purge, soft_purge, []}, - {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, + {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []}, + {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mpd]}, {update, snmpm_config, soft, soft_purge, soft_purge, [snmp_conf]}, {update, snmpm_server, soft, soft_purge, soft_purge, @@ -218,6 +222,7 @@ }, {"4.20", [ + {load_module, snmpa_vacm, soft_purge, soft_purge, []}, {load_module, snmpa_set_lib, soft_purge, soft_purge, []}, {load_module, snmpa_trap, soft_purge, soft_purge, []}, {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []}, @@ -232,7 +237,8 @@ [snmp_conf, snmp_config]}, {load_module, snmpa_conf, soft_purge, soft_purge, [snmp_config]}, {update, snmp_note_store, soft, soft_purge, soft_purge, []}, - {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, + {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []}, + {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mpd]}, {update, snmpm_config, soft, soft_purge, soft_purge, [snmp_conf]}, {update, snmpm_server, soft, soft_purge, soft_purge, @@ -240,50 +246,6 @@ {update, snmpm_net_if, soft, soft_purge, soft_purge, [snmp_conf, snmpm_mpd, snmpm_config]} ] - }, - {"4.19", - [ - {load_module, snmpa_set_lib, soft_purge, soft_purge, []}, - {load_module, snmpa, soft_purge, soft_purge, []}, - {load_module, snmpm, soft_purge, soft_purge, - [snmpm_server, snmpm_config, snmp_config]}, - {load_module, snmpa_usm, soft_purge, soft_purge, []}, - {load_module, snmpm_usm, soft_purge, soft_purge, []}, - {load_module, snmp_log, soft_purge, soft_purge, []}, - {load_module, snmp_pdus, soft_purge, soft_purge, []}, - {load_module, snmp_conf, soft_purge, soft_purge, []}, - {load_module, snmpa_conf, soft_purge, soft_purge, - [snmp_conf, snmp_config]}, - {load_module, snmp_misc, soft_purge, soft_purge, []}, - {load_module, snmp_config, soft_purge, soft_purge, []}, - {load_module, snmpa_mpd, soft_purge, soft_purge, - [snmp_conf, snmp_config]}, - {load_module, snmpm_mpd, soft_purge, soft_purge, - [snmp_conf, snmp_config, snmpm_config]}, - {load_module, snmpa_trap, soft_purge, soft_purge, - [snmpa_mpd, snmp_notification_mib, snmp_target_mib, snmpa_net_if]}, - {load_module, snmpa_acm, soft_purge, soft_purge, - [snmp_conf, snmpa_mpd, snmp_target_mib]}, - {load_module, snmpa_conf, soft_purge, soft_purge, - [snmp_config, snmp_notification_mib]}, - {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []}, - {load_module, snmp_notification_mib, soft_purge, soft_purge, - [snmp_conf, snmp_target_mib]}, - {load_module, snmp_community_mib, soft_purge, soft_purge, []}, - {load_module, snmp_target_mib, soft_purge, soft_purge, - [snmp_conf]}, - {update, snmp_note_store, soft, soft_purge, soft_purge, []}, - {update, snmpm_net_if, soft, soft_purge, soft_purge, - [snmp_conf, snmpm_mpd, snmpm_config]}, - {update, snmpm_config, soft, soft_purge, soft_purge, [snmp_conf]}, - {update, snmpm_server, soft, soft_purge, soft_purge, - [snmpm_net_if, snmpm_mpd, snmpm_config]}, - {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, - {update, snmpa_net_if, soft, soft_purge, soft_purge, - [snmp_conf, snmpa_mpd]}, - {update, snmpa_agent, soft, soft_purge, soft_purge, - [snmpa_acm, snmpa_mpd, snmpa_trap]} - ] } ] }. diff --git a/lib/snmp/test/snmp_compiler_test.erl b/lib/snmp/test/snmp_compiler_test.erl index c964b08168..0a147130b0 100644 --- a/lib/snmp/test/snmp_compiler_test.erl +++ b/lib/snmp/test/snmp_compiler_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2011. All Rights Reserved. +%% Copyright Ericsson AB 2003-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 @@ -566,14 +566,7 @@ p(F, A) -> p(TName, F, A) -> io:format("*** [~w][~s] ***" - "~n" ++ F ++ "~n", [TName,format_timestamp(now())|A]). - -format_timestamp({_N1, _N2, N3} = Now) -> - {Date, Time} = calendar:now_to_datetime(Now), - {YYYY,MM,DD} = Date, - {Hour,Min,Sec} = Time, - FormatDate = - io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w", - [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]), - lists:flatten(FormatDate). + "~n" ++ F ++ "~n", [TName, formated_timestamp()|A]). +formated_timestamp() -> + snmp_test_lib:formated_timestamp(). diff --git a/lib/snmp/test/snmp_manager_config_test.erl b/lib/snmp/test/snmp_manager_config_test.erl index 4498d506f3..3192fe1b40 100644 --- a/lib/snmp/test/snmp_manager_config_test.erl +++ b/lib/snmp/test/snmp_manager_config_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2011. All Rights Reserved. +%% Copyright Ericsson AB 2004-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 @@ -2726,14 +2726,7 @@ p(F, A) -> p(TName, F, A) -> io:format("*** [~s] ***" - " ~w -> " ++ F ++ "~n", [format_timestamp(now()),TName|A]). - -format_timestamp({_N1, _N2, N3} = Now) -> - {Date, Time} = calendar:now_to_datetime(Now), - {YYYY,MM,DD} = Date, - {Hour,Min,Sec} = Time, - FormatDate = - io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w", - [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]), - lists:flatten(FormatDate). + " ~w -> " ++ F ++ "~n", [formated_timestamp(),TName|A]). +formated_timestamp() -> + snmp_test_lib:formated_timestamp(). diff --git a/lib/snmp/test/snmp_manager_test.erl b/lib/snmp/test/snmp_manager_test.erl index d18f20d359..75c9f7b277 100644 --- a/lib/snmp/test/snmp_manager_test.erl +++ b/lib/snmp/test/snmp_manager_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2011. All Rights Reserved. +%% Copyright Ericsson AB 2003-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 @@ -6064,7 +6064,7 @@ rcall(Node, Mod, Func, Args) -> %% Time in milli sec %% t() -> -%% {A,B,C} = erlang:now(), +%% {A,B,C} = os:timestamp(), %% A*1000000000+B*1000+(C div 1000). @@ -6078,16 +6078,10 @@ p(F, A) -> p(TName, F, A) -> io:format("*** [~w][~s] ***" - "~n" ++ F ++ "~n", [TName,format_timestamp(now())|A]). - -format_timestamp({_N1, _N2, N3} = Now) -> - {Date, Time} = calendar:now_to_datetime(Now), - {YYYY,MM,DD} = Date, - {Hour,Min,Sec} = Time, - FormatDate = - io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w", - [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]), - lists:flatten(FormatDate). + "~n" ++ F ++ "~n", [TName, formated_timestamp()|A]). + +formated_timestamp() -> + snmp_test_lib:formated_timestamp(). %% p(TName, F, A) -> %% io:format("~w -> " ++ F ++ "~n", [TName|A]). diff --git a/lib/snmp/test/snmp_test_lib.erl b/lib/snmp/test/snmp_test_lib.erl index 54839d989b..e4d58a1253 100644 --- a/lib/snmp/test/snmp_test_lib.erl +++ b/lib/snmp/test/snmp_test_lib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2002-2010. All Rights Reserved. +%% Copyright Ericsson AB 2002-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 @@ -37,7 +37,7 @@ -export([watchdog/3, watchdog_start/1, watchdog_start/2, watchdog_stop/1]). -export([del_dir/1]). -export([cover/1]). --export([p/2, print/5]). +-export([p/2, print/5, formated_timestamp/0]). %% ---------------------------------------------------------------------- @@ -521,15 +521,18 @@ p(F, A) when is_list(F) andalso is_list(A) -> print(Prefix, Module, Line, Format, Args) -> io:format("*** [~s] ~s ~p ~p ~p:~p *** " ++ Format ++ "~n", - [format_timestamp(now()), + [formated_timestamp(), Prefix, node(), self(), Module, Line|Args]). +formated_timestamp() -> + format_timestamp(os:timestamp()). + format_timestamp({_N1, _N2, N3} = Now) -> {Date, Time} = calendar:now_to_datetime(Now), {YYYY,MM,DD} = Date, {Hour,Min,Sec} = Time, FormatDate = - io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w", + io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w ~w", [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]), lists:flatten(FormatDate). diff --git a/lib/snmp/test/snmp_test_mgr.erl b/lib/snmp/test/snmp_test_mgr.erl index 84bdc6b04f..499cf7abcf 100644 --- a/lib/snmp/test/snmp_test_mgr.erl +++ b/lib/snmp/test/snmp_test_mgr.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2010. All Rights Reserved. +%% Copyright Ericsson AB 1996-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 @@ -1124,16 +1124,11 @@ d(F,A) -> d(get(debug),F,A). d(true,F,A) -> io:format("*** [~s] MGR_DBG *** " ++ F ++ "~n", - [format_timestamp(now())|A]); + [formated_timestamp()|A]); d(_,_F,_A) -> ok. -format_timestamp({_N1, _N2, N3} = Now) -> - {Date, Time} = calendar:now_to_datetime(Now), - {YYYY,MM,DD} = Date, - {Hour,Min,Sec} = Time, - FormatDate = - io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w", - [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]), - lists:flatten(FormatDate). + +formated_timestamp() -> + snmp_test_lib:formated_timestamp(). diff --git a/lib/snmp/test/snmp_test_mgr_misc.erl b/lib/snmp/test/snmp_test_mgr_misc.erl index fc6dedd96d..5525c5c3ec 100644 --- a/lib/snmp/test/snmp_test_mgr_misc.erl +++ b/lib/snmp/test/snmp_test_mgr_misc.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2011. All Rights Reserved. +%% Copyright Ericsson AB 1996-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 @@ -779,16 +779,9 @@ d(F,A) -> d(get(debug),F,A). d(true,F,A) -> io:format("*** [~s] MGR_PS_DBG *** " ++ F ++ "~n", - [format_timestamp(now())|A]); + [formated_timestamp()|A]); d(_,_F,_A) -> ok. -format_timestamp({_N1, _N2, N3} = Now) -> - {Date, Time} = calendar:now_to_datetime(Now), - {YYYY,MM,DD} = Date, - {Hour,Min,Sec} = Time, - FormatDate = - io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w", - [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]), - lists:flatten(FormatDate). - +formated_timestamp() -> + snmp_test_lib:formated_timestamp(). diff --git a/lib/snmp/vsn.mk b/lib/snmp/vsn.mk index ee2e633c69..dafdcefe79 100644 --- a/lib/snmp/vsn.mk +++ b/lib/snmp/vsn.mk @@ -2,7 +2,7 @@ # %CopyrightBegin% # -# Copyright Ericsson AB 1997-2011. All Rights Reserved. +# Copyright Ericsson AB 1997-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 @@ -18,6 +18,6 @@ # %CopyrightEnd% APPLICATION = snmp -SNMP_VSN = 4.21.4 +SNMP_VSN = 4.21.5 PRE_VSN = APP_VSN = "$(APPLICATION)-$(SNMP_VSN)$(PRE_VSN)" diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl index 5ea0d98980..73b60057cc 100644 --- a/lib/ssh/test/ssh_basic_SUITE.erl +++ b/lib/ssh/test/ssh_basic_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2011. All Rights Reserved. +%% Copyright Ericsson AB 2008-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 @@ -41,9 +41,20 @@ init_per_suite(Config) -> case catch crypto:start() of ok -> - Dir = ?config(priv_dir, Config), - {ok, _} = ssh_test_lib:get_id_keys(Dir), - ssh_test_lib:make_dsa_files(Config), + DataDir = ?config(data_dir, Config), + UserDir = ?config(priv_dir, Config), + ssh_test_lib:copyfile(DataDir, UserDir, "id_rsa"), + ssh_test_lib:copyfile(DataDir, UserDir, "id_dsa"), + RSAFile = filename:join(DataDir, "id_rsa.pub"), + DSAFile = filename:join(DataDir, "id_dsa.pub"), + {ok, Ssh1} = file:read_file(RSAFile), + {ok, Ssh2} = file:read_file(DSAFile), + [{RSA, _}] = public_key:ssh_decode(Ssh1,public_key), + [{DSA, _}] = public_key:ssh_decode(Ssh2,public_key), + AuthKeys = public_key:ssh_encode([{RSA, [{comment, "Test"}]}, + {DSA,[{comment, "Test"}]}], auth_keys), + AuthKeysFile = filename:join(UserDir, "authorized_keys"), + file:write_file(AuthKeysFile, AuthKeys), Config; _Else -> {skip, "Crypto could not be started!"} @@ -56,9 +67,7 @@ init_per_suite(Config) -> %% Description: Cleanup after the whole suite %%-------------------------------------------------------------------- end_per_suite(Config) -> - Dir = ?config(priv_dir, Config), crypto:stop(), - ssh_test_lib:remove_id_keys(Dir), ok. %%-------------------------------------------------------------------- @@ -75,7 +84,6 @@ end_per_suite(Config) -> %% Description: Initialization before each test case %%-------------------------------------------------------------------- init_per_testcase(_TestCase, Config) -> - ssh_test_lib:known_hosts(backup), ssh:start(), Config. @@ -87,9 +95,16 @@ init_per_testcase(_TestCase, Config) -> %% A list of key/value pairs, holding the test case configuration. %% Description: Cleanup after each test case %%-------------------------------------------------------------------- -end_per_testcase(_TestCase, _Config) -> + +end_per_testcase(TestCase, Config) when TestCase == server_password_option; + TestCase == server_userpassword_option -> + UserDir = filename:join(?config(priv_dir, Config), nopubkey), + file:del_dir(UserDir), + end_per_testcase(Config); +end_per_testcase(_TestCase, Config) -> + end_per_testcase(Config). +end_per_testcase(Config) -> ssh:stop(), - ssh_test_lib:known_hosts(restore), ok. %%-------------------------------------------------------------------- @@ -101,9 +116,8 @@ end_per_testcase(_TestCase, _Config) -> %% Description: Returns a list of all test cases in this test suite %%-------------------------------------------------------------------- all() -> - [exec, exec_compressed, shell, daemon_already_started, - server_password_option, server_userpassword_option, - known_hosts]. + [exec, exec_compressed, shell, daemon_already_started, + server_password_option, server_userpassword_option, known_hosts]. groups() -> []. @@ -136,10 +150,14 @@ exec(suite) -> exec(Config) when is_list(Config) -> process_flag(trap_exit, true), SystemDir = ?config(data_dir, Config), + UserDir = ?config(priv_dir, Config), + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, + {user_dir, UserDir}, {failfun, fun ssh_test_lib:failfun/2}]), ConnectionRef = ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user_dir, UserDir}, {user_interaction, false}]), {ok, ChannelId0} = ssh_connection:session_channel(ConnectionRef, infinity), success = ssh_connection:exec(ConnectionRef, ChannelId0, @@ -178,12 +196,15 @@ exec_compressed(suite) -> exec_compressed(Config) when is_list(Config) -> process_flag(trap_exit, true), SystemDir = ?config(data_dir, Config), - {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, + UserDir = ?config(priv_dir, Config), + + {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},{user_dir, UserDir}, {compression, zlib}, {failfun, fun ssh_test_lib:failfun/2}]), ConnectionRef = ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true}, + {user_dir, UserDir}, {user_interaction, false}]), {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity), success = ssh_connection:exec(ConnectionRef, ChannelId, @@ -209,12 +230,14 @@ shell(suite) -> shell(Config) when is_list(Config) -> process_flag(trap_exit, true), SystemDir = ?config(data_dir, Config), - {_Pid, _Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, + UserDir = ?config(priv_dir, Config), + + {_Pid, _Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},{user_dir, UserDir}, {failfun, fun ssh_test_lib:failfun/2}]), test_server:sleep(500), IO = ssh_test_lib:start_io_server(), - Shell = ssh_test_lib:start_shell(Port, IO), + Shell = ssh_test_lib:start_shell(Port, IO, UserDir), receive ErlShellStart -> test_server:format("Erlang shell start: ~p~n", [ErlShellStart]) @@ -291,8 +314,9 @@ server_password_option(doc) -> server_password_option(suite) -> []; server_password_option(Config) when is_list(Config) -> - UserDir = ?config(data_dir, Config), % to make sure we don't use - SysDir = ?config(data_dir, Config), % public-key-auth + UserDir = filename:join(?config(priv_dir, Config), nopubkey), % to make sure we don't use public-key-auth + file:make_dir(UserDir), + SysDir = ?config(data_dir, Config), {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, {password, "morot"}]), @@ -321,8 +345,9 @@ server_userpassword_option(doc) -> server_userpassword_option(suite) -> []; server_userpassword_option(Config) when is_list(Config) -> - UserDir = ?config(data_dir, Config), % to make sure we don't use - SysDir = ?config(data_dir, Config), % public-key-auth + UserDir = filename:join(?config(priv_dir, Config), nopubkey), % to make sure we don't use public-key-auth + file:make_dir(UserDir), + SysDir = ?config(data_dir, Config), {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir}, {user_passwords, [{"vego", "morot"}]}]), @@ -361,10 +386,10 @@ known_hosts(doc) -> known_hosts(suite) -> []; known_hosts(Config) when is_list(Config) -> - SystemDir = ?config(data_dir, Config), + DataDir = ?config(data_dir, Config), UserDir = ?config(priv_dir, Config), - - {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, + + {Pid, Host, Port} = ssh_test_lib:daemon([{user_dir, UserDir},{system_dir, DataDir}, {failfun, fun ssh_test_lib:failfun/2}]), KnownHosts = filename:join(UserDir, "known_hosts"), diff --git a/lib/ssh/test/ssh_basic_SUITE_data/id_dsa b/lib/ssh/test/ssh_basic_SUITE_data/id_dsa new file mode 100644 index 0000000000..d306f8b26e --- /dev/null +++ b/lib/ssh/test/ssh_basic_SUITE_data/id_dsa @@ -0,0 +1,13 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBvAIBAAKBgQDfi2flSTZZofwT4yQT0NikX/LGNT7UPeB/XEWe/xovEYCElfaQ +APFixXvEgXwoojmZ5kiQRKzLM39wBP0jPERLbnZXfOOD0PDnw0haMh7dD7XKVMod +/EigVgHf/qBdM2M8yz1s/rRF7n1UpLSypziKjkzCm7JoSQ2zbWIPdmBIXwIVAMgP +kpr7Sq3O7sHdb8D601DRjoExAoGAMOQxDfB2Fd8ouz6G96f/UOzRMI/Kdv8kYYKW +JIGY+pRYrLPyYzUeJznwZreOJgrczAX+luHnKFWJ2Dnk5CyeXk67Wsr7pJ/4MBMD +OKeIS0S8qoSBN8+Krp79fgA+yS3IfqbkJLtLu4EBaCX4mKQIX4++k44d4U5lc8pt ++9hlEI8CgYEAznKxx9kyC6bVo7LUYKaGhofRFt0SYFc5PVmT2VUGRs1R6+6DPD+e +uEO6IhFct7JFSRbP9p0JD4Uk+3zlZF+XX6b2PsZkeV8f/02xlNGUSmEzCSiNg1AX +Cy/WusYhul0MncWCHMcOZB5rIvU/aP5EJJtn3xrRaz6u0SThF6AnT34CFQC63czE +ZU8w8Q+H7z0j+a+70x2iAw== +-----END DSA PRIVATE KEY----- + diff --git a/lib/ssh/test/ssh_basic_SUITE_data/id_dsa.pub b/lib/ssh/test/ssh_basic_SUITE_data/id_dsa.pub new file mode 100644 index 0000000000..9406116777 --- /dev/null +++ b/lib/ssh/test/ssh_basic_SUITE_data/id_dsa.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBAN+LZ+VJNlmh/BPjJBPQ2KRf8sY1PtQ94H9cRZ7/Gi8RgISV9pAA8WLFe8SBfCiiOZnmSJBErMszf3AE/SM8REtudld844PQ8OfDSFoyHt0PtcpUyh38SKBWAd/+oF0zYzzLPWz+tEXufVSktLKnOIqOTMKbsmhJDbNtYg92YEhfAAAAFQDID5Ka+0qtzu7B3W/A+tNQ0Y6BMQAAAIAw5DEN8HYV3yi7Pob3p/9Q7NEwj8p2/yRhgpYkgZj6lFiss/JjNR4nOfBmt44mCtzMBf6W4ecoVYnYOeTkLJ5eTrtayvukn/gwEwM4p4hLRLyqhIE3z4qunv1+AD7JLch+puQku0u7gQFoJfiYpAhfj76Tjh3hTmVzym372GUQjwAAAIEAznKxx9kyC6bVo7LUYKaGhofRFt0SYFc5PVmT2VUGRs1R6+6DPD+euEO6IhFct7JFSRbP9p0JD4Uk+3zlZF+XX6b2PsZkeV8f/02xlNGUSmEzCSiNg1AXCy/WusYhul0MncWCHMcOZB5rIvU/aP5EJJtn3xrRaz6u0SThF6AnT34= Dsa diff --git a/lib/ssh/test/ssh_basic_SUITE_data/id_rsa b/lib/ssh/test/ssh_basic_SUITE_data/id_rsa new file mode 100644 index 0000000000..79968bdd7d --- /dev/null +++ b/lib/ssh/test/ssh_basic_SUITE_data/id_rsa @@ -0,0 +1,16 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQDCZX+4FBDwZIh9y/Uxee1VJnEXlowpz2yDKwj8semM4q843337 +zbNfxHmladB1lpz2NqyxI175xMIJuDxogyZdsOxGnFAzAnthR4dqL/RWRWzjaxSB +6IAO9SPYVVlrpZ+1hsjLW79fwXK/yc8VdhRuWTeQiRgYY2ek8+OKbOqz4QIDAQAB +AoGANmvJzJO5hkLuvyDZHKfAnGTtpifcR1wtSa9DjdKUyn8vhKF0mIimnbnYQEmW +NUUb3gXCZLi9PvkpRSVRrASDOZwcjoU/Kvww163vBUVb2cOZfFhyn6o2Sk88Tt++ +udH3hdjpf9i7jTtUkUe+QYPsia+wgvvrmn4QrahLAH86+kECQQDx5gFeXTME3cnW +WMpFz3PPumduzjqgqMMWEccX4FtQkMX/gyGa5UC7OHFyh0N/gSWvPbRHa8A6YgIt +n8DO+fh5AkEAzbqX4DOn8NY6xJIi42q7l/2jIA0RkB6P7YugW5NblhqBZ0XDnpA5 +sMt+rz+K07u9XZtxgh1xi7mNfwY6lEAMqQJBAJBEauCKmRj35Z6OyeQku59SPsnY ++SJEREVvSNw2lH9SOKQQ4wPsYlTGbvKtNVZgAcen91L5MmYfeckYE/fdIZECQQCt +64zxsTnM1I8iFxj/gP/OYlJBikrKt8udWmjaghzvLMEw+T2DExJyb9ZNeT53+UMB +m6O+B/4xzU/djvp+0hbhAkAemIt+rA5kTmYlFndhpvzkSSM8a2EXsO4XIPgGWCTT +tQKS/tTly0ADMjN/TVy11+9d6zcqadNVuHXHGtR4W0GR +-----END RSA PRIVATE KEY----- + diff --git a/lib/ssh/test/ssh_basic_SUITE_data/id_rsa.pub b/lib/ssh/test/ssh_basic_SUITE_data/id_rsa.pub new file mode 100644 index 0000000000..95bce6bc61 --- /dev/null +++ b/lib/ssh/test/ssh_basic_SUITE_data/id_rsa.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDCZX+4FBDwZIh9y/Uxee1VJnEXlowpz2yDKwj8semM4q843337zbNfxHmladB1lpz2NqyxI175xMIJuDxogyZdsOxGnFAzAnthR4dqL/RWRWzjaxSB6IAO9SPYVVlrpZ+1hsjLW79fwXK/yc8VdhRuWTeQiRgYY2ek8+OKbOqz4Q== ingela@dain diff --git a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key new file mode 100644 index 0000000000..d306f8b26e --- /dev/null +++ b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_dsa_key @@ -0,0 +1,13 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBvAIBAAKBgQDfi2flSTZZofwT4yQT0NikX/LGNT7UPeB/XEWe/xovEYCElfaQ +APFixXvEgXwoojmZ5kiQRKzLM39wBP0jPERLbnZXfOOD0PDnw0haMh7dD7XKVMod +/EigVgHf/qBdM2M8yz1s/rRF7n1UpLSypziKjkzCm7JoSQ2zbWIPdmBIXwIVAMgP +kpr7Sq3O7sHdb8D601DRjoExAoGAMOQxDfB2Fd8ouz6G96f/UOzRMI/Kdv8kYYKW +JIGY+pRYrLPyYzUeJznwZreOJgrczAX+luHnKFWJ2Dnk5CyeXk67Wsr7pJ/4MBMD +OKeIS0S8qoSBN8+Krp79fgA+yS3IfqbkJLtLu4EBaCX4mKQIX4++k44d4U5lc8pt ++9hlEI8CgYEAznKxx9kyC6bVo7LUYKaGhofRFt0SYFc5PVmT2VUGRs1R6+6DPD+e +uEO6IhFct7JFSRbP9p0JD4Uk+3zlZF+XX6b2PsZkeV8f/02xlNGUSmEzCSiNg1AX +Cy/WusYhul0MncWCHMcOZB5rIvU/aP5EJJtn3xrRaz6u0SThF6AnT34CFQC63czE +ZU8w8Q+H7z0j+a+70x2iAw== +-----END DSA PRIVATE KEY----- + diff --git a/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_rsa_key b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_rsa_key new file mode 100644 index 0000000000..79968bdd7d --- /dev/null +++ b/lib/ssh/test/ssh_basic_SUITE_data/ssh_host_rsa_key @@ -0,0 +1,16 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQDCZX+4FBDwZIh9y/Uxee1VJnEXlowpz2yDKwj8semM4q843337 +zbNfxHmladB1lpz2NqyxI175xMIJuDxogyZdsOxGnFAzAnthR4dqL/RWRWzjaxSB +6IAO9SPYVVlrpZ+1hsjLW79fwXK/yc8VdhRuWTeQiRgYY2ek8+OKbOqz4QIDAQAB +AoGANmvJzJO5hkLuvyDZHKfAnGTtpifcR1wtSa9DjdKUyn8vhKF0mIimnbnYQEmW +NUUb3gXCZLi9PvkpRSVRrASDOZwcjoU/Kvww163vBUVb2cOZfFhyn6o2Sk88Tt++ +udH3hdjpf9i7jTtUkUe+QYPsia+wgvvrmn4QrahLAH86+kECQQDx5gFeXTME3cnW +WMpFz3PPumduzjqgqMMWEccX4FtQkMX/gyGa5UC7OHFyh0N/gSWvPbRHa8A6YgIt +n8DO+fh5AkEAzbqX4DOn8NY6xJIi42q7l/2jIA0RkB6P7YugW5NblhqBZ0XDnpA5 +sMt+rz+K07u9XZtxgh1xi7mNfwY6lEAMqQJBAJBEauCKmRj35Z6OyeQku59SPsnY ++SJEREVvSNw2lH9SOKQQ4wPsYlTGbvKtNVZgAcen91L5MmYfeckYE/fdIZECQQCt +64zxsTnM1I8iFxj/gP/OYlJBikrKt8udWmjaghzvLMEw+T2DExJyb9ZNeT53+UMB +m6O+B/4xzU/djvp+0hbhAkAemIt+rA5kTmYlFndhpvzkSSM8a2EXsO4XIPgGWCTT +tQKS/tTly0ADMjN/TVy11+9d6zcqadNVuHXHGtR4W0GR +-----END RSA PRIVATE KEY----- + diff --git a/lib/ssh/test/ssh_sftp_SUITE.erl b/lib/ssh/test/ssh_sftp_SUITE.erl index c96b6de3ea..a9a568ced6 100644 --- a/lib/ssh/test/ssh_sftp_SUITE.erl +++ b/lib/ssh/test/ssh_sftp_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2011. All Rights Reserved. +%% Copyright Ericsson AB 2005-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 @@ -50,7 +50,6 @@ init_per_suite(Config) -> {ok,ok} -> Dir = ?config(priv_dir, Config), {ok, _} = ssh_test_lib:get_id_keys(Dir), - ssh_test_lib:make_dsa_files(Config), Config; {ok,_} -> {skip,"Could not start ssh!"}; @@ -94,13 +93,14 @@ init_per_testcase(_Case, Config) -> SysDir = ?config(data_dir, Config), Host = ssh_test_lib:hostname(), + %% Run test against openssh server if available Sftp = case (catch ssh_sftp:start_channel(Host, [{user_dir, Dir}, {user_interaction, false}, {silently_accept_hosts, true}])) of {ok, ChannelPid, Connection} -> {ChannelPid, Connection}; - _Error -> + _Error -> %% Start own sftp server {_Sftpd, _Host, _Port} = ssh_test_lib:daemon(Host, ?SFPD_PORT, [{system_dir, SysDir}, diff --git a/lib/ssh/test/ssh_sftp_SUITE_data/id_rsa b/lib/ssh/test/ssh_sftp_SUITE_data/id_rsa deleted file mode 100644 index 7e3f885f5d..0000000000 --- a/lib/ssh/test/ssh_sftp_SUITE_data/id_rsa +++ /dev/null @@ -1,15 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIICWwIBAAKBgQDLKYTdRnGzphcN+pF8UuI3sYB7rxZUHbOT87K3vh8XOLkDOsS3 -8VREtNS8Wb3uYXsRtyDoUvrLIDnyllOfJSDupWLr4ibckUZd/nhFAaC6WryVmH6k -GlQLLp9KU+vcn2DwYeo14gbwHYDB3pmv4CWAlnO1m/BkX4aLz1zC314OkQIBIwKB -gD/Z2UzboBPjvhpWEHeHw3CW3zzQoJ4X9pw2peH57IOkHOPCA0/A3/hWFvleCH4e -owWRU3w3ViKVGYbBh/7RJ5rllN+ENUmVn536srJTxLKUtvb5jRGj3W6EWgAGHSUB -hm83Kt9Lb5hprL7dPrNGvSseBm/LQSfBQ4vUUyiVRKGPAkEA/rPxWoLdBBP+FZtE -fGzz9izPM6Fe6o8ZGNZIlRBProOhgEvvIqdgzQWObgLVVrw+M/YApPpiYS3PEmWj -b2b+jwJBAMwyYeL6coKTl8swDu8HvLnshgUFJFTtHhOTXsKtXQNI1b24xhUrB3Sb -X8fmoByyRNRpOfvg4Jdqi3Z6KfIcsN8CQQDEfC83McBw3DkJWoVKCugVrYnmACSm -USH9N5cT6AL0VupNB2C0VTwL37cEaJXyc/V4ipLIaWHV8CNl9qKmZWVJAkEAurG4 -lQI8zyfbPW3EgsU+1d+QeZ5NGnJkpC73jWtNudwxIn0M4CdXRgpmMxwAGjyWs5No -Nr75OfsDKn5SPHIAywJAKrtONlOizgDiG3EvAXZlwFtOb+HkQ7lrFwczrQu9m7yi -brSAcnTrLKI6CrR33b/QJLvb9C/HTEZojFABGq8M7A== ------END RSA PRIVATE KEY----- diff --git a/lib/ssh/test/ssh_sftp_SUITE_data/id_rsa.pub b/lib/ssh/test/ssh_sftp_SUITE_data/id_rsa.pub deleted file mode 100644 index 77f57de4af..0000000000 --- a/lib/ssh/test/ssh_sftp_SUITE_data/id_rsa.pub +++ /dev/null @@ -1 +0,0 @@ -ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAyymE3UZxs6YXDfqRfFLiN7GAe68WVB2zk/Oyt74fFzi5AzrEt/FURLTUvFm97mF7Ebcg6FL6yyA58pZTnyUg7qVi6+Im3JFGXf54RQGgulq8lZh+pBpUCy6fSlPr3J9g8GHqNeIG8B2Awd6Zr+AlgJZztZvwZF+Gi89cwt9eDpE= jakob@balin diff --git a/lib/ssh/test/ssh_sftpd_SUITE.erl b/lib/ssh/test/ssh_sftpd_SUITE.erl index bfe54a3e75..0873348be0 100644 --- a/lib/ssh/test/ssh_sftpd_SUITE.erl +++ b/lib/ssh/test/ssh_sftpd_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2011. All Rights Reserved. +%% Copyright Ericsson AB 2006-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 @@ -53,16 +53,15 @@ %% variable, but should NOT alter/remove any existing entries. %%-------------------------------------------------------------------- init_per_suite(Config) -> - case {catch ssh:stop(),catch crypto:start()} of - {ok,ok} -> - ssh_test_lib:make_dsa_files(Config), + case (catch crypto:start()) of + ok -> + ssh:start(), + DataDir = ?config(data_dir, Config), + UserDir = ?config(priv_dir, Config), + ssh_test_lib:setup_dsa(UserDir, DataDir), Config; - {ok,_} -> - {skip,"Could not start ssh!"}; - {_,ok} -> - {skip,"Could not start crypto!"}; - {_,_} -> - {skip,"Could not start crypto and ssh!"} + _ -> + {skip,"Could not start ssh!"} end. %%-------------------------------------------------------------------- @@ -71,7 +70,10 @@ init_per_suite(Config) -> %% A list of key/value pairs, holding the test case configuration. %% Description: Cleanup after the whole suite %%-------------------------------------------------------------------- -end_per_suite(_Config) -> +end_per_suite(Config) -> + UserDir = ?config(priv_dir, Config), + ssh_test_lib:clean_dsa(UserDir), + ssh:stop(), crypto:stop(), ok. diff --git a/lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key new file mode 100644 index 0000000000..51ab6fbd88 --- /dev/null +++ b/lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key @@ -0,0 +1,13 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBuwIBAAKBgQCClaHzE2ul0gKSUxah5W0W8UiJLy4hXngKEqpaUq9SSdVdY2LK +wVfKH1gt5iuaf1FfzOhsIC9G/GLnjYttXZc92cv/Gfe3gR+s0ni2++MX+T++mE/Q +diltXv/Hp27PybS67SmiFW7I+RWnT2OKlMPtw2oUuKeztCe5UWjaj/y5FQIVAPLA +l9RpiU30Z87NRAHY3NTRaqtrAoGANMRxw8UfdtNVR0CrQj3AgPaXOGE4d+G4Gp4X +skvnCHycSVAjtYxebUkzUzt5Q6f/IabuLUdge3gXrc8BetvrcKbp+XZgM0/Vj2CF +Ymmy3in6kzGZq7Fw1sZaku6AOU8vLa5woBT2vAcHLLT1bLAzj7viL048T6MfjrOP +ef8nHvACgYBhDWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah +/XcF3DeRF+eEoz48wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+U +ykSTXYUbtsfTNRFQGBW2/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0CgIVAN4wtL5W +Lv62jKcdskxNyz2NQoBx +-----END DSA PRIVATE KEY----- + diff --git a/lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key.pub new file mode 100644 index 0000000000..4dbb1305b0 --- /dev/null +++ b/lib/ssh/test/ssh_sftpd_SUITE_data/ssh_host_dsa_key.pub @@ -0,0 +1,11 @@ +---- BEGIN SSH2 PUBLIC KEY ---- +AAAAB3NzaC1kc3MAAACBAIKVofMTa6XSApJTFqHlbRbxSIkvLiFeeAoSqlpSr1JJ1V1j +YsrBV8ofWC3mK5p/UV/M6GwgL0b8YueNi21dlz3Zy/8Z97eBH6zSeLb74xf5P76YT9B2 +KW1e/8enbs/JtLrtKaIVbsj5FadPY4qUw+3DahS4p7O0J7lRaNqP/LkVAAAAFQDywJfU +aYlN9GfOzUQB2NzU0WqrawAAAIA0xHHDxR9201VHQKtCPcCA9pc4YTh34bganheyS+cI +fJxJUCO1jF5tSTNTO3lDp/8hpu4tR2B7eBetzwF62+twpun5dmAzT9WPYIViabLeKfqT +MZmrsXDWxlqS7oA5Ty8trnCgFPa8BwcstPVssDOPu+IvTjxPox+Os495/yce8AAAAIBh +DWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah/XcF3DeRF+eEoz48 +wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+UykSTXYUbtsfTNRFQGBW2 +/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0Cg== +---- END SSH2 PUBLIC KEY ---- diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl index 2209af05d5..c63ad7de73 100644 --- a/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl +++ b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2011. All Rights Reserved. +%% Copyright Ericsson AB 2007-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 @@ -48,13 +48,14 @@ init_per_suite(Config) -> case catch crypto:start() of ok -> DataDir = ?config(data_dir, Config), + UserDir = ?config(priv_dir, Config), FileAlt = filename:join(DataDir, "ssh_sftpd_file_alt.erl"), c:c(FileAlt), FileName = filename:join(DataDir, "test.txt"), {ok, FileInfo} = file:read_file_info(FileName), ok = file:write_file_info(FileName, FileInfo#file_info{mode = 8#400}), - ssh_test_lib:make_dsa_files(Config), + ssh_test_lib:setup_dsa(DataDir, UserDir), Config; _Else -> {skip,"Could not start ssh!"} @@ -66,7 +67,9 @@ init_per_suite(Config) -> %% A list of key/value pairs, holding the test case configuration. %% Description: Cleanup after the whole suite %%-------------------------------------------------------------------- -end_per_suite(_Config) -> +end_per_suite(Config) -> + UserDir = ?config(priv_dir, Config), + ssh_test_lib:clean_dsa(UserDir), crypto:stop(), ok. @@ -85,7 +88,7 @@ end_per_suite(_Config) -> %%-------------------------------------------------------------------- init_per_testcase(TestCase, Config) -> ssh:start(), - DataDir = ?config(data_dir, Config), + PrivDir = ?config(priv_dir, Config), Options = case atom_to_list(TestCase) of @@ -95,8 +98,7 @@ init_per_testcase(TestCase, Config) -> ssh_sftpd_file_alt}]), [{user_passwords,[{?USER, ?PASSWD}]}, {pwdfun, fun(_,_) -> true end}, - {system_dir, DataDir}, - {user_dir, DataDir}, + {system_dir, PrivDir}, {subsystems, [Spec]}]; "root_dir" -> Privdir = ?config(priv_dir, Config), @@ -105,23 +107,20 @@ init_per_testcase(TestCase, Config) -> Spec = ssh_sftpd:subsystem_spec([{root,Root}]), [{user_passwords,[{?USER, ?PASSWD}]}, {pwdfun, fun(_,_) -> true end}, - {system_dir, DataDir}, - {user_dir, DataDir}, + {system_dir, PrivDir}, {subsystems, [Spec]}]; "list_dir_limited" -> Spec = ssh_sftpd:subsystem_spec([{max_files,1}]), [{user_passwords,[{?USER, ?PASSWD}]}, {pwdfun, fun(_,_) -> true end}, - {system_dir, DataDir}, - {user_dir, DataDir}, + {system_dir, PrivDir}, {subsystems, [Spec]}]; _ -> [{user_passwords,[{?USER, ?PASSWD}]}, {pwdfun, fun(_,_) -> true end}, - {user_dir, DataDir}, - {system_dir, DataDir}] + {system_dir, PrivDir}] end, {Sftpd, Host, _Port} = ssh_test_lib:daemon(any, ?SSHD_PORT, Options), @@ -131,8 +130,7 @@ init_per_testcase(TestCase, Config) -> [{silently_accept_hosts, true}, {user, ?USER}, {password, ?PASSWD}, {pwdfun, fun(_,_) -> true end}, - {system_dir, DataDir}, - {user_dir, DataDir}, + {user_dir, PrivDir}, {timeout, 30000}]), TmpConfig = lists:keydelete(sftp, 1, Config), NewConfig = lists:keydelete(sftpd, 1, TmpConfig), diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key new file mode 100644 index 0000000000..51ab6fbd88 --- /dev/null +++ b/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key @@ -0,0 +1,13 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBuwIBAAKBgQCClaHzE2ul0gKSUxah5W0W8UiJLy4hXngKEqpaUq9SSdVdY2LK +wVfKH1gt5iuaf1FfzOhsIC9G/GLnjYttXZc92cv/Gfe3gR+s0ni2++MX+T++mE/Q +diltXv/Hp27PybS67SmiFW7I+RWnT2OKlMPtw2oUuKeztCe5UWjaj/y5FQIVAPLA +l9RpiU30Z87NRAHY3NTRaqtrAoGANMRxw8UfdtNVR0CrQj3AgPaXOGE4d+G4Gp4X +skvnCHycSVAjtYxebUkzUzt5Q6f/IabuLUdge3gXrc8BetvrcKbp+XZgM0/Vj2CF +Ymmy3in6kzGZq7Fw1sZaku6AOU8vLa5woBT2vAcHLLT1bLAzj7viL048T6MfjrOP +ef8nHvACgYBhDWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah +/XcF3DeRF+eEoz48wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+U +ykSTXYUbtsfTNRFQGBW2/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0CgIVAN4wtL5W +Lv62jKcdskxNyz2NQoBx +-----END DSA PRIVATE KEY----- + diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key.pub new file mode 100644 index 0000000000..4dbb1305b0 --- /dev/null +++ b/lib/ssh/test/ssh_sftpd_erlclient_SUITE_data/ssh_host_dsa_key.pub @@ -0,0 +1,11 @@ +---- BEGIN SSH2 PUBLIC KEY ---- +AAAAB3NzaC1kc3MAAACBAIKVofMTa6XSApJTFqHlbRbxSIkvLiFeeAoSqlpSr1JJ1V1j +YsrBV8ofWC3mK5p/UV/M6GwgL0b8YueNi21dlz3Zy/8Z97eBH6zSeLb74xf5P76YT9B2 +KW1e/8enbs/JtLrtKaIVbsj5FadPY4qUw+3DahS4p7O0J7lRaNqP/LkVAAAAFQDywJfU +aYlN9GfOzUQB2NzU0WqrawAAAIA0xHHDxR9201VHQKtCPcCA9pc4YTh34bganheyS+cI +fJxJUCO1jF5tSTNTO3lDp/8hpu4tR2B7eBetzwF62+twpun5dmAzT9WPYIViabLeKfqT +MZmrsXDWxlqS7oA5Ty8trnCgFPa8BwcstPVssDOPu+IvTjxPox+Os495/yce8AAAAIBh +DWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah/XcF3DeRF+eEoz48 +wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+UykSTXYUbtsfTNRFQGBW2 +/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0Cg== +---- END SSH2 PUBLIC KEY ---- diff --git a/lib/ssh/test/ssh_test_lib.erl b/lib/ssh/test/ssh_test_lib.erl index 425fae22c1..f4e95f9bfb 100644 --- a/lib/ssh/test/ssh_test_lib.erl +++ b/lib/ssh/test/ssh_test_lib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2011. All Rights Reserved. +%% Copyright Ericsson AB 2004-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 @@ -68,15 +68,11 @@ daemon(Host, Port, Options) -> Error end. +start_shell(Port, IOServer, UserDir) -> + spawn_link(?MODULE, init_shell, [Port, IOServer, [{user_dir, UserDir}]]). - - -start_shell(Port, IOServer) -> - spawn_link(?MODULE, init_shell, [Port, IOServer]). - -init_shell(Port, IOServer) -> +init_shell(Port, IOServer, UserDir) -> Host = hostname(), - UserDir = get_user_dir(), Options = [{user_interaction, false}, {silently_accept_hosts, true}] ++ UserDir, group_leader(IOServer, self()), @@ -139,12 +135,18 @@ reply(TestCase, Result) -> receive_exec_result(Msg) -> test_server:format("Expect data! ~p", [Msg]), receive + {ssh_cm,_,{data,_,1, Data}} -> + test_server:format("StdErr: ~p~n", [Data]), + receive_exec_result(Msg); Msg -> test_server:format("1: Collected data ~p", [Msg]), expected; Other -> + test_server:format("Other ~p", [Other]), {unexpected_msg, Other} end. + + receive_exec_end(ConnectionRef, ChannelId) -> Eof = {ssh_cm, ConnectionRef, {eof, ChannelId}}, ExitStatus = {ssh_cm, ConnectionRef, {exit_status, ChannelId, 0}}, @@ -198,9 +200,16 @@ remove_id_keys(Dir) -> file:delete(filename:join(Dir, "id_rsa")), file:delete(filename:join(Dir, "id_dsa")). -copyfile(SrcDir, DstDir, Fn) -> - file:copy(filename:join(SrcDir, Fn), - filename:join(DstDir, Fn)). +copyfile(SrcDir, DstDir, FileName) -> + Dest = filename:join(DstDir, FileName), + Result = file:copy(filename:join(SrcDir, FileName), Dest), + {ok, Pem} = file:read_file(Dest), + case public_key:pem_decode(Pem) of + [{_,_, not_encrypted}] -> + Result; + _ -> + {error, "Has pass phrase can not be used by automated test case"} + end. failfun(_User, {authmethod,none}) -> ok; @@ -222,39 +231,11 @@ known_hosts(BR) -> file:rename(B, KnownHosts) end. - -get_user_dir() -> - case os:type() of - {win32, _} -> - [{user_dir, filename:join([os:getenv("HOME"), ".ssh"])}]; - _ -> - [] - end. - - -make_dsa_cert_files(Config) -> - make_dsa_cert_files("", Config). - -make_dsa_cert_files(RoleStr, Config) -> - - CaInfo = {CaCert, _} = make_cert([{key, dsa}]), - {Cert, CertKey} = make_cert([{key, dsa}, {issuer, CaInfo}]), - CaCertFile = filename:join([?config(data_dir, Config), - RoleStr, "dsa_cacerts.pem"]), - CertFile = filename:join([?config(data_dir, Config), - RoleStr, "dsa_cert.pem"]), - KeyFile = filename:join([?config(data_dir, Config), - RoleStr, "dsa_key.pem"]), - - der_to_pem(CaCertFile, [{'Certificate', CaCert, not_encrypted}]), - der_to_pem(CertFile, [{'Certificate', Cert, not_encrypted}]), - der_to_pem(KeyFile, [CertKey]), - {CaCertFile, CertFile, KeyFile}. - -make_dsa_files(Config) -> - make_dsa_files(Config, rfc4716_public_key). -make_dsa_files(Config, Type) -> - {DSA, EncodedKey} = ssh_test_lib:gen_dsa(128, 20), +setup_dsa(DataDir, UserDir) -> + ssh_test_lib:copyfile(DataDir, UserDir, "ssh_host_dsa_key"), + ssh_test_lib:copyfile(DataDir, UserDir, "ssh_host_dsa_key.pub"), + {ok, Pem} = file:read_file(filename:join(UserDir, "ssh_host_dsa_key")), + DSA = public_key:pem_entry_decode(hd(public_key:pem_decode(Pem))), PKey = DSA#'DSAPrivateKey'.y, P = DSA#'DSAPrivateKey'.p, Q = DSA#'DSAPrivateKey'.q, @@ -263,422 +244,13 @@ make_dsa_files(Config, Type) -> {ok, Hostname} = inet:gethostname(), {ok, {A, B, C, D}} = inet:getaddr(Hostname, inet), IP = lists:concat([A, ".", B, ".", C, ".", D]), - Attributes = [], % Could be [{comment,"user@" ++ Hostname}], HostNames = [{hostnames,[IP, IP]}], - PublicKey = [{{PKey, Dss}, Attributes}], KnownHosts = [{{PKey, Dss}, HostNames}], - KnownHostsEnc = public_key:ssh_encode(KnownHosts, known_hosts), - KnownHosts = public_key:ssh_decode(KnownHostsEnc, known_hosts), - - PublicKeyEnc = public_key:ssh_encode(PublicKey, Type), -% PublicKey = public_key:ssh_decode(PublicKeyEnc, Type), - - SystemTmpDir = ?config(data_dir, Config), - filelib:ensure_dir(SystemTmpDir), - file:make_dir(SystemTmpDir), - - DSAFile = filename:join(SystemTmpDir, "ssh_host_dsa_key.pub"), - file:delete(DSAFile), - - DSAPrivateFile = filename:join(SystemTmpDir, "ssh_host_dsa_key"), - file:delete(DSAPrivateFile), - - KHFile = filename:join(SystemTmpDir, "known_hosts"), - file:delete(KHFile), - - PemBin = public_key:pem_encode([EncodedKey]), - - file:write_file(DSAFile, PublicKeyEnc), - file:write_file(KHFile, KnownHostsEnc), - file:write_file(DSAPrivateFile, PemBin), - ok. - -%%-------------------------------------------------------------------- -%% Create and return a der encoded certificate -%% Option Default -%% ------------------------------------------------------- -%% digest sha1 -%% validity {date(), date() + week()} -%% version 3 -%% subject [] list of the following content -%% {name, Name} -%% {email, Email} -%% {city, City} -%% {state, State} -%% {org, Org} -%% {org_unit, OrgUnit} -%% {country, Country} -%% {serial, Serial} -%% {title, Title} -%% {dnQualifer, DnQ} -%% issuer = {Issuer, IssuerKey} true (i.e. a ca cert is created) -%% (obs IssuerKey migth be {Key, Password} -%% key = KeyFile|KeyBin|rsa|dsa Subject PublicKey rsa or dsa generates key -%% -%% -%% (OBS: The generated keys are for testing only) -%% make_cert([{::atom(), ::term()}]) -> {Cert::binary(), Key::binary()} -%%-------------------------------------------------------------------- -make_cert(Opts) -> - SubjectPrivateKey = get_key(Opts), - {TBSCert, IssuerKey} = make_tbs(SubjectPrivateKey, Opts), - Cert = public_key:pkix_sign(TBSCert, IssuerKey), - true = verify_signature(Cert, IssuerKey, undef), %% verify that the keys where ok - {Cert, encode_key(SubjectPrivateKey)}. - -%%-------------------------------------------------------------------- -%% Writes cert files in Dir with FileName and FileName ++ Suffix -%% write_cert(::string(), ::string(), {Cert,Key}) -> ok -%%-------------------------------------------------------------------- -write_cert(Dir, FileName, Suffix, {Cert, Key = {_,_,not_encrypted}}) when is_binary(Cert) -> - ok = der_to_pem(filename:join(Dir, FileName), - [{'Certificate', Cert, not_encrypted}]), - ok = der_to_pem(filename:join(Dir, FileName ++ Suffix), [Key]). - -%%-------------------------------------------------------------------- -%% Creates a rsa key (OBS: for testing only) -%% the size are in bytes -%% gen_rsa(::integer()) -> {::atom(), ::binary(), ::opaque()} -%%-------------------------------------------------------------------- -gen_rsa(Size) when is_integer(Size) -> - Key = gen_rsa2(Size), - {Key, encode_key(Key)}. - -%%-------------------------------------------------------------------- -%% Creates a dsa key (OBS: for testing only) -%% the sizes are in bytes -%% gen_dsa(::integer()) -> {::atom(), ::binary(), ::opaque()} -%%-------------------------------------------------------------------- -gen_dsa(LSize,NSize) when is_integer(LSize), is_integer(NSize) -> - Key = gen_dsa2(LSize, NSize), - {Key, encode_key(Key)}. - -%%-------------------------------------------------------------------- -%% Verifies cert signatures -%% verify_signature(::binary(), ::tuple()) -> ::boolean() -%%-------------------------------------------------------------------- -verify_signature(DerEncodedCert, DerKey, _KeyParams) -> - Key = decode_key(DerKey), - case Key of - #'RSAPrivateKey'{modulus=Mod, publicExponent=Exp} -> - public_key:pkix_verify(DerEncodedCert, - #'RSAPublicKey'{modulus=Mod, publicExponent=Exp}); - #'DSAPrivateKey'{p=P, q=Q, g=G, y=Y} -> - public_key:pkix_verify(DerEncodedCert, {Y, #'Dss-Parms'{p=P, q=Q, g=G}}) - end. - -%%%%%%%%%%%%%%%%%%%%%%%%% Implementation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -get_key(Opts) -> - case proplists:get_value(key, Opts) of - undefined -> make_key(rsa, Opts); - rsa -> make_key(rsa, Opts); - dsa -> make_key(dsa, Opts); - Key -> - Password = proplists:get_value(password, Opts, no_passwd), - decode_key(Key, Password) - end. - -decode_key({Key, Pw}) -> - decode_key(Key, Pw); -decode_key(Key) -> - decode_key(Key, no_passwd). - - -decode_key(#'RSAPublicKey'{} = Key,_) -> - Key; -decode_key(#'RSAPrivateKey'{} = Key,_) -> - Key; -decode_key(#'DSAPrivateKey'{} = Key,_) -> - Key; -decode_key(PemEntry = {_,_,_}, Pw) -> - public_key:pem_entry_decode(PemEntry, Pw); -decode_key(PemBin, Pw) -> - [KeyInfo] = public_key:pem_decode(PemBin), - decode_key(KeyInfo, Pw). - -encode_key(Key = #'RSAPrivateKey'{}) -> - {ok, Der} = 'OTP-PUB-KEY':encode('RSAPrivateKey', Key), - {'RSAPrivateKey', list_to_binary(Der), not_encrypted}; -encode_key(Key = #'DSAPrivateKey'{}) -> - {ok, Der} = 'OTP-PUB-KEY':encode('DSAPrivateKey', Key), - {'DSAPrivateKey', list_to_binary(Der), not_encrypted}. - -make_tbs(SubjectKey, Opts) -> - Version = list_to_atom("v"++integer_to_list(proplists:get_value(version, Opts, 3))), - - IssuerProp = proplists:get_value(issuer, Opts, true), - {Issuer, IssuerKey} = issuer(IssuerProp, Opts, SubjectKey), - - {Algo, Parameters} = sign_algorithm(IssuerKey, Opts), - - SignAlgo = #'SignatureAlgorithm'{algorithm = Algo, - parameters = Parameters}, - Subject = case IssuerProp of - true -> %% Is a Root Ca - Issuer; - _ -> - subject(proplists:get_value(subject, Opts),false) - end, - - {#'OTPTBSCertificate'{serialNumber = trunc(random:uniform()*100000000)*10000 + 1, - signature = SignAlgo, - issuer = Issuer, - validity = validity(Opts), - subject = Subject, - subjectPublicKeyInfo = publickey(SubjectKey), - version = Version, - extensions = extensions(Opts) - }, IssuerKey}. - -issuer(true, Opts, SubjectKey) -> - %% Self signed - {subject(proplists:get_value(subject, Opts), true), SubjectKey}; -issuer({Issuer, IssuerKey}, _Opts, _SubjectKey) when is_binary(Issuer) -> - {issuer_der(Issuer), decode_key(IssuerKey)}; -issuer({File, IssuerKey}, _Opts, _SubjectKey) when is_list(File) -> - {ok, [{cert, Cert, _}|_]} = pem_to_der(File), - {issuer_der(Cert), decode_key(IssuerKey)}. - -issuer_der(Issuer) -> - Decoded = public_key:pkix_decode_cert(Issuer, otp), - #'OTPCertificate'{tbsCertificate=Tbs} = Decoded, - #'OTPTBSCertificate'{subject=Subject} = Tbs, - Subject. - -subject(undefined, IsRootCA) -> - User = if IsRootCA -> "RootCA"; true -> os:getenv("USER") end, - Opts = [{email, User ++ "@erlang.org"}, - {name, User}, - {city, "Stockholm"}, - {country, "SE"}, - {org, "erlang"}, - {org_unit, "testing dep"}], - subject(Opts); -subject(Opts, _) -> - subject(Opts). - -subject(SubjectOpts) when is_list(SubjectOpts) -> - Encode = fun(Opt) -> - {Type,Value} = subject_enc(Opt), - [#'AttributeTypeAndValue'{type=Type, value=Value}] - end, - {rdnSequence, [Encode(Opt) || Opt <- SubjectOpts]}. - -%% Fill in the blanks -subject_enc({name, Name}) -> {?'id-at-commonName', {printableString, Name}}; -subject_enc({email, Email}) -> {?'id-emailAddress', Email}; -subject_enc({city, City}) -> {?'id-at-localityName', {printableString, City}}; -subject_enc({state, State}) -> {?'id-at-stateOrProvinceName', {printableString, State}}; -subject_enc({org, Org}) -> {?'id-at-organizationName', {printableString, Org}}; -subject_enc({org_unit, OrgUnit}) -> {?'id-at-organizationalUnitName', {printableString, OrgUnit}}; -subject_enc({country, Country}) -> {?'id-at-countryName', Country}; -subject_enc({serial, Serial}) -> {?'id-at-serialNumber', Serial}; -subject_enc({title, Title}) -> {?'id-at-title', {printableString, Title}}; -subject_enc({dnQualifer, DnQ}) -> {?'id-at-dnQualifier', DnQ}; -subject_enc(Other) -> Other. - - -extensions(Opts) -> - case proplists:get_value(extensions, Opts, []) of - false -> - asn1_NOVALUE; - Exts -> - lists:flatten([extension(Ext) || Ext <- default_extensions(Exts)]) - end. - -default_extensions(Exts) -> - Def = [{key_usage,undefined}, - {subject_altname, undefined}, - {issuer_altname, undefined}, - {basic_constraints, default}, - {name_constraints, undefined}, - {policy_constraints, undefined}, - {ext_key_usage, undefined}, - {inhibit_any, undefined}, - {auth_key_id, undefined}, - {subject_key_id, undefined}, - {policy_mapping, undefined}], - Filter = fun({Key, _}, D) -> lists:keydelete(Key, 1, D) end, - Exts ++ lists:foldl(Filter, Def, Exts). - -extension({_, undefined}) -> []; -extension({basic_constraints, Data}) -> - case Data of - default -> - #'Extension'{extnID = ?'id-ce-basicConstraints', - extnValue = #'BasicConstraints'{cA=true}, - critical=true}; - false -> - []; - Len when is_integer(Len) -> - #'Extension'{extnID = ?'id-ce-basicConstraints', - extnValue = #'BasicConstraints'{cA=true, pathLenConstraint=Len}, - critical=true}; - _ -> - #'Extension'{extnID = ?'id-ce-basicConstraints', - extnValue = Data} - end; -extension({Id, Data, Critical}) -> - #'Extension'{extnID = Id, extnValue = Data, critical = Critical}. - - -publickey(#'RSAPrivateKey'{modulus=N, publicExponent=E}) -> - Public = #'RSAPublicKey'{modulus=N, publicExponent=E}, - Algo = #'PublicKeyAlgorithm'{algorithm= ?rsaEncryption, parameters='NULL'}, - #'OTPSubjectPublicKeyInfo'{algorithm = Algo, - subjectPublicKey = Public}; -publickey(#'DSAPrivateKey'{p=P, q=Q, g=G, y=Y}) -> - Algo = #'PublicKeyAlgorithm'{algorithm= ?'id-dsa', - parameters={params, #'Dss-Parms'{p=P, q=Q, g=G}}}, - #'OTPSubjectPublicKeyInfo'{algorithm = Algo, subjectPublicKey = Y}. - -validity(Opts) -> - DefFrom0 = calendar:gregorian_days_to_date(calendar:date_to_gregorian_days(date())-1), - DefTo0 = calendar:gregorian_days_to_date(calendar:date_to_gregorian_days(date())+7), - {DefFrom, DefTo} = proplists:get_value(validity, Opts, {DefFrom0, DefTo0}), - Format = fun({Y,M,D}) -> lists:flatten(io_lib:format("~w~2..0w~2..0w000000Z",[Y,M,D])) end, - #'Validity'{notBefore={generalTime, Format(DefFrom)}, - notAfter ={generalTime, Format(DefTo)}}. - -sign_algorithm(#'RSAPrivateKey'{}, Opts) -> - Type = case proplists:get_value(digest, Opts, sha1) of - sha1 -> ?'sha1WithRSAEncryption'; - sha512 -> ?'sha512WithRSAEncryption'; - sha384 -> ?'sha384WithRSAEncryption'; - sha256 -> ?'sha256WithRSAEncryption'; - md5 -> ?'md5WithRSAEncryption'; - md2 -> ?'md2WithRSAEncryption' - end, - {Type, 'NULL'}; -sign_algorithm(#'DSAPrivateKey'{p=P, q=Q, g=G}, _Opts) -> - {?'id-dsa-with-sha1', {params,#'Dss-Parms'{p=P, q=Q, g=G}}}. - -make_key(rsa, _Opts) -> - %% (OBS: for testing only) - gen_rsa2(64); -make_key(dsa, _Opts) -> - gen_dsa2(128, 20). %% Bytes i.e. {1024, 160} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% RSA key generation (OBS: for testing only) -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - --define(SMALL_PRIMES, [65537,97,89,83,79,73,71,67,61,59,53, - 47,43,41,37,31,29,23,19,17,13,11,7,5,3]). - -gen_rsa2(Size) -> - P = prime(Size), - Q = prime(Size), - N = P*Q, - Tot = (P - 1) * (Q - 1), - [E|_] = lists:dropwhile(fun(Candidate) -> (Tot rem Candidate) == 0 end, ?SMALL_PRIMES), - {D1,D2} = extended_gcd(E, Tot), - D = erlang:max(D1,D2), - case D < E of - true -> - gen_rsa2(Size); - false -> - {Co1,Co2} = extended_gcd(Q, P), - Co = erlang:max(Co1,Co2), - #'RSAPrivateKey'{version = 'two-prime', - modulus = N, - publicExponent = E, - privateExponent = D, - prime1 = P, - prime2 = Q, - exponent1 = D rem (P-1), - exponent2 = D rem (Q-1), - coefficient = Co - } - end. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% DSA key generation (OBS: for testing only) -%% See http://en.wikipedia.org/wiki/Digital_Signature_Algorithm -%% and the fips_186-3.pdf -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -gen_dsa2(LSize, NSize) -> - Q = prime(NSize), %% Choose N-bit prime Q - X0 = prime(LSize), - P0 = prime((LSize div 2) +1), - - %% Choose L-bit prime modulus P such that p-1 is a multiple of q. - case dsa_search(X0 div (2*Q*P0), P0, Q, 1000) of - error -> - gen_dsa2(LSize, NSize); - P -> - G = crypto:mod_exp(2, (P-1) div Q, P), % Choose G a number whose multiplicative order modulo p is q. - %% such that This may be done by setting g = h^(p-1)/q mod p, commonly h=2 is used. - - X = prime(20), %% Choose x by some random method, where 0 < x < q. - Y = crypto:mod_exp(G, X, P), %% Calculate y = g^x mod p. - - #'DSAPrivateKey'{version=0, p=P, q=Q, g=G, y=Y, x=X} - end. - -%% See fips_186-3.pdf -dsa_search(T, P0, Q, Iter) when Iter > 0 -> - P = 2*T*Q*P0 + 1, - case is_prime(crypto:mpint(P), 50) of - true -> P; - false -> dsa_search(T+1, P0, Q, Iter-1) - end; -dsa_search(_,_,_,_) -> - error. - - -%%%%%%% Crypto Math %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -prime(ByteSize) -> - Rand = odd_rand(ByteSize), - crypto:erlint(prime_odd(Rand, 0)). - -prime_odd(Rand, N) -> - case is_prime(Rand, 50) of - true -> - Rand; - false -> - NotPrime = crypto:erlint(Rand), - prime_odd(crypto:mpint(NotPrime+2), N+1) - end. - -%% see http://en.wikipedia.org/wiki/Fermat_primality_test -is_prime(_, 0) -> true; -is_prime(Candidate, Test) -> - CoPrime = odd_rand(<<0,0,0,4, 10000:32>>, Candidate), - case crypto:mod_exp(CoPrime, Candidate, Candidate) of - CoPrime -> is_prime(Candidate, Test-1); - _ -> false - end. - -odd_rand(Size) -> - Min = 1 bsl (Size*8-1), - Max = (1 bsl (Size*8))-1, - odd_rand(crypto:mpint(Min), crypto:mpint(Max)). - -odd_rand(Min,Max) -> - Rand = <<Sz:32, _/binary>> = crypto:rand_uniform(Min,Max), - BitSkip = (Sz+4)*8-1, - case Rand of - Odd = <<_:BitSkip, 1:1>> -> Odd; - Even = <<_:BitSkip, 0:1>> -> - crypto:mpint(crypto:erlint(Even)+1) - end. - -extended_gcd(A, B) -> - case A rem B of - 0 -> - {0, 1}; - N -> - {X, Y} = extended_gcd(B, N), - {Y, X-Y*(A div B)} - end. - -pem_to_der(File) -> - {ok, PemBin} = file:read_file(File), - public_key:pem_decode(PemBin). + KHFile = filename:join(UserDir, "known_hosts"), + file:write_file(KHFile, KnownHostsEnc). -der_to_pem(File, Entries) -> - PemBin = public_key:pem_encode(Entries), - file:write_file(File, PemBin). +clean_dsa(UserDir) -> + file:delete(filename:join(UserDir, "ssh_host_dsa_key")), + file:delete(filename:join(UserDir, "ssh_host_dsa_key.pub")), + file:delete(filename:join(UserDir, "known_hosts")). diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl index f959d50484..53d04620c5 100644 --- a/lib/ssh/test/ssh_to_openssh_SUITE.erl +++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2011. All Rights Reserved. +%% Copyright Ericsson AB 2008-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 @@ -42,8 +42,12 @@ init_per_suite(Config) -> case catch crypto:start() of ok -> - ssh_test_lib:make_dsa_files(Config), - Config; + case gen_tcp:connect("localhost", 22, []) of + {error,econnrefused} -> + {skip,"No openssh deamon"}; + _ -> + Config + end; _Else -> {skip,"Could not start crypto!"} end. @@ -100,26 +104,43 @@ all() -> false -> {skip, "openSSH not installed on host"}; _ -> - [erlang_shell_client_openssh_server, - erlang_client_openssh_server_exec, - erlang_client_openssh_server_exec_compressed, - erlang_server_openssh_client_exec, - erlang_server_openssh_client_exec_compressed, - erlang_client_openssh_server_setenv, - erlang_client_openssh_server_publickey_rsa, - erlang_client_openssh_server_publickey_dsa, - erlang_server_openssh_client_pulic_key_dsa, - erlang_client_openssh_server_password] + [{group, erlang_client}, + {group, erlang_server} + ] end. groups() -> - []. - -init_per_group(_GroupName, Config) -> - Config. + [{erlang_client, [], [erlang_shell_client_openssh_server, + erlang_client_openssh_server_exec, + erlang_client_openssh_server_exec_compressed, + erlang_client_openssh_server_setenv, + erlang_client_openssh_server_publickey_rsa, + erlang_client_openssh_server_publickey_dsa, + erlang_client_openssh_server_password]}, + {erlang_server, [], [erlang_server_openssh_client_exec, + erlang_server_openssh_client_exec_compressed, + erlang_server_openssh_client_pulic_key_dsa, + erlang_client_openssh_server_password]} + ]. + +init_per_group(erlang_server, Config) -> + DataDir = ?config(data_dir, Config), + UserDir = ?config(priv_dir, Config), + ssh_test_lib:setup_dsa(DataDir, UserDir), + Config; +init_per_group(_, Config) -> + Dir = ?config(priv_dir, Config), + {ok, _} = ssh_test_lib:get_id_keys(Dir), + Config. -end_per_group(_GroupName, Config) -> - Config. +end_per_group(erlang_server, Config) -> + UserDir = ?config(priv_dir, Config), + ssh_test_lib:clean_dsa(UserDir), + Config; +end_per_group(_, Config) -> + Dir = ?config(priv_dir, Config), + ssh_test_lib:remove_id_keys(Dir), + Config. %% TEST cases starts here. %%-------------------------------------------------------------------- @@ -131,8 +152,9 @@ erlang_shell_client_openssh_server(suite) -> erlang_shell_client_openssh_server(Config) when is_list(Config) -> process_flag(trap_exit, true), + UserDir = ?config(priv_dir, Config), IO = ssh_test_lib:start_io_server(), - Shell = ssh_test_lib:start_shell(?SSH_DEFAULT_PORT, IO), + Shell = ssh_test_lib:start_shell(?SSH_DEFAULT_PORT, IO, UserDir), IO ! {input, self(), "echo Hej\n"}, receive_hej(), IO ! {input, self(), "exit\n"}, @@ -228,7 +250,7 @@ erlang_server_openssh_client_exec(suite) -> []; erlang_server_openssh_client_exec(Config) when is_list(Config) -> - SystemDir = ?config(data_dir, Config), + SystemDir = ?config(priv_dir, Config), {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, {failfun, fun ssh_test_lib:failfun/2}]), @@ -257,7 +279,7 @@ erlang_server_openssh_client_exec_compressed(suite) -> []; erlang_server_openssh_client_exec_compressed(Config) when is_list(Config) -> - SystemDir = ?config(data_dir, Config), + SystemDir = ?config(priv_dir, Config), {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, {compression, zlib}, {failfun, fun ssh_test_lib:failfun/2}]), @@ -346,7 +368,9 @@ erlang_client_openssh_server_publickey_rsa(Config) when is_list(Config) -> ok = ssh:close(ConnectionRef), ok = file:delete(filename:join(UserDir, "id_rsa")); {error, enoent} -> - {skip, "no ~/.ssh/id_rsa"} + {skip, "no ~/.ssh/id_rsa"}; + {error, Reason} -> + {skip, Reason} end. %%-------------------------------------------------------------------- @@ -372,7 +396,9 @@ erlang_client_openssh_server_publickey_dsa(Config) when is_list(Config) -> ok = ssh:close(ConnectionRef), ok = file:delete(filename:join(UserDir, "id_dsa")); {error, enoent} -> - {skip, "no ~/.ssh/id_dsa"} + {skip, "no ~/.ssh/id_dsa"}; + {error, Reason} -> + {skip, Reason} end. %%-------------------------------------------------------------------- @@ -383,7 +409,7 @@ erlang_server_openssh_client_pulic_key_dsa(suite) -> []; erlang_server_openssh_client_pulic_key_dsa(Config) when is_list(Config) -> - SystemDir = ?config(data_dir, Config), + SystemDir = ?config(priv_dir, Config), {Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir}, {public_key_alg, ssh_dsa}, {failfun, fun ssh_test_lib:failfun/2}]), diff --git a/lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key b/lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key new file mode 100644 index 0000000000..51ab6fbd88 --- /dev/null +++ b/lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key @@ -0,0 +1,13 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBuwIBAAKBgQCClaHzE2ul0gKSUxah5W0W8UiJLy4hXngKEqpaUq9SSdVdY2LK +wVfKH1gt5iuaf1FfzOhsIC9G/GLnjYttXZc92cv/Gfe3gR+s0ni2++MX+T++mE/Q +diltXv/Hp27PybS67SmiFW7I+RWnT2OKlMPtw2oUuKeztCe5UWjaj/y5FQIVAPLA +l9RpiU30Z87NRAHY3NTRaqtrAoGANMRxw8UfdtNVR0CrQj3AgPaXOGE4d+G4Gp4X +skvnCHycSVAjtYxebUkzUzt5Q6f/IabuLUdge3gXrc8BetvrcKbp+XZgM0/Vj2CF +Ymmy3in6kzGZq7Fw1sZaku6AOU8vLa5woBT2vAcHLLT1bLAzj7viL048T6MfjrOP +ef8nHvACgYBhDWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah +/XcF3DeRF+eEoz48wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+U +ykSTXYUbtsfTNRFQGBW2/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0CgIVAN4wtL5W +Lv62jKcdskxNyz2NQoBx +-----END DSA PRIVATE KEY----- + diff --git a/lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key.pub b/lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key.pub new file mode 100644 index 0000000000..4dbb1305b0 --- /dev/null +++ b/lib/ssh/test/ssh_to_openssh_SUITE_data/ssh_host_dsa_key.pub @@ -0,0 +1,11 @@ +---- BEGIN SSH2 PUBLIC KEY ---- +AAAAB3NzaC1kc3MAAACBAIKVofMTa6XSApJTFqHlbRbxSIkvLiFeeAoSqlpSr1JJ1V1j +YsrBV8ofWC3mK5p/UV/M6GwgL0b8YueNi21dlz3Zy/8Z97eBH6zSeLb74xf5P76YT9B2 +KW1e/8enbs/JtLrtKaIVbsj5FadPY4qUw+3DahS4p7O0J7lRaNqP/LkVAAAAFQDywJfU +aYlN9GfOzUQB2NzU0WqrawAAAIA0xHHDxR9201VHQKtCPcCA9pc4YTh34bganheyS+cI +fJxJUCO1jF5tSTNTO3lDp/8hpu4tR2B7eBetzwF62+twpun5dmAzT9WPYIViabLeKfqT +MZmrsXDWxlqS7oA5Ty8trnCgFPa8BwcstPVssDOPu+IvTjxPox+Os495/yce8AAAAIBh +DWFQJ1mf99sg92LalVq1dHLmVXb3PTJDfCO/Gz5NFmj9EZbAtdah/XcF3DeRF+eEoz48 +wQF/ExVxSMIhLdL+o+ElpVhlM7Yii+T7dPhkQfEul6zZXu+UykSTXYUbtsfTNRFQGBW2 +/GfnEc0mnIxfn9v10NEWMzlq5z9wT9P0Cg== +---- END SSH2 PUBLIC KEY ---- 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/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl index e5adb84932..2f29954dc9 100644 --- a/lib/stdlib/src/erl_lint.erl +++ b/lib/stdlib/src/erl_lint.erl @@ -1804,12 +1804,19 @@ guard_test(G, Vt, St0) -> %% Specially handle record type test here. guard_test2({call,Line,{atom,Lr,record},[E,A]}, Vt, St0) -> gexpr({call,Line,{atom,Lr,is_record},[E,A]}, Vt, St0); -guard_test2({call,_Line,{atom,_La,F},As}=G, Vt, St0) -> +guard_test2({call,Line,{atom,_La,F},As}=G, Vt, St0) -> {Asvt,St1} = gexpr_list(As, Vt, St0), %Always check this. A = length(As), case erl_internal:type_test(F, A) of - true when F =/= is_record -> {Asvt,St1}; - _ -> gexpr(G, Vt, St0) + true when F =/= is_record -> + case no_guard_bif_clash(St1, {F,A}) of + false -> + {Asvt,add_error(Line, {illegal_guard_local_call,{F,A}}, St1)}; + true -> + {Asvt,St1} + end; + _ -> + gexpr(G, Vt, St0) end; guard_test2(G, Vt, St) -> %% Everything else is a guard expression. diff --git a/lib/stdlib/src/error_logger_file_h.erl b/lib/stdlib/src/error_logger_file_h.erl index ee4f0b3a51..08f1873803 100644 --- a/lib/stdlib/src/error_logger_file_h.erl +++ b/lib/stdlib/src/error_logger_file_h.erl @@ -104,7 +104,7 @@ code_change(_OldVsn, State, _Extra) -> %%% ------------------------------------------------------ tag_event(Event) -> - {erlang:localtime(), Event}. + {erlang:universaltime(), Event}. write_events(Fd, Events) -> write_events1(Fd, lists:reverse(Events)). @@ -169,23 +169,18 @@ write_event(_, _) -> maybe_utc(Time) -> UTC = case application:get_env(sasl, utc_log) of - {ok, Val} -> - Val; + {ok, Val} -> Val; undefined -> %% Backwards compatible: case application:get_env(stdlib, utc_log) of - {ok, Val} -> - Val; - undefined -> - false + {ok, Val} -> Val; + undefined -> false end end, - if - UTC =:= true -> - {utc, calendar:local_time_to_universal_time(Time)}; - true -> - Time - end. + maybe_utc(Time, UTC). + +maybe_utc(Time, true) -> {utc, Time}; +maybe_utc(Time, _) -> {local, calendar:universal_time_to_local_time(Time)}. format_report(Rep) when is_list(Rep) -> case string_p(Rep) of @@ -238,7 +233,7 @@ write_time(Time) -> write_time(Time, "ERROR REPORT"). write_time({utc,{{Y,Mo,D},{H,Mi,S}}}, Type) -> io_lib:format("~n=~s==== ~p-~s-~p::~s:~s:~s UTC ===~n", [Type,D,month(Mo),Y,t(H),t(Mi),t(S)]); -write_time({{Y,Mo,D},{H,Mi,S}}, Type) -> +write_time({local, {{Y,Mo,D},{H,Mi,S}}}, Type) -> io_lib:format("~n=~s==== ~p-~s-~p::~s:~s:~s ===~n", [Type,D,month(Mo),Y,t(H),t(Mi),t(S)]). diff --git a/lib/stdlib/src/error_logger_tty_h.erl b/lib/stdlib/src/error_logger_tty_h.erl index fa13fbb2bd..48e069a407 100644 --- a/lib/stdlib/src/error_logger_tty_h.erl +++ b/lib/stdlib/src/error_logger_tty_h.erl @@ -97,7 +97,7 @@ set_group_leader() -> end. tag_event(Event) -> - {erlang:localtime(), Event}. + {erlang:universaltime(), Event}. write_events(Events,IOMod) -> write_events1(lists:reverse(Events),IOMod). @@ -162,23 +162,18 @@ write_event({_Time, _Error},_IOMod) -> maybe_utc(Time) -> UTC = case application:get_env(sasl, utc_log) of - {ok, Val} -> - Val; + {ok, Val} -> Val; undefined -> %% Backwards compatible: case application:get_env(stdlib, utc_log) of - {ok, Val} -> - Val; - undefined -> - false + {ok, Val} -> Val; + undefined -> false end end, - if - UTC =:= true -> - {utc, calendar:local_time_to_universal_time(Time)}; - true -> - Time - end. + maybe_utc(Time, UTC). + +maybe_utc(Time, true) -> {utc, Time}; +maybe_utc(Time, _) -> {local, calendar:universal_time_to_local_time(Time)}. format(IOMod, String) -> format(IOMod, String, []). format(io_lib, String, Args) -> io_lib:format(String, Args); @@ -234,7 +229,7 @@ write_time(Time) -> write_time(Time, "ERROR REPORT"). write_time({utc,{{Y,Mo,D},{H,Mi,S}}},Type) -> io_lib:format("~n=~s==== ~p-~s-~p::~s:~s:~s UTC ===~n", [Type,D,month(Mo),Y,t(H),t(Mi),t(S)]); -write_time({{Y,Mo,D},{H,Mi,S}},Type) -> +write_time({local, {{Y,Mo,D},{H,Mi,S}}},Type) -> io_lib:format("~n=~s==== ~p-~s-~p::~s:~s:~s ===~n", [Type,D,month(Mo),Y,t(H),t(Mi),t(S)]). diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl index 9041adbe5c..e4c7fd5b02 100644 --- a/lib/stdlib/test/erl_lint_SUITE.erl +++ b/lib/stdlib/test/erl_lint_SUITE.erl @@ -2631,7 +2631,24 @@ bif_clash(Config) when is_list(Config) -> binary_part(A,B,C). ">>, [warn_unused_import], - {warnings,[{2,erl_lint,{redefine_bif_import,{binary_part,3}}}]}} + {warnings,[{2,erl_lint,{redefine_bif_import,{binary_part,3}}}]}}, + %% Don't accept call to a guard BIF if there is a local definition + %% or an import with the same name. + {clash21, + <<"-export([is_list/1]). + -import(x, [is_tuple/1]). + x(T) when is_tuple(T) -> ok; + x(T) when is_list(T) -> ok. + y(T) when is_tuple(T) =:= true -> ok; + y(T) when is_list(T) =:= true -> ok. + is_list(_) -> + ok. + ">>, + [{no_auto_import,[{is_tuple,1}]}], + {errors,[{3,erl_lint,{illegal_guard_local_call,{is_tuple,1}}}, + {4,erl_lint,{illegal_guard_local_call,{is_list,1}}}, + {5,erl_lint,{illegal_guard_local_call,{is_tuple,1}}}, + {6,erl_lint,{illegal_guard_local_call,{is_list,1}}}],[]}} ], ?line [] = run(Config, Ts), 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/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} |