diff options
Diffstat (limited to 'lib')
59 files changed, 1937 insertions, 1046 deletions
diff --git a/lib/compiler/src/beam_ssa_codegen.erl b/lib/compiler/src/beam_ssa_codegen.erl index 07f4c8b461..08641e2abc 100644 --- a/lib/compiler/src/beam_ssa_codegen.erl +++ b/lib/compiler/src/beam_ssa_codegen.erl @@ -764,9 +764,8 @@ defined(Linear, #cg{regs=Regs}) -> def([{L,#cg_blk{is=Is0,last=Last}=Blk0}|Bs], DefMap0, Regs) -> Def0 = def_get(L, DefMap0), - {Is,Def} = def_is(Is0, Regs, Def0, []), - Successors = successors(Last), - DefMap = def_successors(Successors, Def, DefMap0), + {Is,Def,MaybeDef} = def_is(Is0, Regs, Def0, []), + DefMap = def_successors(Last, Def, MaybeDef, DefMap0), Blk = Blk0#cg_blk{is=Is}, [{L,Blk}|def(Bs, DefMap, Regs)]; def([], _, _) -> []. @@ -780,6 +779,11 @@ def_get(L, DefMap) -> def_is([#cg_alloc{anno=Anno0}=I0|Is], Regs, Def, Acc) -> I = I0#cg_alloc{anno=Anno0#{def_yregs=>Def}}, def_is(Is, Regs, Def, [I|Acc]); +def_is([#cg_set{op=succeeded,args=[Var]}=I], Regs, Def, Acc) -> + %% Var will only be defined on the success branch of the `br` + %% for this block. + MaybeDef = def_add_yreg(Var, [], Regs), + {reverse(Acc, [I]),Def,MaybeDef}; def_is([#cg_set{op=kill_try_tag,args=[#b_var{}=Tag]}=I|Is], Regs, Def0, Acc) -> Def = ordsets:del_element(Tag, Def0), def_is(Is, Regs, Def, [I|Acc]); @@ -822,7 +826,7 @@ def_is([#cg_set{anno=Anno0,dst=Dst}=I0|Is], Regs, Def0, Acc) -> Def = def_add_yreg(Dst, Def0, Regs), def_is(Is, Regs, Def, [I|Acc]); def_is([], _, Def, Acc) -> - {reverse(Acc),Def}. + {reverse(Acc),Def,[]}. def_add_yreg(Dst, Def, Regs) -> case is_yreg(Dst, Regs) of @@ -830,6 +834,12 @@ def_add_yreg(Dst, Def, Regs) -> false -> Def end. +def_successors(#cg_br{bool=#b_var{},succ=Succ,fail=Fail}, Def, MaybeDef, DefMap0) -> + DefMap = def_successors([Fail], ordsets:subtract(Def, MaybeDef), DefMap0), + def_successors([Succ], Def, DefMap); +def_successors(Last, Def, [], DefMap) -> + def_successors(successors(Last), Def, DefMap). + def_successors([S|Ss], Def0, DefMap) -> case DefMap of #{S:=Def1} -> diff --git a/lib/compiler/src/beam_ssa_dead.erl b/lib/compiler/src/beam_ssa_dead.erl index 64b9b3e222..e78e4647a8 100644 --- a/lib/compiler/src/beam_ssa_dead.erl +++ b/lib/compiler/src/beam_ssa_dead.erl @@ -30,7 +30,7 @@ -import(lists, [append/1,keymember/3,last/1,member/2, takewhile/2,reverse/1]). --type used_vars() :: #{beam_ssa:label():=ordsets:ordset(beam_ssa:var_name())}. +-type used_vars() :: #{beam_ssa:label():=cerl_sets:set(beam_ssa:var_name())}. -type basic_type_test() :: atom() | {'is_tagged_tuple',pos_integer(),atom()}. -type type_test() :: basic_type_test() | {'not',basic_type_test()}. @@ -90,13 +90,11 @@ shortcut_opt(#st{bs=Blocks}=St) -> %% the diff.) %% %% Unfortunately, processing the blocks in reverse post order - %% potentially makes the time complexity quadratic or even cubic if - %% the ordset of unset variables grows large, instead of - %% linear for post order processing. We try to still get reasonable - %% compilation times by optimizations that will keep the constant - %% factor as low as possible, and we try to avoid the cubic time - %% complexity by trying to keep the set of unset variables as small - %% as possible. + %% potentially makes the time complexity quadratic, instead of + %% linear for post order processing. We avoid drastic slowdowns by + %% limiting how far we search forward to a common block that + %% both the success and failure label will reach (see the comment + %% in the first clause of shortcut_2/5). Ls = beam_ssa:rpo(Blocks), shortcut_opt(Ls, #{}, St). @@ -124,10 +122,15 @@ shortcut_terminator(#b_br{bool=#b_var{}=Bool,succ=Succ0,fail=Fail0}=Br, Is, From, Bs, St0) -> St = St0#st{target=one_way}, RelOp = get_rel_op(Bool, Is), - SuccBs = bind_var(Bool, #b_literal{val=true}, Bs), + + %% The boolean in a `br` is seldom used by the successors. By + %% not binding its value unless it is actually used we might be able + %% to skip some work in shortcut/4 and sub/2. + SuccBs = bind_var_if_used(Succ0, Bool, #b_literal{val=true}, Bs, St), BrSucc = shortcut(Succ0, From, SuccBs, St#st{rel_op=RelOp}), - FailBs = bind_var(Bool, #b_literal{val=false}, Bs), + FailBs = bind_var_if_used(Fail0, Bool, #b_literal{val=false}, Bs, St), BrFail = shortcut(Fail0, From, FailBs, St#st{rel_op=invert_op(RelOp)}), + case {BrSucc,BrFail} of {#b_br{bool=#b_literal{val=true},succ=Succ}, #b_br{bool=#b_literal{val=true},succ=Fail}} @@ -152,8 +155,14 @@ shortcut_switch([{Lit,L0}|T], Bool, From, Bs, St0) -> [{Lit,L}|shortcut_switch(T, Bool, From, Bs, St0)]; shortcut_switch([], _, _, _, _) -> []. +shortcut(L, _From, Bs, #st{rel_op=none,target=one_way}) when map_size(Bs) =:= 0 -> + %% There is no way that we can find a suitable branch, because there is no + %% relational operator stored, there are no bindings, and the block L can't + %% have any phi nodes from which we could pick bindings because when the target + %% is `one_way`, it implies the From block has a two-way `br` terminator. + #b_br{bool=#b_literal{val=true},succ=L,fail=L}; shortcut(L, From, Bs, St) -> - shortcut_1(L, From, Bs, ordsets:new(), St). + shortcut_1(L, From, Bs, cerl_sets:new(), St). shortcut_1(L, From, Bs0, UnsetVars0, St) -> case shortcut_2(L, From, Bs0, UnsetVars0, St) of @@ -170,7 +179,19 @@ shortcut_1(L, From, Bs0, UnsetVars0, St) -> end. %% Try to shortcut this block, branching to a successor. -shortcut_2(L, From, Bs0, UnsetVars0, St) -> +shortcut_2(L, From, Bs, UnsetVars, St) -> + case cerl_sets:size(UnsetVars) of + SetSize when SetSize > 128 -> + %% This is an heuristic to limit the search for a forced label + %% before it drastically slows down the compiler. Experiments + %% with scripts/diffable showed that limits larger than 31 did not + %% find any more opportunities for optimization. + none; + _SetSize -> + shortcut_3(L, From, Bs, UnsetVars, St) + end. + +shortcut_3(L, From, Bs0, UnsetVars0, St) -> #b_blk{is=Is,last=Last} = get_block(L, St), case eval_is(Is, From, Bs0, St) of none -> @@ -347,7 +368,7 @@ update_unset_vars(L, Is, Br, UnsetVars, #st{skippable=Skippable}) -> %% Some variables defined in this block are used by %% successors. We must update the set of unset variables. SetInThisBlock = [V || #b_set{dst=V} <- Is], - ordsets:union(UnsetVars, ordsets:from_list(SetInThisBlock)) + cerl_sets:union(UnsetVars, cerl_sets:from_list(SetInThisBlock)) end. shortcut_two_way(#b_br{succ=Succ,fail=Fail}, From, Bs0, UnsetVars0, St0) -> @@ -376,14 +397,14 @@ is_br_safe(UnsetVars, Br, #st{us=Us}=St) -> %% A two-way branch never branches to a phi node, so there %% is no need to check for phi nodes here. - not member(V, UnsetVars) andalso - ordsets:is_disjoint(Used0, UnsetVars) andalso - ordsets:is_disjoint(Used1, UnsetVars); + not cerl_sets:is_element(V, UnsetVars) andalso + cerl_sets:is_disjoint(Used0, UnsetVars) andalso + cerl_sets:is_disjoint(Used1, UnsetVars); #b_br{succ=Same,fail=Same} -> %% An unconditional branch must not jump to %% a phi node. not is_forbidden(Same, St) andalso - ordsets:is_disjoint(map_get(Same, Us), UnsetVars) + cerl_sets:is_disjoint(map_get(Same, Us), UnsetVars) end. is_forbidden(L, St) -> @@ -500,6 +521,15 @@ eval_switch_1([], _Arg, _PrevOp, Fail) -> %% Fail is now either the failure label or 'none'. Fail. +bind_var_if_used(L, Var, Val0, Bs, #st{us=Us}) -> + case cerl_sets:is_element(Var, map_get(L, Us)) of + true -> + Val = get_value(Val0, Bs), + Bs#{Var=>Val}; + false -> + Bs + end. + bind_var(Var, Val0, Bs) -> Val = get_value(Val0, Bs), Bs#{Var=>Val}. @@ -989,7 +1019,7 @@ used_vars([{L,#b_blk{is=Is}=Blk}|Bs], UsedVars0, Skip0) -> %% shortcut_opt/1. Successors = beam_ssa:successors(Blk), - Used0 = used_vars_succ(Successors, L, UsedVars0, []), + Used0 = used_vars_succ(Successors, L, UsedVars0, cerl_sets:new()), Used = used_vars_blk(Blk, Used0), UsedVars = used_vars_phis(Is, L, Used, UsedVars0), @@ -1000,8 +1030,8 @@ used_vars([{L,#b_blk{is=Is}=Blk}|Bs], UsedVars0, Skip0) -> %% shortcut_opt/1. Defined0 = [Def || #b_set{dst=Def} <- Is], - Defined = ordsets:from_list(Defined0), - MaySkip = ordsets:is_disjoint(Defined, Used0), + Defined = cerl_sets:from_list(Defined0), + MaySkip = cerl_sets:is_disjoint(Defined, Used0), case MaySkip of true -> Skip = Skip0#{L=>true}, @@ -1018,11 +1048,11 @@ used_vars_succ([S|Ss], L, LiveMap, Live0) -> #{Key:=Live} -> %% The successor has a phi node, and the value for %% this block in the phi node is a variable. - used_vars_succ(Ss, L, LiveMap, ordsets:union(Live, Live0)); + used_vars_succ(Ss, L, LiveMap, cerl_sets:union(Live, Live0)); #{S:=Live} -> %% No phi node in the successor, or the value for %% this block in the phi node is a literal. - used_vars_succ(Ss, L, LiveMap, ordsets:union(Live, Live0)); + used_vars_succ(Ss, L, LiveMap, cerl_sets:union(Live, Live0)); #{} -> %% A peek_message block which has not been processed yet. used_vars_succ(Ss, L, LiveMap, Live0) @@ -1040,7 +1070,7 @@ used_vars_phis(Is, L, Live0, UsedVars0) -> case [{P,V} || {#b_var{}=V,P} <- PhiArgs] of [_|_]=PhiVars -> PhiLive0 = rel2fam(PhiVars), - PhiLive = [{{L,P},ordsets:union(ordsets:from_list(Vs), Live0)} || + PhiLive = [{{L,P},cerl_sets:union(cerl_sets:from_list(Vs), Live0)} || {P,Vs} <- PhiLive0], maps:merge(UsedVars, maps:from_list(PhiLive)); [] -> @@ -1050,14 +1080,14 @@ used_vars_phis(Is, L, Live0, UsedVars0) -> end. used_vars_blk(#b_blk{is=Is,last=Last}, Used0) -> - Used = ordsets:union(Used0, beam_ssa:used(Last)), + Used = cerl_sets:union(Used0, cerl_sets:from_list(beam_ssa:used(Last))), used_vars_is(reverse(Is), Used). used_vars_is([#b_set{op=phi}|Is], Used) -> used_vars_is(Is, Used); used_vars_is([#b_set{dst=Dst}=I|Is], Used0) -> - Used1 = ordsets:union(Used0, beam_ssa:used(I)), - Used = ordsets:del_element(Dst, Used1), + Used1 = cerl_sets:union(Used0, cerl_sets:from_list(beam_ssa:used(I))), + Used = cerl_sets:del_element(Dst, Used1), used_vars_is(Is, Used); used_vars_is([], Used) -> Used. @@ -1066,8 +1096,9 @@ used_vars_is([], Used) -> %%% Common utilities. %%% -sub(#b_set{args=Args}=I, Sub) -> - I#b_set{args=[sub_arg(A, Sub) || A <- Args]}. +sub(#b_set{args=Args}=I, Sub) when map_size(Sub) =/= 0 -> + I#b_set{args=[sub_arg(A, Sub) || A <- Args]}; +sub(I, _Sub) -> I. sub_arg(#b_var{}=Old, Sub) -> case Sub of diff --git a/lib/compiler/src/beam_ssa_opt.erl b/lib/compiler/src/beam_ssa_opt.erl index 229edc6a1d..d87c66c272 100644 --- a/lib/compiler/src/beam_ssa_opt.erl +++ b/lib/compiler/src/beam_ssa_opt.erl @@ -1939,12 +1939,24 @@ verify_merge_is(_) -> is_merge_allowed(_, #b_blk{}, #b_blk{is=[#b_set{op=peek_message}|_]}) -> false; -is_merge_allowed(L, #b_blk{last=#b_br{}}=Blk, #b_blk{}) -> +is_merge_allowed(L, #b_blk{last=#b_br{}}=Blk, #b_blk{is=Is}) -> %% The predecessor block must have exactly one successor (L) for %% the merge to be safe. case beam_ssa:successors(Blk) of - [L] -> true; - [_|_] -> false + [L] -> + case Is of + [#b_set{op=phi,args=[_]}|_] -> + %% The type optimizer pass must have been + %% turned off, since it would have removed this + %% redundant phi node. Refuse to merge the blocks + %% to ensure that this phi node remains at the + %% beginning of a block. + false; + _ -> + true + end; + [_|_] -> + false end; is_merge_allowed(_, #b_blk{last=#b_switch{}}, #b_blk{}) -> false. diff --git a/lib/compiler/src/beam_ssa_share.erl b/lib/compiler/src/beam_ssa_share.erl index 426efa2cc9..73983bd34a 100644 --- a/lib/compiler/src/beam_ssa_share.erl +++ b/lib/compiler/src/beam_ssa_share.erl @@ -303,8 +303,12 @@ canonical_is([#b_ret{arg=Arg}], VarMap, Acc0) -> Acc0 end, {{ret,canonical_arg(Arg, VarMap),Acc1},VarMap}; -canonical_is([#b_br{bool=#b_var{},fail=Fail}], VarMap, Acc) -> - {{br,succ,Fail,Acc},VarMap}; +canonical_is([#b_br{bool=#b_var{}=Arg,fail=Fail}], VarMap, Acc) -> + %% A previous buggy version of this code omitted the canonicalized + %% argument in the return value. Unfortunately, that worked most + %% of the time, except when `br` terminator referenced a variable + %% defined in a previous block instead of in the same block. + {{br,canonical_arg(Arg, VarMap),succ,Fail,Acc},VarMap}; canonical_is([#b_br{succ=Succ}], VarMap, Acc) -> {{br,Succ,Acc},VarMap}; canonical_is([], VarMap, Acc) -> diff --git a/lib/compiler/src/beam_ssa_type.erl b/lib/compiler/src/beam_ssa_type.erl index 68920e7dd3..3c06c83e2e 100644 --- a/lib/compiler/src/beam_ssa_type.erl +++ b/lib/compiler/src/beam_ssa_type.erl @@ -160,6 +160,10 @@ opt_finish_1([Arg | Args], [TypeMap | TypeMaps], ParamInfo0) -> case join(maps:values(TypeMap)) of any -> opt_finish_1(Args, TypeMaps, ParamInfo0); + none -> + %% This function will never be called. Pretend that we don't + %% know the type for this argument. + opt_finish_1(Args, TypeMaps, ParamInfo0); JoinedType -> JoinedType = verified_type(JoinedType), ParamInfo = ParamInfo0#{ Arg => validator_anno(JoinedType) }, diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl index ebe9631e09..349d74eb58 100644 --- a/lib/compiler/src/beam_validator.erl +++ b/lib/compiler/src/beam_validator.erl @@ -1068,8 +1068,11 @@ verify_get_map(Fail, Src, List, Vst0) -> %% {get_map_elements,{f,7},{x,1},{list,[{atom,a},{x,1},{atom,b},{x,2}]}}. %% %% If 'a' exists but not 'b', {x,1} is overwritten when we jump to {f,7}. +%% +%% We must be careful to preserve the uninitialized status for Y registers +%% that have been allocated but not yet defined. clobber_map_vals([Key,Dst|T], Map, Vst0) -> - case is_reg_defined(Dst, Vst0) of + case is_reg_initialized(Dst, Vst0) of true -> Vst = extract_term(term, {bif,map_get}, [Key, Map], Dst, Vst0), clobber_map_vals(T, Map, Vst); @@ -1079,6 +1082,17 @@ clobber_map_vals([Key,Dst|T], Map, Vst0) -> clobber_map_vals([], _Map, Vst) -> Vst. +is_reg_initialized({x,_}=Reg, #vst{current=#st{xs=Xs}}) -> + is_map_key(Reg, Xs); +is_reg_initialized({y,_}=Reg, #vst{current=#st{ys=Ys}}) -> + case Ys of + #{Reg:=Val} -> + Val =/= uninitialized; + #{} -> + false + end; +is_reg_initialized(V, #vst{}) -> error({not_a_register, V}). + extract_map_keys([Key,_Val|T]) -> [Key|extract_map_keys(T)]; extract_map_keys([]) -> []. @@ -1604,13 +1618,8 @@ infer_types_1(#value{op={bif,'=:='},args=[LHS,RHS]}) -> end; infer_types_1(#value{op={bif,element},args=[{integer,Index}=Key,Tuple]}) -> fun(Val, S) -> - case is_value_alive(Tuple, S) of - true -> - Type = {tuple,[Index], #{ Key => get_term_type(Val, S) }}, - update_type(fun meet/2, Type, Tuple, S); - false -> - S - end + Type = {tuple,[Index], #{ Key => get_term_type(Val, S) }}, + update_type(fun meet/2, Type, Tuple, S) end; infer_types_1(#value{op={bif,is_atom},args=[Src]}) -> infer_type_test_bif({atom,[]}, Src); @@ -1634,10 +1643,7 @@ infer_types_1(#value{op={bif,is_tuple},args=[Src]}) -> infer_type_test_bif({tuple,[0],#{}}, Src); infer_types_1(#value{op={bif,tuple_size}, args=[Tuple]}) -> fun({integer,Arity}, S) -> - case is_value_alive(Tuple, S) of - true -> update_type(fun meet/2, {tuple,Arity,#{}}, Tuple, S); - false -> S - end; + update_type(fun meet/2, {tuple,Arity,#{}}, Tuple, S); (_, S) -> S end; infer_types_1(_) -> @@ -1645,10 +1651,7 @@ infer_types_1(_) -> infer_type_test_bif(Type, Src) -> fun({atom,true}, S) -> - case is_value_alive(Src, S) of - true -> update_type(fun meet/2, Type, Src, S); - false -> S - end; + update_type(fun meet/2, Type, Src, S); (_, S) -> S end. @@ -1885,10 +1888,6 @@ check_try_catch_tags(Type, {y,N}=Reg, Vst) -> ok end. -is_reg_defined({x,_}=Reg, #vst{current=#st{xs=Xs}}) -> is_map_key(Reg, Xs); -is_reg_defined({y,_}=Reg, #vst{current=#st{ys=Ys}}) -> is_map_key(Reg, Ys); -is_reg_defined(V, #vst{}) -> error({not_a_register, V}). - assert_term(Src, Vst) -> _ = get_term_type(Src, Vst), ok. @@ -2285,9 +2284,6 @@ get_raw_type(#value_ref{}=Ref, #vst{current=#st{vs=Vs}}) -> get_raw_type(Src, #vst{}) -> get_literal_type(Src). -is_value_alive(#value_ref{}=Ref, #vst{current=#st{vs=Vs}}) -> - is_map_key(Ref, Vs). - get_literal_type(nil=T) -> T; get_literal_type({atom,A}=T) when is_atom(A) -> T; get_literal_type({float,F}=T) when is_float(F) -> T; @@ -2469,25 +2465,44 @@ merge_vrefs(RefA, RefB, Merge, Counter) -> merge_values(Merge, VsA, VsB) -> maps:fold(fun(Spec, New, Acc) -> - merge_values_1(Spec, New, VsA, VsB, Acc) + mv_1(Spec, New, VsA, VsB, Acc) end, #{}, Merge). -merge_values_1(Same, Same, VsA, VsB, Acc) -> +mv_1(Same, Same, VsA, VsB, Acc0) -> %% We're merging different versions of the same value, so it's safe to %% reuse old entries if the type's unchanged. - #value{type=TypeA}=EntryA = map_get(Same, VsA), - #value{type=TypeB}=EntryB = map_get(Same, VsB), + #value{type=TypeA,args=Args}=EntryA = map_get(Same, VsA), + #value{type=TypeB,args=Args}=EntryB = map_get(Same, VsB), + Entry = case join(TypeA, TypeB) of TypeA -> EntryA; TypeB -> EntryB; JoinedType -> EntryA#value{type=JoinedType} end, - Acc#{ Same => Entry }; -merge_values_1({RefA, RefB}, New, VsA, VsB, Acc) -> + + Acc = Acc0#{ Same => Entry }, + + %% Type inference may depend on values that are no longer reachable from a + %% register, so all arguments must be merged into the new state. + mv_args(Args, VsA, VsB, Acc); +mv_1({RefA, RefB}, New, VsA, VsB, Acc) -> #value{type=TypeA} = map_get(RefA, VsA), #value{type=TypeB} = map_get(RefB, VsB), Acc#{ New => #value{op=join,args=[],type=join(TypeA, TypeB)} }. +mv_args([#value_ref{}=Arg | Args], VsA, VsB, Acc0) -> + case Acc0 of + #{ Arg := _ } -> + mv_args(Args, VsA, VsB, Acc0); + #{} -> + Acc = mv_1(Arg, Arg, VsA, VsB, Acc0), + mv_args(Args, VsA, VsB, Acc) + end; +mv_args([_ | Args], VsA, VsB, Acc) -> + mv_args(Args, VsA, VsB, Acc); +mv_args([], _VsA, _VsB, Acc) -> + Acc. + merge_fragility(FragileA, FragileB) -> cerl_sets:union(FragileA, FragileB). diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl index 28db8986ff..0325c714d0 100644 --- a/lib/compiler/src/compile.erl +++ b/lib/compiler/src/compile.erl @@ -268,8 +268,11 @@ expand_opt(r21, Os) -> [no_put_tuple2 | expand_opt(no_bsm3, Os)]; expand_opt({debug_info_key,_}=O, Os) -> [encrypt_debug_info,O|Os]; -expand_opt(no_type_opt, Os) -> - [no_ssa_opt_type_start, +expand_opt(no_type_opt=O, Os) -> + %% Be sure to keep the no_type_opt option so that it will + %% be recorded in the BEAM file, allowing the test suites + %% to recompile the file with this option. + [O,no_ssa_opt_type_start, no_ssa_opt_type_continue, no_ssa_opt_type_finish | Os]; expand_opt(O, Os) -> [O|Os]. diff --git a/lib/compiler/test/Makefile b/lib/compiler/test/Makefile index db8eb7e2e1..7be23fbb93 100644 --- a/lib/compiler/test/Makefile +++ b/lib/compiler/test/Makefile @@ -109,6 +109,8 @@ NO_MOD_OPT = $(NO_OPT) NO_SSA_OPT = $(NO_OPT) +NO_TYPE_OPT = $(NO_OPT) + NO_OPT_MODULES= $(NO_OPT:%=%_no_opt_SUITE) NO_OPT_ERL_FILES= $(NO_OPT_MODULES:%=%.erl) POST_OPT_MODULES= $(NO_OPT:%=%_post_opt_SUITE) @@ -121,6 +123,8 @@ NO_MOD_OPT_MODULES= $(NO_MOD_OPT:%=%_no_module_opt_SUITE) NO_MOD_OPT_ERL_FILES= $(NO_MOD_OPT_MODULES:%=%.erl) NO_SSA_OPT_MODULES= $(NO_SSA_OPT:%=%_no_ssa_opt_SUITE) NO_SSA_OPT_ERL_FILES= $(NO_SSA_OPT_MODULES:%=%.erl) +NO_TYPE_OPT_MODULES= $(NO_TYPE_OPT:%=%_no_type_opt_SUITE) +NO_TYPE_OPT_ERL_FILES= $(NO_TYPE_OPT_MODULES:%=%.erl) ERL_FILES= $(MODULES:%=%.erl) CORE_FILES= $(CORE_MODULES:%=%.core) @@ -150,7 +154,7 @@ EBIN = . # ---------------------------------------------------- make_emakefile: $(NO_OPT_ERL_FILES) $(POST_OPT_ERL_FILES) $(NO_SSA_OPT_ERL_FILES) \ - $(INLINE_ERL_FILES) $(R21_ERL_FILES) $(NO_MOD_OPT_ERL_FILES) + $(INLINE_ERL_FILES) $(R21_ERL_FILES) $(NO_MOD_OPT_ERL_FILES) $(NO_TYPE_OPT_ERL_FILES) $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES) \ > $(EMAKEFILE) $(ERL_TOP)/make/make_emakefile +no_copt +no_postopt \ @@ -169,6 +173,8 @@ make_emakefile: $(NO_OPT_ERL_FILES) $(POST_OPT_ERL_FILES) $(NO_SSA_OPT_ERL_FILES -o$(EBIN) $(NO_MOD_OPT_MODULES) >> $(EMAKEFILE) $(ERL_TOP)/make/make_emakefile +from_core $(ERL_COMPILE_FLAGS) \ -o$(EBIN) $(CORE_MODULES) >> $(EMAKEFILE) + $(ERL_TOP)/make/make_emakefile +no_type_opt $(ERL_COMPILE_FLAGS) \ + -o$(EBIN) $(NO_TYPE_OPT_MODULES) >> $(EMAKEFILE) tests debug opt: make_emakefile erl $(ERL_MAKE_FLAGS) -make @@ -202,6 +208,10 @@ docs: %_no_module_opt_SUITE.erl: %_SUITE.erl sed -e 's;-module($(basename $<));-module($(basename $@));' $< > $@ +%_no_type_opt_SUITE.erl: %_SUITE.erl + sed -e 's;-module($(basename $<));-module($(basename $@));' $< > $@ + + # ---------------------------------------------------- # Release Target # ---------------------------------------------------- @@ -216,7 +226,8 @@ release_tests_spec: make_emakefile $(INSTALL_DATA) $(NO_OPT_ERL_FILES) $(POST_OPT_ERL_FILES) \ $(INLINE_ERL_FILES) $(R21_ERL_FILES) \ $(NO_MOD_OPT_ERL_FILES) \ - $(NO_SSA_OPT_ERL_FILES) "$(RELSYSDIR)" + $(NO_SSA_OPT_ERL_FILES) \ + $(NO_TYPE_OPT_ERL_FILES) "$(RELSYSDIR)" $(INSTALL_DATA) $(CORE_FILES) "$(RELSYSDIR)" for file in $(ERL_DUMMY_FILES); do \ module=`basename $$file .erl`; \ diff --git a/lib/compiler/test/beam_ssa_SUITE.erl b/lib/compiler/test/beam_ssa_SUITE.erl index dd1b7ddcd3..3b510f3528 100644 --- a/lib/compiler/test/beam_ssa_SUITE.erl +++ b/lib/compiler/test/beam_ssa_SUITE.erl @@ -23,7 +23,7 @@ init_per_group/2,end_per_group/2, calls/1,tuple_matching/1,recv/1,maps/1, cover_ssa_dead/1,combine_sw/1,share_opt/1, - beam_ssa_dead_crash/1]). + beam_ssa_dead_crash/1,stack_init/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -39,7 +39,8 @@ groups() -> cover_ssa_dead, combine_sw, share_opt, - beam_ssa_dead_crash + beam_ssa_dead_crash, + stack_init ]}]. init_per_suite(Config) -> @@ -524,9 +525,11 @@ do_comb_sw_2(X) -> erase(?MODULE). share_opt(_Config) -> - ok = do_share_opt(0). + ok = do_share_opt_1(0), + ok = do_share_opt_2(), + ok. -do_share_opt(A) -> +do_share_opt_1(A) -> %% The compiler would be stuck in an infinite loop in beam_ssa_share. case A of 0 -> a; @@ -535,6 +538,26 @@ do_share_opt(A) -> end, receive after 1 -> ok end. +do_share_opt_2() -> + ok = sopt_2({[pointtopoint], [{dstaddr,any}]}, ok), + ok = sopt_2({[broadcast], [{broadaddr,any}]}, ok), + ok = sopt_2({[], []}, ok), + ok. + +sopt_2({Flags, Opts}, ok) -> + Broadcast = lists:member(broadcast, Flags), + P2P = lists:member(pointtopoint, Flags), + case Opts of + %% The following two clauses would be combined to one, silently + %% discarding the guard test of the P2P variable. + [{broadaddr,_}|Os] when Broadcast -> + sopt_2({Flags, Os}, ok); + [{dstaddr,_}|Os] when P2P -> + sopt_2({Flags, Os}, ok); + [] -> + ok + end. + beam_ssa_dead_crash(_Config) -> not_A_B = do_beam_ssa_dead_crash(id(false), id(true)), not_A_not_B = do_beam_ssa_dead_crash(false, false), @@ -589,6 +612,30 @@ do_beam_ssa_dead_crash(A, B) -> end end. +stack_init(_Config) -> + 6 = stack_init(a, #{a => [1,2,3]}), + 0 = stack_init(missing, #{}), + ok. + +stack_init(Key, Map) -> + %% beam_ssa_codegen would wrongly assume that y(0) would always be + %% initialized by the `get_map_elements` instruction that follows, and + %% would set up the stack frame using an `allocate` instruction and + %% would not generate an `init` instruction to initialize y(0). + Res = case Map of + #{Key := Elements} -> + %% Elements will be assigned to y(0) if the key Key exists. + lists:foldl(fun(El, Acc) -> + Acc + El + end, 0, Elements); + #{} -> + %% y(0) will be left uninitialized when the key is not + %% present in the map. + 0 + end, + %% y(0) would be uninitialized here if the key was not present in the map + %% (if the second clause was executed). + id(Res). %% The identity function. id(I) -> I. diff --git a/lib/compiler/test/beam_type_SUITE.erl b/lib/compiler/test/beam_type_SUITE.erl index 076a604aa4..a99dee48aa 100644 --- a/lib/compiler/test/beam_type_SUITE.erl +++ b/lib/compiler/test/beam_type_SUITE.erl @@ -24,7 +24,8 @@ integers/1,numbers/1,coverage/1,booleans/1,setelement/1, cons/1,tuple/1,record_float/1,binary_float/1,float_compare/1, arity_checks/1,elixir_binaries/1,find_best/1, - test_size/1,cover_lists_functions/1,list_append/1,bad_binary_unit/1]). + test_size/1,cover_lists_functions/1,list_append/1,bad_binary_unit/1, + none_argument/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -49,7 +50,8 @@ groups() -> test_size, cover_lists_functions, list_append, - bad_binary_unit + bad_binary_unit, + none_argument ]}]. init_per_suite(Config) -> @@ -518,5 +520,24 @@ bad_binary_unit(_Config) -> false = is_binary(Bitstring), ok. +%% ERL-1013: The compiler would crash during the type optimization pass. +none_argument(_Config) -> + Binary = id(<<3:16, 42>>), + error = id(case Binary of + <<Len:16, Body/binary>> when length(Body) == Len - 2 -> + %% The type for Body will be none. It means + %% that this clause will never match and that + %% uncompress/1 will never be called. + uncompress(Body); + _ -> + error + end), + ok. + +uncompress(CompressedBinary) -> + %% The type for CompressedBinary is none, which beam_ssa_type + %% did not handle properly. + zlib:uncompress(CompressedBinary). + id(I) -> I. diff --git a/lib/compiler/test/beam_validator_SUITE.erl b/lib/compiler/test/beam_validator_SUITE.erl index 6b1438abdd..20f6cb2691 100644 --- a/lib/compiler/test/beam_validator_SUITE.erl +++ b/lib/compiler/test/beam_validator_SUITE.erl @@ -681,11 +681,16 @@ infer_on_eq_4(T) -> %% ERIERL-348; types were inferred for dead values, causing validation to fail. +-record(idv, {key}). + infer_dead_value(Config) when is_list(Config) -> a = idv_1({a, b, c, d, e, f, g}, {0, 0, 0, 0, 0, 0, 0}), b = idv_1({a, b, c, d, 0, 0, 0}, {a, b, c, d, 0, 0, 0}), c = idv_1({0, 0, 0, 0, 0, f, g}, {0, 0, 0, 0, 0, f, g}), error = idv_1(gurka, gaffel), + + ok = idv_2(id(#idv{})), + ok. idv_1({_A, _B, _C, _D, _E, _F, _G}, @@ -700,6 +705,23 @@ idv_1({_A, _B, _C, _D, _E, F, G}, idv_1(_A, _B) -> error. +%% ERL-995: The first solution to ERIERL-348 was incomplete and caused +%% validation to fail when living values depended on delayed type inference on +%% "dead" values. + +idv_2(State) -> + Flag = (State#idv.key == undefined), + case id(gurka) of + {_} -> id([Flag]); + _ -> ok + end, + if + Flag -> idv_called_once(State); + true -> ok + end. + +idv_called_once(_State) -> ok. + %%%------------------------------------------------------------------------- transform_remove(Remove, Module) -> diff --git a/lib/compiler/test/test_lib.erl b/lib/compiler/test/test_lib.erl index 3348c6e9ea..34410e4b2a 100644 --- a/lib/compiler/test/test_lib.erl +++ b/lib/compiler/test/test_lib.erl @@ -97,7 +97,8 @@ get_data_dir(Config) -> Data2 = re:replace(Data1, "_post_opt_SUITE", "_SUITE", Opts), Data3 = re:replace(Data2, "_inline_SUITE", "_SUITE", Opts), Data4 = re:replace(Data3, "_r21_SUITE", "_SUITE", Opts), - Data = re:replace(Data4, "_no_module_opt_SUITE", "_SUITE", Opts), + Data5 = re:replace(Data4, "_no_module_opt_SUITE", "_SUITE", Opts), + Data = re:replace(Data5, "_no_type_opt_SUITE", "_SUITE", Opts), re:replace(Data, "_no_ssa_opt_SUITE", "_SUITE", Opts). is_cloned_mod(Mod) -> diff --git a/lib/megaco/test/Makefile b/lib/megaco/test/Makefile index 4ddd73eea1..b4e31765b8 100644 --- a/lib/megaco/test/Makefile +++ b/lib/megaco/test/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 1999-2016. All Rights Reserved. +# Copyright Ericsson AB 1999-2019. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -102,6 +102,9 @@ endif ERL_COMPILE_FLAGS += $(MEGACO_ERL_COMPILE_FLAGS) +# We have a behaviour in the test catalog (megaco_test_generator) +ERL_COMPILE_FLAGS += -pa ../../megaco/test + ERL_PATH = -pa ../../megaco/examples/simple \ -pa ../../megaco/ebin \ -pa ../../et/ebin diff --git a/lib/megaco/test/megaco_SUITE.erl b/lib/megaco/test/megaco_SUITE.erl index 38590f9fee..f7b8ffe032 100644 --- a/lib/megaco/test/megaco_SUITE.erl +++ b/lib/megaco/test/megaco_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2016. All Rights Reserved. +%% Copyright Ericsson AB 2000-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -25,7 +25,21 @@ -module(megaco_SUITE). --compile(export_all). +-export([ + suite/0, + all/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, + + t/0, t/1, + init/0 + ]). -include("megaco_test_lib.hrl"). -include_lib("megaco/include/megaco.hrl"). @@ -96,6 +110,20 @@ groups() -> {flex, [], [{megaco_flex_test, all}]}]. init_per_suite(Config) -> + io:format("~w:init_per_suite -> entry with" + "~n Config: ~p" + "~n OS Type: ~p" + "~n OS Version: ~s" + "~n", + [?MODULE, + Config, + os:type(), + case os:version() of + {Major, Minor, Release} -> + ?F("~w.~w.~w", [Major, Minor, Release]); + Str when is_list(Str) -> + Str + end]), Config. end_per_suite(_Config) -> diff --git a/lib/megaco/test/megaco_actions_test.erl b/lib/megaco/test/megaco_actions_test.erl index fcbe4f12fa..498e5c91cb 100644 --- a/lib/megaco/test/megaco_actions_test.erl +++ b/lib/megaco/test/megaco_actions_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2016. All Rights Reserved. +%% Copyright Ericsson AB 2004-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -20,13 +20,30 @@ %% %%---------------------------------------------------------------------- -%% Purpose: Verify that it is possible to separatelly encode +%% Purpose: Verify that it is possible to separately encode %% the action requests list. Do this with all codec's %% that supports partial encode. %%---------------------------------------------------------------------- -module(megaco_actions_test). --compile(export_all). +-export([ + all/0, + groups/0, + + init_per_group/2, + end_per_group/2, + init_per_testcase/2, + end_per_testcase/2, + + t/0, t/1, + + pretty_text/1, + flex_pretty_text/1, + compact_text/1, + flex_compact_text/1, + erl_dist/1, + erl_dist_mc/1 + ]). -include("megaco_test_lib.hrl"). -include_lib("megaco/include/megaco.hrl"). @@ -364,9 +381,6 @@ sleep(X) -> receive after X -> ok end. -error_msg(F,A) -> error_logger:error_msg(F ++ "~n",A). - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% i(F) -> @@ -376,8 +390,8 @@ i(F, A) -> print(info, get(verbosity), "", F, A). -d(F) -> - d(F, []). +%% d(F) -> +%% d(F, []). d(F, A) -> print(debug, get(verbosity), "DBG: ", F, A). @@ -391,20 +405,10 @@ print(Severity, Verbosity, P, F, A) -> print(printable(Severity,Verbosity), P, F, A). print(true, P, F, A) -> - io:format("~s~p:~s: " ++ F ++ "~n", [P, self(), get(sname) | A]); + io:format("*** [~s] ~s ~p ~s ***" + "~n " ++ F ++ "~n", + [?FTS(), P, self(), get(sname) | A]); print(_, _, _, _) -> ok. -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -random_init() -> - {A,B,C} = now(), - random:seed(A,B,C). - -random() -> - 10 * random:uniform(50). - -apply_load_timer() -> - erlang:send_after(random(), self(), apply_load_timeout). - diff --git a/lib/megaco/test/megaco_app_test.erl b/lib/megaco/test/megaco_app_test.erl index 981d93f5dd..fff2d8c7d4 100644 --- a/lib/megaco/test/megaco_app_test.erl +++ b/lib/megaco/test/megaco_app_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2002-2016. All Rights Reserved. +%% Copyright Ericsson AB 2002-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -20,29 +20,42 @@ %%---------------------------------------------------------------------- %% Purpose: Verify the application specifics of the Megaco application %%---------------------------------------------------------------------- + -module(megaco_app_test). --compile(export_all). +-export([ + all/0, + + app/0, app/1, + appup/0, appup/1 + ]). -include_lib("common_test/include/ct.hrl"). + %%-------------------------------------------------------------------- %% Common Test interface functions ----------------------------------- %%-------------------------------------------------------------------- + all() -> [ app, appup ]. + %%-------------------------------------------------------------------- %% Test Cases -------------------------------------------------------- %%-------------------------------------------------------------------- + app() -> [{doc, "Test that the megaco app file is ok"}]. app(Config) when is_list(Config) -> ok = test_server:app_test(megaco). + + %%-------------------------------------------------------------------- + appup() -> [{doc, "Test that the megaco appup file is ok"}]. appup(Config) when is_list(Config) -> diff --git a/lib/megaco/test/megaco_appup_test.erl b/lib/megaco/test/megaco_appup_test.erl index 8dc3ad51a0..a06d274844 100644 --- a/lib/megaco/test/megaco_appup_test.erl +++ b/lib/megaco/test/megaco_appup_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2002-2016. All Rights Reserved. +%% Copyright Ericsson AB 2002-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -22,8 +22,23 @@ %%---------------------------------------------------------------------- -module(megaco_appup_test). --compile(export_all). --compile({no_auto_import,[error/1]}). +-export([ + all/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, + + appup_file/1 + ]). + +-compile({no_auto_import, [error/1]}). -include_lib("common_test/include/ct.hrl"). -include("megaco_test_lib.hrl"). @@ -76,6 +91,10 @@ end_per_testcase(_Case, Config) when is_list(Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Perform a simple check of the appup file +appup_file(suite) -> + []; +appup_file(doc) -> + ["Perform a simple check of the appup file"]; appup_file(Config) when is_list(Config) -> ok = ?t:appup_test(megaco). diff --git a/lib/megaco/test/megaco_call_flow_test.erl b/lib/megaco/test/megaco_call_flow_test.erl index eb4574862d..03caf705ba 100644 --- a/lib/megaco/test/megaco_call_flow_test.erl +++ b/lib/megaco/test/megaco_call_flow_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2016. All Rights Reserved. +%% Copyright Ericsson AB 2000-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -38,7 +38,85 @@ -module(megaco_call_flow_test). --compile(export_all). +-export([ + all/0, + groups/0, + + init_per_group/2, + end_per_group/2, + init_per_testcase/2, + end_per_testcase/2, + + pretty/1, + compact/1, + pretty_flex/1, + compact_flex/1, + bin/1, + ber/1, + per/1, + standard_erl/1, + compressed_erl/1, + + t/0, t/1 + + ]). + +-export([ + msg1/0, msg1/1, + msg2/0, msg2/1, + msg3/0, msg3/1, + msg4/0, msg4/1, + msg5a/0, msg5a/1, + msg5b/0, msg5b/1, + msg6/0, msg6/1, + msg7/0, msg7/1, + msg9/0, msg9/1, + msg10/0, msg10/1, + msg11/0, msg11/1, + msg12/0, msg12/1, + msg13/0, msg13/1, + msg14/0, msg14/1, + msg15/0, msg15/1, + msg16/0, msg16/1, + msg17a/0, msg17a/1, + msg17b/0, msg17b/1, + msg18a/0, msg18a/1, + msg18b/0, msg18b/1, + msg18c/0, msg18c/1, + msg18d/0, msg18d/1, + msg19a/0, msg19a/1, + msg19b/0, msg19b/1, + msg20/0, msg20/1, + msg21/0, msg21/1, + msg22a/0, msg22a/1, + msg22b/0, msg22b/1, + msg23a/0, msg23a/1, + msg23b/0, msg23b/1 + + ]). + +-export([ + encoders/0, + msg_sizes/0, + coding_times/0, + encoding_times/0, + decoding_times/0, + coding_times_stat/0, + encoding_times_stat/0, + decoding_times_stat/0, + size_stat/0, + gnuplot_gif/0, + gnuplot_size_gif/0, + + gen_byte_msg/2, + gen_header_file_binary/1, + gen_ber_header/0, + gen_ber_bin_header/0, + gen_per_header/0, + single_meter/4, + count/2 + ]). + -include_lib("megaco/include/megaco.hrl"). -include_lib("megaco/include/megaco_message_v1.hrl"). -include("megaco_test_lib.hrl"). @@ -53,16 +131,20 @@ init_per_testcase(Case, Config) -> end_per_testcase(Case, Config) -> megaco_test_lib:end_per_testcase(Case, Config). + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Top test case all() -> - [{group, text}, {group, binary}]. + [{group, text}, {group, binary}, {group, erl}]. groups() -> - [{text, [], [pretty, compact]}, - {flex, [], [pretty_flex, compact_flex]}, - {binary, [], [bin, ber, per]}]. + [ + {text, [], [pretty, compact]}, + {flex, [], [pretty_flex, compact_flex]}, + {binary, [], [bin, ber, per]}, + {erl, [], [standard_erl, compressed_erl]} + ]. init_per_group(_GroupName, Config) -> Config. diff --git a/lib/megaco/test/megaco_codec_test.erl b/lib/megaco/test/megaco_codec_test.erl index 007136f83e..0dfbabcc81 100644 --- a/lib/megaco/test/megaco_codec_test.erl +++ b/lib/megaco/test/megaco_codec_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2016. All Rights Reserved. +%% Copyright Ericsson AB 2003-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -25,7 +25,18 @@ -module(megaco_codec_test). --compile(export_all). +-export([ + all/0, + groups/0, + + init_per_group/2, + end_per_group/2, + init_per_testcase/2, + end_per_testcase/2, + + t/0, t/1, + init/0 + ]). -include("megaco_test_lib.hrl"). -include_lib("megaco/include/megaco.hrl"). diff --git a/lib/megaco/test/megaco_codec_test_lib.erl b/lib/megaco/test/megaco_codec_test_lib.erl index 6eee5caaaa..7a3d4e6cf8 100644 --- a/lib/megaco/test/megaco_codec_test_lib.erl +++ b/lib/megaco/test/megaco_codec_test_lib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2016. All Rights Reserved. +%% Copyright Ericsson AB 2004-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -993,15 +993,15 @@ expect_exec([#expect_instruction{description = Desc, skip({What, Why}) when is_atom(What) andalso is_list(Why) -> Reason = lists:flatten(io_lib:format("~p: ~s", [What, Why])), - exit({skipped, Reason}); + ?SKIP(Reason); skip({What, Why}) -> Reason = lists:flatten(io_lib:format("~p: ~p", [What, Why])), - exit({skipped, Reason}); + ?SKIP(Reason); skip(Reason) when is_list(Reason) -> - exit({skipped, Reason}); + ?SKIP(Reason); skip(Reason1) -> Reason2 = lists:flatten(io_lib:format("~p", [Reason1])), - exit({skipped, Reason2}). + ?SKIP(Reason2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/lib/megaco/test/megaco_config_test.erl b/lib/megaco/test/megaco_config_test.erl index 02e06a722a..d46806927a 100644 --- a/lib/megaco/test/megaco_config_test.erl +++ b/lib/megaco/test/megaco_config_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2016. All Rights Reserved. +%% Copyright Ericsson AB 2000-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -25,7 +25,24 @@ -module(megaco_config_test). --compile(export_all). +-export([ + all/0, + groups/0, + + init_per_group/2, + end_per_group/2, + init_per_testcase/2, + end_per_testcase/2, + + config/1, + transaction_id_counter_mg/1, + transaction_id_counter_mgc/1, + otp_7216/1, + otp_8167/1, + otp_8183/1, + + t/0, t/1 + ]). -include("megaco_test_lib.hrl"). -include_lib("megaco/include/megaco.hrl"). @@ -37,6 +54,19 @@ t(Case) -> megaco_test_lib:t({?MODULE, Case}). min(M) -> timer:minutes(M). %% Test server callbacks +init_per_testcase(Case, Config) when (Case =:= otp_7216) orelse + (Case =:= otp_8167) orelse + (Case =:= otp_8183) -> + i("try starting megaco_config"), + case megaco_config:start_link() of + {ok, _} -> + C = lists:keydelete(tc_timeout, 1, Config), + do_init_per_testcase(Case, [{tc_timeout, min(3)}|C]); + {error, Reason} -> + i("Failed starting megaco_config: " + "~n ~p", [Reason]), + {skip, ?F("Failed starting config: ~p", [Reason])} + end; init_per_testcase(Case, Config) -> C = lists:keydelete(tc_timeout, 1, Config), do_init_per_testcase(Case, [{tc_timeout, min(3)}|C]). @@ -45,6 +75,12 @@ do_init_per_testcase(Case, Config) -> process_flag(trap_exit, true), megaco_test_lib:init_per_testcase(Case, Config). +end_per_testcase(Case, Config) when (Case =:= otp_7216) orelse + (Case =:= otp_8167) orelse + (Case =:= otp_8183) -> + (catch megaco_config:stop()), + process_flag(trap_exit, false), + megaco_test_lib:end_per_testcase(Case, Config); end_per_testcase(Case, Config) -> process_flag(trap_exit, false), megaco_test_lib:end_per_testcase(Case, Config). @@ -60,14 +96,17 @@ end_per_testcase(Case, Config) -> %% Top test case all() -> - [config, {group, transaction_id_counter}, - {group, tickets}]. + [ + config, + {group, transaction_id_counter}, + {group, tickets} + ]. groups() -> - [{transaction_id_counter, [], - [transaction_id_counter_mg, - transaction_id_counter_mgc]}, - {tickets, [], [otp_7216, otp_8167, otp_8183]}]. + [ + {transaction_id_counter, [], transaction_id_counter_cases()}, + {tickets, [], tickets_cases()} + ]. init_per_group(_GroupName, Config) -> Config. @@ -75,6 +114,19 @@ init_per_group(_GroupName, Config) -> end_per_group(_GroupName, Config) -> Config. +transaction_id_counter_cases() -> + [ + transaction_id_counter_mg, + transaction_id_counter_mgc + ]. + +tickets_cases() -> + [ + otp_7216, + otp_8167, + otp_8183 + ]. + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Config test case @@ -736,9 +788,6 @@ otp_7216(Config) when is_list(Config) -> put(tc, otp_7216), p("start"), - p("start the megaco config process"), - megaco_config:start_link(), - LocalMid1 = {deviceName, "local-mid-1"}, %% LocalMid2 = {deviceName, "local-mid-2"}, RemoteMid1 = {deviceName, "remote-mid-1"}, @@ -859,9 +908,6 @@ otp_8167(Config) when is_list(Config) -> put(tc, otp8167), p("start"), - p("start the megaco config process"), - megaco_config:start_link(), - LocalMid1 = {deviceName, "local-mid-1"}, LocalMid2 = {deviceName, "local-mid-2"}, RemoteMid1 = {deviceName, "remote-mid-1"}, @@ -981,9 +1027,6 @@ otp_8183(Config) when is_list(Config) -> put(tc, otp8183), p("start"), - p("start the megaco config process"), - megaco_config:start_link(), - LocalMid1 = {deviceName, "local-mid-1"}, LocalMid2 = {deviceName, "local-mid-2"}, RemoteMid1 = {deviceName, "remote-mid-1"}, @@ -1122,28 +1165,18 @@ i(F) -> i(F, []). i(F, A) -> - print(info, get(verbosity), now(), get(tc), "INF", F, A). + print(info, get(verbosity), get(tc), "INF", F, A). printable(_, debug) -> true; printable(info, info) -> true; printable(_,_) -> false. -print(Severity, Verbosity, Ts, Tc, P, F, A) -> - print(printable(Severity,Verbosity), Ts, Tc, P, F, A). +print(Severity, Verbosity, Tc, P, F, A) -> + print(printable(Severity,Verbosity), Tc, P, F, A). -print(true, Ts, Tc, P, F, A) -> +print(true, Tc, P, F, A) -> io:format("*** [~s] ~s ~p ~s:~w ***" "~n " ++ F ++ "~n", - [format_timestamp(Ts), P, self(), get(sname), Tc | A]); -print(_, _, _, _, _, _) -> + [?FTS(), P, self(), get(sname), Tc | A]); +print(_, _, _, _, _) -> 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). - diff --git a/lib/megaco/test/megaco_digit_map_test.erl b/lib/megaco/test/megaco_digit_map_test.erl index 998e829b67..e03d38497c 100644 --- a/lib/megaco/test/megaco_digit_map_test.erl +++ b/lib/megaco/test/megaco_digit_map_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2016. All Rights Reserved. +%% Copyright Ericsson AB 2005-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -24,7 +24,27 @@ %%---------------------------------------------------------------------- -module(megaco_digit_map_test). --compile(export_all). +-export([ + all/0, + groups/0, + + init_per_group/2, + end_per_group/2, + init_per_testcase/2, + end_per_testcase/2, + + otp_5750_01/1, + otp_5750_02/1, + otp_5799_01/1, + otp_5826_01/1, + otp_5826_02/1, + otp_5826_03/1, + otp_7449_1/1, + otp_7449_2/1, + + t/0, t/1 + ]). + -include("megaco_test_lib.hrl"). @@ -44,16 +64,18 @@ end_per_testcase(Case, Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% all() -> - [{group, tickets}]. + [ + {group, tickets} + ]. groups() -> - [{tickets, [], - [{group, otp_5750}, {group, otp_5799}, - {group, otp_5826}, {group, otp_7449}]}, - {otp_5750, [], [otp_5750_01, otp_5750_02]}, - {otp_5799, [], [otp_5799_01]}, - {otp_5826, [], [otp_5826_01, otp_5826_02, otp_5826_03]}, - {otp_7449, [], [otp_7449_1, otp_7449_2]}]. + [ + {tickets, [], tickets_cases()}, + {otp_5750, [], otp_5750_cases()}, + {otp_5799, [], otp_5799_cases()}, + {otp_5826, [], otp_5826_cases()}, + {otp_7449, [], otp_7449_cases()} + ]. init_per_group(_GroupName, Config) -> Config. @@ -62,6 +84,38 @@ end_per_group(_GroupName, Config) -> Config. +tickets_cases() -> + [ + {group, otp_5750}, + {group, otp_5799}, + {group, otp_5826}, + {group, otp_7449} + ]. + +otp_5750_cases() -> + [ + otp_5750_01, + otp_5750_02 + ]. + +otp_5799_cases() -> + [ + otp_5799_01 + ]. + +otp_5826_cases() -> + [ + otp_5826_01, + otp_5826_02, + otp_5826_03 + ]. + +otp_7449_cases() -> + [ + otp_7449_1, + otp_7449_2 + ]. + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/lib/megaco/test/megaco_examples_test.erl b/lib/megaco/test/megaco_examples_test.erl index 10ca0375f6..fdf9fe29ff 100644 --- a/lib/megaco/test/megaco_examples_test.erl +++ b/lib/megaco/test/megaco_examples_test.erl @@ -25,7 +25,20 @@ -module(megaco_examples_test). --compile(export_all). +-export([ + all/0, + groups/0, + + init_per_group/2, + end_per_group/2, + init_per_testcase/2, + end_per_testcase/2, + + simple/1, + + t/0, t/1 + ]). + -include("megaco_test_lib.hrl"). -include_lib("megaco/include/megaco.hrl"). diff --git a/lib/megaco/test/megaco_flex_test.erl b/lib/megaco/test/megaco_flex_test.erl index 999d1abc6c..27c46a3b47 100644 --- a/lib/megaco/test/megaco_flex_test.erl +++ b/lib/megaco/test/megaco_flex_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2016. All Rights Reserved. +%% Copyright Ericsson AB 2008-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -219,18 +219,5 @@ p(F, A) -> TC = get(tc), io:format("*** [~s] ~p ~w ***" "~n " ++ F ++ "~n", - [formated_timestamp(), self(), TC | A]). - -formated_timestamp() -> - format_timestamp(erlang:now()). - -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). - + [?FTS(), self(), TC | A]). diff --git a/lib/megaco/test/megaco_load_test.erl b/lib/megaco/test/megaco_load_test.erl index 511e5a2e8e..9cce9e70ce 100644 --- a/lib/megaco/test/megaco_load_test.erl +++ b/lib/megaco/test/megaco_load_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2016. All Rights Reserved. +%% Copyright Ericsson AB 2003-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -24,7 +24,33 @@ %%---------------------------------------------------------------------- -module(megaco_load_test). --compile(export_all). +-export([ + all/0, + groups/0, + + init_per_group/2, + end_per_group/2, + init_per_testcase/2, + end_per_testcase/2, + + single_user_light_load/1, + single_user_medium_load/1, + single_user_heavy_load/1, + single_user_extreme_load/1, + + multi_user_light_load/1, + multi_user_medium_load/1, + multi_user_heavy_load/1, + multi_user_extreme_load/1, + + t/0, t/1 + ]). + +-export([ + do_multi_load/3, + multi_load_collector/7 + ]). + -include("megaco_test_lib.hrl"). -include_lib("megaco/include/megaco.hrl"). @@ -66,8 +92,6 @@ t() -> megaco_test_lib:t(?MODULE). t(Case) -> megaco_test_lib:t({?MODULE, Case}). -min(M) -> timer:minutes(M). - %% Test server callbacks init_per_testcase(single_user_light_load = Case, Config) -> C = lists:keydelete(tc_timeout, 1, Config), @@ -108,15 +132,33 @@ end_per_testcase(Case, Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% all() -> - [single_user_light_load, - single_user_medium_load, single_user_heavy_load, - single_user_extreme_load, multi_user_light_load, - multi_user_medium_load, multi_user_heavy_load, - multi_user_extreme_load]. + [ + {group, single}, + {group, multi} + ]. groups() -> - []. - + [ + {single, [], single_cases()}, + {multi, [], multi_cases()} + ]. + +single_cases() -> + [ + single_user_light_load, + single_user_medium_load, + single_user_heavy_load, + single_user_extreme_load + ]. + +multi_cases() -> + [ + multi_user_light_load, + multi_user_medium_load, + multi_user_heavy_load, + multi_user_extreme_load + ]. + init_per_group(_GroupName, Config) -> Config. @@ -326,6 +368,17 @@ load_controller(Config, Fun) when is_list(Config) and is_function(Fun) -> d("load_controller -> " "loader [~p] terminated with ok~n", [Loader]), ok; + {'EXIT', Loader, {skipped, {fatal, Reason, File, Line}}} -> + i("load_controller -> " + "loader [~p] terminated with fatal skip" + "~n Reason: ~p" + "~n At: ~p:~p", [Loader, Reason, File, Line]), + ?SKIP(Reason); + {'EXIT', Loader, {skipped, Reason}} -> + i("load_controller -> " + "loader [~p] terminated with skip" + "~n Reason: ~p", [Loader, Reason]), + ?SKIP(Reason); {'EXIT', Loader, Reason} -> i("load_controller -> " "loader [~p] terminated with" @@ -629,14 +682,6 @@ make_mids([MgNode|MgNodes], Mids) -> exit("Test node must be started with '-sname'") end. -tim() -> - {A,B,C} = erlang:now(), - A*1000000000+B*1000+(C div 1000). - -sleep(X) -> receive after X -> ok end. - -error_msg(F,A) -> error_logger:error_msg(F ++ "~n",A). - maybe_display_system_info(NumLoaders) when NumLoaders > 50 -> [{display_system_info, timer:seconds(2)}]; maybe_display_system_info(NumLoaders) when NumLoaders > 10 -> @@ -647,50 +692,32 @@ maybe_display_system_info(_) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +min(M) -> timer:minutes(M). + i(F) -> i(F, []). i(F, A) -> - print(info, get(verbosity), now(), get(tc), "INF", F, A). + print(info, get(verbosity), get(tc), "INF", F, A). d(F) -> d(F, []). d(F, A) -> - print(debug, get(verbosity), now(), get(tc), "DBG", F, A). + print(debug, get(verbosity), get(tc), "DBG", F, A). printable(_, debug) -> true; printable(info, info) -> true; printable(_,_) -> false. -print(Severity, Verbosity, Ts, Tc, P, F, A) -> - print(printable(Severity,Verbosity), Ts, Tc, P, F, A). +print(Severity, Verbosity, Tc, P, F, A) -> + print(printable(Severity,Verbosity), Tc, P, F, A). -print(true, Ts, Tc, P, F, A) -> +print(true, Tc, P, F, A) -> io:format("*** [~s] ~s ~p ~s:~w ***" "~n " ++ F ++ "~n", - [format_timestamp(Ts), P, self(), get(sname), Tc | A]); -print(_, _, _, _, _, _) -> + [?FTS(), P, self(), get(sname), Tc | A]); +print(_, _, _, _, _) -> ok. -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -random_init() -> - {A,B,C} = now(), - random:seed(A,B,C). - -random() -> - 10 * random:uniform(50). - -apply_load_timer() -> - erlang:send_after(random(), self(), apply_load_timeout). - -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). diff --git a/lib/megaco/test/megaco_mess_test.erl b/lib/megaco/test/megaco_mess_test.erl index d3216c2a6d..3fd39a9e58 100644 --- a/lib/megaco/test/megaco_mess_test.erl +++ b/lib/megaco/test/megaco_mess_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2016. All Rights Reserved. +%% Copyright Ericsson AB 1999-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -281,6 +281,8 @@ -define(VERSION, 1). +-define(USER_MOD, megaco_mess_user_test). + -define(TEST_VERBOSITY, debug). -define(MGC_VERBOSITY, debug). -define(MG_VERBOSITY, debug). @@ -303,26 +305,48 @@ -define(MG_NOTIF_RAR(Pid), megaco_test_mg:notify_request_and_reply(Pid)). -define(SEND(Expr), - ?VERIFY(ok, megaco_mess_user_test:apply_proxy(fun() -> Expr end))). + ?VERIFY(ok, ?USER_MOD:apply_proxy(fun() -> Expr end))). -define(USER(Expected, Reply), - megaco_mess_user_test:reply(?MODULE, - ?LINE, - fun(Actual) -> - case ?VERIFY(Expected, Actual) of - Expected -> {ok, Reply}; - UnExpected -> {error, {reply_verify, - ?MODULE, - ?LINE, - UnExpected}} - end - end)). - -%% t() -> megaco_test_lib:t(?MODULE). -%% t(Case) -> megaco_test_lib:t({?MODULE, Case}). - - -min(M) -> timer:minutes(M). + ?USER_MOD:reply(?MODULE, + ?LINE, + fun(Actual) -> + case ?VERIFY(Expected, Actual) of + Expected -> {ok, Reply}; + UnExpected -> {error, {reply_verify, + ?MODULE, + ?LINE, + UnExpected}} + end + end)). + +%% Some generator (utility) macros +-define(GM_START(), megaco_start). +-define(GM_STOP(), megaco_stop). +-define(GM_START_USER(M, RI, C), {megaco_start_user, M, RI, C}). +-define(GM_START_USER(M, RI), ?GM_START_USER(M, RI, [])). +-define(GM_STOP_USER(), megaco_stop_user). +-define(GMSI(I), {megaco_system_info, I}). +-define(GMSI_USERS(), ?GMSI(users)). +-define(GMSI_CONNS(), ?GMSI(connections)). +-define(GMCAST(Reqs, Opts), {megaco_cast, Reqs, Opts}). +-define(GMCAST(Reqs), ?GMCAST(Reqs, [])). +-define(GMCB(CB, VF), {megaco_callback, CB, VF}). +-define(GMCB_CONNECT(VF), ?GMCB(handle_connect, VF)). +-define(GMCB_TRANS_REP(VF), ?GMCB(handle_trans_reply, VF)). +-define(GMT(T), {megaco_trace, T}). +-define(GMT_ENABLE(), ?GMT(enable)). +-define(GMT_DISABLE(), ?GMT(disable)). +-define(GD(D), {debug, D}). +-define(GD_ENABLE(), ?GD(true)). +-define(GD_DISABLE(), ?GD(false)). +-define(GS(T), {sleep, T}). + +-define(GSND(T, D), {send, T, D}). +-define(GERCV(T, VF, TO), {expect_receive, T, {VF, TO}}). + + +min(M) -> ?MINS(M). %% Test server callbacks init_per_testcase(otp_7189 = Case, Config) -> @@ -396,8 +420,19 @@ groups() -> init_per_suite(Config) -> io:format("~w:init_per_suite -> entry with" - "~n Config: ~p" - "~n", [?MODULE, Config]), + "~n Config: ~p" + "~n OS Type: ~p" + "~n OS Version: ~s" + "~n", + [?MODULE, + Config, + os:type(), + case os:version() of + {Major, Minor, Release} -> + ?F("~w.~w.~w", [Major, Minor, Release]); + Str when is_list(Str) -> + Str + end]), Config. end_per_suite(_Config) -> @@ -491,12 +526,12 @@ request_and_reply_plain(suite) -> request_and_reply_plain(Config) when is_list(Config) -> ?ACQUIRE_NODES(1, Config), d("request_and_reply_plain -> start proxy",[]), - megaco_mess_user_test:start_proxy(), + ?USER_MOD:start_proxy(), PrelMid = preliminary_mid, MgMid = ipv4_mid(4711), MgcMid = ipv4_mid(), - UserMod = megaco_mess_user_test, + UserMod = ?USER_MOD, d("request_and_reply_plain -> start megaco app",[]), ?VERIFY(ok, application:start(megaco)), UserConfig = [{user_mod, UserMod}, {send_mod, UserMod}, @@ -564,6 +599,7 @@ request_and_reply_plain(Config) when is_list(Config) -> ok. + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% OTP-4760 @@ -1715,9 +1751,6 @@ rarpaop_mg_event_sequence(Port, EncMod, EncConf) -> ScrVerifyFun = ?rarpaop_mg_verify_service_change_rep_msg_fun(), PendVerifyFun = ?rarpaop_mg_verify_pending_msg_fun(TransId), NrVerifyFun = ?rarpaop_mg_verify_notify_rep_msg_fun(TransId, TermId), -%% ScrVerifyFun = rarpaop_mg_verify_service_change_rep_msg_fun(), -%% PendVerifyFun = rarpaop_mg_verify_pending_msg_fun(TransId), -%% NrVerifyFun = rarpaop_mg_verify_notify_rep_msg_fun(TransId, TermId), EvSeq = [{debug, true}, {decode, DecodeFun}, {encode, EncodeFun}, @@ -2359,9 +2392,6 @@ strar_mg_event_sequence(text, tcp) -> ConnectVerify = ?strar_mg_verify_handle_connect_fun(), ServiceChangeReplyVerify = ?strar_mg_verify_service_change_reply_fun(), NotifyReplyVerify = ?strar_mg_verify_notify_reply_fun(), -%% ConnectVerify = strar_mg_verify_handle_connect_fun(), -%% ServiceChangeReplyVerify = strar_mg_verify_service_change_reply_fun(), -%% NotifyReplyVerify = fun strar_mg_verify_notify_reply/1, EvSeq = [ {debug, true}, megaco_start, @@ -3437,9 +3467,6 @@ raraa_mg_event_sequence(text, tcp) -> ScrVerifyFun = ?raraa_mg_verify_service_change_rep_msg_fun(), NrVerifyFun = ?raraa_mg_verify_notify_rep_msg_fun(TermId, TransId, ReqId, CtxId), -%% ScrVerifyFun = raraa_mg_verify_service_change_rep_msg_fun(), -%% NrVerifyFun = raraa_mg_verify_notify_rep_msg_fun(TermId, -%% TransId, ReqId, CtxId), EvSeq = [{debug, true}, {decode, DecodeFun}, {encode, EncodeFun}, @@ -4048,9 +4075,6 @@ rarana_mg_event_sequence(text, tcp) -> ScrVerifyFun = ?rarana_mg_verify_service_change_rep_msg_fun(), NrVerifyFun = ?rarana_mg_verify_notify_rep_msg_fun(TermId, TransId, ReqId, CtxId), -%% ScrVerifyFun = rarana_mg_verify_service_change_rep_msg_fun(), -%% NrVerifyFun = rarana_mg_verify_notify_rep_msg_fun(TermId, -%% TransId, ReqId, CtxId), EvSeq = [{debug, true}, {decode, DecodeFun}, {encode, EncodeFun}, @@ -4663,9 +4687,6 @@ rarala_mg_event_sequence(text, tcp) -> ScrVerifyFun = ?rarala_mg_verify_service_change_rep_msg_fun(), NrVerifyFun = ?rarala_mg_verify_notify_rep_msg_fun(TermId, TransId, ReqId, CtxId), -%% ScrVerifyFun = rarala_mg_verify_service_change_rep_msg_fun(), -%% NrVerifyFun = rarala_mg_verify_notify_rep_msg_fun(TermId, -%% TransId, ReqId, CtxId), EvSeq = [{debug, true}, {decode, DecodeFun}, {encode, EncodeFun}, @@ -5298,15 +5319,6 @@ trarar_mg_event_sequence(text, tcp) -> ?trarar_mg_verify_notify_rep_msg_fun(TermId, 2, 3, 3), NrVerifyFun4 = ?trarar_mg_verify_notify_rep_msg_fun(TermId, 2, 4, 4), -%% ScrVerifyFun = trarar_mg_verify_service_change_rep_msg_fun(), -%% NrVerifyFun1 = -%% trarar_mg_verify_notify_rep_msg_fun(TermId, 2, 1, 1), -%% NrVerifyFun2 = -%% trarar_mg_verify_notify_rep_msg_fun(TermId, 2, 2, 2), -%% NrVerifyFun3 = -%% trarar_mg_verify_notify_rep_msg_fun(TermId, 2, 3, 3), -%% NrVerifyFun4 = -%% trarar_mg_verify_notify_rep_msg_fun(TermId, 2, 4, 4), EvSeq = [{debug, true}, {decode, DecodeFun}, {encode, EncodeFun}, @@ -5983,11 +5995,6 @@ pap_mg_event_sequence(text, tcp) -> ?pap_mg_verify_pending_msg_fun(TransId), NrVerifyFun = ?pap_mg_verify_notify_rep_msg_fun(TermId, TransId, ReqId, CtxId), -%% ScrVerifyFun = pap_mg_verify_service_change_rep_msg_fun(), -%% PendingVerifyFun = -%% pap_mg_verify_pending_msg_fun(TransId), -%% NrVerifyFun = -%% pap_mg_verify_notify_rep_msg_fun(TermId, TransId, ReqId, CtxId), EvSeq = [{debug, true}, {decode, DecodeFun}, {encode, EncodeFun}, @@ -6380,10 +6387,6 @@ rapalr_mgc_event_sequence(text, tcp) -> NrVerifyFun = ?rapalr_mgc_verify_notify_req_msg_fun(TermId, TransId, ReqId, CtxId), AckVerifyFun = ?rapalr_mgc_verify_trans_ack_msg_fun(TransId), -%% ScrVerifyFun = rapalr_mgc_verify_service_change_req_msg_fun(), -%% NrVerifyFun = -%% rapalr_mgc_verify_notify_req_msg_fun(TermId, TransId, ReqId, CtxId), -%% AckVerifyFun = rapalr_mgc_verify_trans_ack_msg_fun(TransId), EvSeq = [{debug, false}, {decode, DecodeFun}, {encode, EncodeFun}, @@ -6866,12 +6869,12 @@ dist(Config) when is_list(Config) -> ?SKIP("Needs a re-write..."), [_Local, Dist] = ?ACQUIRE_NODES(2, Config), d("dist -> start proxy",[]), - megaco_mess_user_test:start_proxy(), + ?USER_MOD:start_proxy(), PrelMid = preliminary_mid, MgMid = ipv4_mid(4711), MgcMid = ipv4_mid(), - UserMod = megaco_mess_user_test, + UserMod = ?USER_MOD, d("dist -> start megaco app",[]), ?VERIFY(ok, application:start(megaco)), UserConfig = [{user_mod, UserMod}, {send_mod, UserMod}, @@ -6977,7 +6980,7 @@ dist(Config) when is_list(Config) -> ?RECEIVE([]), d("dist -> stop proxy",[]), - megaco_mess_user_test:stop_proxy(), + ?USER_MOD:stop_proxy(), d("dist -> done", []), ok. @@ -7444,9 +7447,6 @@ otp_5805_mg_event_sequence(text, tcp) -> ?otp_5805_mg_verify_service_change_rep_msg_fun(), EDVerify = ?otp_5805_mg_verify_error_descriptor_msg_fun(), -%% ServiceChangeReplyVerifyFun = -%% otp_5805_mg_verify_service_change_rep_msg_fun(), -%% EDVerify = otp_5805_mg_verify_error_descriptor_msg_fun(), MgEvSeq = [{debug, true}, {decode, DecodeFun}, {encode, EncodeFun}, @@ -7939,8 +7939,6 @@ otp_5881_mgc_event_sequence(text, tcp) -> %% Pending = otp_5881_pending_msg(Mid,2), ServiceChangeVerifyFun = ?otp_5881_mgc_verify_service_change_req_msg_fun(), NotifyReqVerifyFun = ?otp_5881_mgc_verify_notify_req_msg_fun(), -%% ServiceChangeVerifyFun = otp_5881_verify_service_change_req_msg_fun(), -%% NotifyReqVerifyFun = otp_5881_verify_notify_request_fun(), MgcEvSeq = [{debug, true}, {decode, DecodeFun}, {encode, EncodeFun}, @@ -8211,8 +8209,6 @@ otp_5887_mgc_event_sequence(text, tcp) -> NotifyReply = otp_5887_notify_reply_msg(Mid, 2, 0, TermId), ServiceChangeVerifyFun = ?otp_5887_mgc_verify_service_change_req_msg_fun(), NotifyReqVerifyFun = ?otp_5887_mgc_verify_notify_req_msg_fun(), -%% ServiceChangeVerifyFun = otp_5887_verify_service_change_req_msg_fun(), -%% NotifyReqVerifyFun = otp_5887_verify_notify_request_fun(), MgcEvSeq = [{debug, true}, {decode, DecodeFun}, {encode, EncodeFun}, @@ -8362,7 +8358,7 @@ otp_6253(Config) when is_list(Config) -> MgMid = ipv4_mid(4711), ?VERIFY(ok, application:start(megaco)), - ?VERIFY(ok, megaco:start_user(MgMid, [{send_mod, megaco_mess_user_test}, + ?VERIFY(ok, megaco:start_user(MgMid, [{send_mod, ?USER_MOD}, {request_timer, infinity}, {reply_timer, infinity}])), @@ -8668,8 +8664,6 @@ otp_6275_mgc_event_sequence(text, tcp) -> NotifyReq = otp_6275_mgc_notify_request_msg(Mid, 2, 1, TermId, 1), SCRVerifyFun = ?otp_6275_mgc_verify_service_change_req_msg_fun(), NotifyReplyVerifyFun = ?otp_6275_mgc_verify_notify_rep_msg_fun(), -%% SCRVerifyFun = otp_6275_mgc_verify_service_change_req_fun(), -%% NotifyReplyVerifyFun = otp_6275_mgc_verify_notify_reply_fun(), MgcEvSeq = [{debug, true}, {decode, DecodeFun}, @@ -11015,12 +11009,12 @@ otp_6865_request_and_reply_plain_extra1(Config) when is_list(Config) -> ok = megaco_tc_controller:insert(extra_transport_info, ExtraInfo), d("start proxy",[]), - megaco_mess_user_test:start_proxy(), + ?USER_MOD:start_proxy(), PrelMid = preliminary_mid, MgMid = ipv4_mid(4711), MgcMid = ipv4_mid(), - UserMod = megaco_mess_user_test, + UserMod = ?USER_MOD, d("start megaco app",[]), ?VERIFY(ok, application:start(megaco)), UserConfig = [{user_mod, UserMod}, {send_mod, UserMod}, @@ -12286,15 +12280,15 @@ otp_7189_mg_event_sequence(text, tcp) -> ?otp_7189_mg_verify_service_change_rep_msg_fun(), NotifyReqVerify = ?otp_7189_mg_verify_notify_req_msg_fun(TermId, TransId, ReqId, CtxId), EvSeq = [ - {debug, true}, + ?GD_ENABLE(), {decode, DecodeFun}, {encode, EncodeFun}, {connect, 2944}, - {send, "service-change-request", ServiceChangeReq}, - {expect_receive, "service-change-reply", {ServiceChangeReplyVerifyFun, 2000}}, - {expect_receive, "notify request", {NotifyReqVerify, 2000}}, - {sleep, 100}, - {send, "pending", Pending}, + ?GSND("service-change-request", ServiceChangeReq), + ?GERCV("service-change-reply", ServiceChangeReplyVerifyFun, ?SECS(5)), + ?GERCV("notify request", NotifyReqVerify, ?SECS(5)), + ?GS(100), + ?GSND("pending", Pending), {expect_closed, timer:seconds(120)}, disconnect ], @@ -12532,7 +12526,7 @@ otp_7259(Config) when is_list(Config) -> megaco_test_generic_transport:incomming_message(Pid, NotifyReply), d("[MG] await the generator reply"), - await_completion([MgId], 5000), + await_completion([MgId], 7000), %% Tell Mg to stop i("[MG] stop generator"), @@ -12832,13 +12826,13 @@ otp_7713(Config) when is_list(Config) -> i("starting"), d("start proxy",[]), - megaco_mess_user_test:start_proxy(), + ?USER_MOD:start_proxy(), Extra = otp7713_extra, PrelMid = preliminary_mid, MgMid = ipv4_mid(4711), MgcMid = ipv4_mid(), - UserMod = megaco_mess_user_test, + UserMod = ?USER_MOD, d("start megaco app",[]), ?VERIFY(ok, application:start(megaco)), UserConfig = [{user_mod, UserMod}, {send_mod, UserMod}, @@ -12954,10 +12948,11 @@ otp_8183_request1(Config) when is_list(Config) -> i("wait some before issuing the notify reply (twice)"), sleep(500), - i("send the notify reply, twice times"), + i("send the notify reply - twice"), NotifyReply = otp_8183_r1_mgc_notify_reply_msg(MgcMid, TransId2, Cid2, TermId2), megaco_test_generic_transport:incomming_message(Pid, NotifyReply), + sleep(100), %% This is to "make sure" the events come in the "right" order megaco_test_generic_transport:incomming_message(Pid, NotifyReply), d("await the generator reply"), @@ -13228,13 +13223,33 @@ otp_8183_r1_mg_verify_notify_rep_fun(Nr) -> end. -endif. -otp_8183_r1_mg_verify_notify_rep(Nr, +otp_8183_r1_mg_verify_notify_rep( + Nr, {handle_trans_reply, _CH, ?VERSION, {ok, Nr, [AR]}, _}) -> io:format("otp_8183_r1_mg_verify_notify_rep -> ok" "~n Nr: ~p" "~n AR: ~p" "~n", [Nr, AR]), {ok, AR, ok}; +otp_8183_r1_mg_verify_notify_rep( + ExpNr, + {handle_trans_reply, _CH, ?VERSION, {ok, ActNr, [AR]}, _}) -> + io:format("otp_8183_r1_mg_verify_notify_rep -> error" + "~n Expected Nr: ~p" + "~n Actual Nr: ~p" + "~n AR: ~p" + "~n", [ExpNr, ActNr, AR]), + Error = {unexpected_nr, ExpNr, ActNr}, + {error, Error, ok}; +otp_8183_r1_mg_verify_notify_rep( + Nr, + {handle_trans_reply, _CH, ?VERSION, Res, _}) -> + io:format("otp_8183_r1_mg_verify_notify_rep -> error" + "~n Nr: ~p" + "~n Res: ~p" + "~n", [Nr, Res]), + Error = {unexpected_result, Nr, Res}, + {error, Error, ok}; otp_8183_r1_mg_verify_notify_rep(Nr, Else) -> io:format("otp_8183_r1_mg_verify_notify_rep -> unknown" "~n Nr: ~p" diff --git a/lib/megaco/test/megaco_mess_user_test.erl b/lib/megaco/test/megaco_mess_user_test.erl index b5a554112e..d2a9c0f290 100644 --- a/lib/megaco/test/megaco_mess_user_test.erl +++ b/lib/megaco/test/megaco_mess_user_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2016. All Rights Reserved. +%% Copyright Ericsson AB 2000-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -86,13 +86,13 @@ reply(Mod, Line, Fun) when is_function(Fun) -> {?MODULE, Pid, UserCallback} -> UserReply = Fun(UserCallback), Pid ! {?MODULE, self(), UserReply}, - UserReply; - Other -> - megaco_test_lib:error(Other, Mod, Line), - {error, Other} -%% after 1000 -> -%% megaco_test_lib:error(timeout, Mod, Line), -%% {error, timeout} + UserReply%% ; + %% Other -> + %% megaco_test_lib:error(Other, Mod, Line), + %% {error, Other} + after 10000 -> + megaco_test_lib:error(timeout, Mod, Line), + {error, timeout} end. call(UserCallback) -> diff --git a/lib/megaco/test/megaco_mib_test.erl b/lib/megaco/test/megaco_mib_test.erl index 06ac7c08ed..9d1d408f18 100644 --- a/lib/megaco/test/megaco_mib_test.erl +++ b/lib/megaco/test/megaco_mib_test.erl @@ -264,7 +264,7 @@ connect(Config) when is_list(Config) -> d("connect -> (Mg1) service change result: ~p", [Res1]), %% Collect the statistics - progress("collect MG1 statustics (after service change)"), + progress("collect MG1 statistics (after service change)"), {ok, Mg1Stats1} = get_stats(Mg1, 1), d("connect -> stats for Mg1: ~n~p", [Mg1Stats1]), progress("collect MGC statistics (after MG1 service change)"), @@ -279,7 +279,7 @@ connect(Config) when is_list(Config) -> d("connect -> (Mg2) service change result: ~p", [Res2]), %% Collect the statistics - progress("collect MG2 statustics (after service change)"), + progress("collect MG2 statistics (after service change)"), {ok, Mg2Stats1} = get_stats(Mg2, 1), d("connect -> stats for Mg1: ~n~p", [Mg2Stats1]), progress("collect MGC statistics (after MG2 service change)"), @@ -751,7 +751,7 @@ mgc_init(Config) -> d("mgc_init -> entry"), Mid = get_conf(local_mid, Config), RI = get_conf(receive_info, Config), - d("mgc_init -> start megaco"), + i("mgc_init -> start megaco"), application:start(megaco), d("mgc_init -> start megaco user"), megaco:start_user(Mid, []), @@ -763,7 +763,7 @@ mgc_init(Config) -> RH = megaco:user_info(Mid,receive_handle), d("mgc_init -> parse receive info"), ListenTo = mgc_parse_receive_info(RI, RH), - d("mgc_init -> start transports"), + i("mgc_init -> start transport(s)"), {Tcp, Udp} = mgc_start_transports(ListenTo), {Mid, Tcp, Udp}. @@ -948,7 +948,7 @@ mgc_start_transports([{_Port, RH}|_ListenTo], _TcpSup, _UdpSup) -> mgc_start_tcp(RH, Port, undefined) -> - d("start tcp transport"), + i("start tcp transport"), case megaco_tcp:start_transport() of {ok, Sup} -> mgc_start_tcp(RH, Port, Sup); @@ -956,7 +956,7 @@ mgc_start_tcp(RH, Port, undefined) -> throw({error, {failed_starting_tcp_transport, Else}}) end; mgc_start_tcp(RH, Port, Sup) when is_pid(Sup) -> - d("tcp listen on ~p", [Port]), + i("tcp listen on ~p", [Port]), Opts = [{port, Port}, {receive_handle, RH}, {tcp_options, [{nodelay, true}]}], @@ -986,7 +986,7 @@ mgc_tcp_create_listen(Sup, Opts, MaxN, N, _InitialReason) mgc_start_udp(RH, Port, undefined) -> - d("start udp transport"), + i("start udp transport"), case megaco_udp:start_transport() of {ok, Sup} -> mgc_start_udp(RH, Port, Sup); @@ -994,7 +994,7 @@ mgc_start_udp(RH, Port, undefined) -> throw({error, {failed_starting_udp_transport, Else}}) end; mgc_start_udp(RH, Port, Sup) -> - d("open udp ~p", [Port]), + i("open udp ~p", [Port]), Opts = [{port, Port}, {receive_handle, RH}], case megaco_udp:open(Sup, Opts) of {ok, _SendHandle, _ControlPid} -> @@ -1119,7 +1119,7 @@ mg_init(Config) -> d("mg_init -> entry"), Mid = get_conf(local_mid, Config), RI = get_conf(receive_info, Config), - d("mg_init -> start megaco"), + i("mg_init -> start megaco"), application:start(megaco), d("mg_init -> start megaco user"), megaco:start_user(Mid, []), @@ -1131,7 +1131,7 @@ mg_init(Config) -> RH = megaco:user_info(Mid,receive_handle), d("mg_init -> parse receive info"), {MgcPort,RH1} = mg_parse_receive_info(RI, RH), - d("mg_init -> start transport with"), + i("mg_init -> start transport(s)"), ConnHandle = mg_start_transport(MgcPort, RH1), {Mid, ConnHandle}. @@ -1255,16 +1255,6 @@ mg_close_conn(CH) -> SendMod -> exit(Pid, Reason) end. -% display_tuple(T) when tuple(T), size(T) > 0 -> -% i("size(T): ~p", [size(T)]), -% display_tuple(T,1). - -% display_tuple(T,P) when P > size(T) -> -% ok; -% display_tuple(T,P) -> -% i("T[~p]: ~p", [P,element(P,T)]), -% display_tuple(T,P+1). - mg_parse_receive_info(RI, RH) -> d("mg_parse_receive_info -> get encoding module"), @@ -1292,7 +1282,7 @@ mg_start_transport(_, #megaco_receive_handle{send_mod = Mod}) -> mg_start_tcp(MgcPort, RH) -> - d("start tcp transport"), + i("start tcp transport"), case megaco_tcp:start_transport() of {ok, Sup} -> {ok, LocalHost} = inet:gethostname(), @@ -1316,7 +1306,7 @@ mg_start_tcp(MgcPort, RH) -> mg_start_udp(MgcPort, RH) -> - d("start udp transport"), + i("start udp transport"), case megaco_udp:start_transport() of {ok, Sup} -> %% Some linux (Ubuntu) has "crap" in their /etc/hosts, that @@ -1723,6 +1713,7 @@ progress(F) -> progress(F, []). progress(F, A) -> + io:format("~s " ++ F ++ "~n", [?FTS()|A]), io:format(user, "~s " ++ F ++ "~n", [?FTS()|A]). diff --git a/lib/megaco/test/megaco_mreq_test.erl b/lib/megaco/test/megaco_mreq_test.erl index e6a5ed3181..ba20329ab3 100644 --- a/lib/megaco/test/megaco_mreq_test.erl +++ b/lib/megaco/test/megaco_mreq_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2016. All Rights Reserved. +%% Copyright Ericsson AB 2003-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -24,7 +24,21 @@ %%---------------------------------------------------------------------- -module(megaco_mreq_test). --compile(export_all). +-export([ + all/0, + groups/0, + + init_per_group/2, + end_per_group/2, + init_per_testcase/2, + end_per_testcase/2, + + req_and_rep/1, + req_and_pending/1, + req_and_cancel/1, + + t/0, t/1 + ]). -include("megaco_test_lib.hrl"). -include_lib("megaco/include/megaco.hrl"). @@ -51,16 +65,19 @@ -define(MG_START(Pid, Mid, Enc, Transp, Verb), megaco_test_mg:start(Pid, Mid, Enc, Transp, Verb)). --define(MG_STOP(Pid), megaco_test_mg:stop(Pid)). --define(MG_GET_STATS(Pid, No), megaco_test_mg:get_stats(Pid, No)). --define(MG_RESET_STATS(Pid), megaco_test_mg:reset_stats(Pid)). --define(MG_SERV_CHANGE(Pid), megaco_test_mg:service_change(Pid)). --define(MG_NOTIF_RAR(Pid), megaco_test_mg:notify_request_and_reply(Pid)). --define(MG_NOTIF_REQ(Pid), megaco_test_mg:notify_request(Pid)). --define(MG_NOTIF_AR(Pid), megaco_test_mg:await_notify_reply(Pid)). --define(MG_CANCEL(Pid,R), megaco_test_mg:cancel_request(Pid,R)). +-define(MG_STOP(Pid), megaco_test_mg:stop(Pid)). +-define(MG_GET_STATS(Pid), megaco_test_mg:get_stats(Pid)). +-define(MG_RESET_STATS(Pid), megaco_test_mg:reset_stats(Pid)). +-define(MG_SERV_CHANGE(Pid), megaco_test_mg:service_change(Pid)). +-define(MG_NOTIF_RAR(Pid), megaco_test_mg:notify_request_and_reply(Pid)). +-define(MG_NOTIF_REQ(Pid), megaco_test_mg:notify_request(Pid)). +-define(MG_NOTIF_AR(Pid), megaco_test_mg:await_notify_reply(Pid)). +-define(MG_CANCEL(Pid,R), megaco_test_mg:cancel_request(Pid,R)). -define(MG_APPLY_LOAD(Pid,CntStart), megaco_test_mg:apply_load(Pid,CntStart)). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + t() -> megaco_test_lib:t(?MODULE). t(Case) -> megaco_test_lib:t({?MODULE, Case}). @@ -74,6 +91,7 @@ end_per_testcase(Case, Config) -> process_flag(trap_exit, false), megaco_test_lib:end_per_testcase(Case, Config). + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% all() -> @@ -228,7 +246,7 @@ req_and_rep_stop_mg(MGs) -> req_and_rep_get_mg_stats([], Acc) -> lists:reverse(Acc); req_and_rep_get_mg_stats([{Name, Pid}|Mgs], Acc) -> - {ok, Stats} = ?MG_GET_STATS(Pid, 1), + {ok, Stats} = ?MG_GET_STATS(Pid), d("req_and_rep_get_mg_stats -> stats for ~s: ~n~p~n", [Name, Stats]), req_and_rep_get_mg_stats(Mgs, [{Name, Stats}|Acc]). @@ -399,11 +417,13 @@ req_and_cancel(Config) when is_list(Config) -> req_and_cancel_analyze_result({ok,{_PV,Res}}) -> - d("req_and_cancel -> notify request result: ~n ~p", [Res]), + i("req_and_cancel -> notify request result: ~n ~p", [Res]), req_and_cancel_analyze_result2(Res); req_and_cancel_analyze_result(Unexpected) -> exit({unexpected_result,Unexpected}). +req_and_cancel_analyze_result2({error,{user_cancel,req_and_cancel}}) -> + ok; req_and_cancel_analyze_result2([]) -> ok; req_and_cancel_analyze_result2([{error,{user_cancel,req_and_cancel}}|Res]) -> @@ -429,9 +449,6 @@ sleep(X) -> receive after X -> ok end. -error_msg(F,A) -> error_logger:error_msg(F ++ "~n",A). - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% i(F) -> @@ -441,8 +458,8 @@ i(F, A) -> print(info, get(verbosity), "", F, A). -d(F) -> - d(F, []). +%% d(F) -> +%% d(F, []). d(F, A) -> print(debug, get(verbosity), "DBG: ", F, A). @@ -456,20 +473,9 @@ print(Severity, Verbosity, P, F, A) -> print(printable(Severity,Verbosity), P, F, A). print(true, P, F, A) -> - io:format("~s~p:~s: " ++ F ++ "~n", [P, self(), get(sname) | A]); + io:format("*** [~s] ~s ~p ~s ***" + "~n " ++ F ++ "~n", + [?FTS(), P, self(), get(sname) | A]); print(_, _, _, _) -> ok. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -random_init() -> - {A,B,C} = now(), - random:seed(A,B,C). - -random() -> - 10 * random:uniform(50). - -apply_load_timer() -> - erlang:send_after(random(), self(), apply_load_timeout). - diff --git a/lib/megaco/test/megaco_pending_limit_test.erl b/lib/megaco/test/megaco_pending_limit_test.erl index ef3b7e51cf..e0c0468d99 100644 --- a/lib/megaco/test/megaco_pending_limit_test.erl +++ b/lib/megaco/test/megaco_pending_limit_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2016. All Rights Reserved. +%% Copyright Ericsson AB 2003-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -2065,23 +2065,12 @@ await_completion(Ids) -> ?ERROR({failed, Reply}) end. -%% await_completion(Ids, Timeout) -> -%% case megaco_test_generator_lib:await_completion(Ids, Timeout) of -%% {ok, Reply} -> -%% d("OK => Reply: ~n~p", [Reply]), -%% ok; -%% {error, Reply} -> -%% d("ERROR => Reply: ~n~p", [Reply]), -%% ?ERROR({failed, Reply}) -%% end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% sleep(X) -> receive after X -> ok end. -%% error_msg(F,A) -> error_logger:error_msg(F ++ "~n",A). - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -2089,49 +2078,30 @@ i(F) -> i(F, []). i(F, A) -> - print(info, get(verbosity), now(), get(tc), "INF", F, A). + print(info, get(verbosity), get(tc), "INF", F, A). d(F) -> d(F, []). d(F, A) -> - print(debug, get(verbosity), now(), get(tc), "DBG", F, A). + print(debug, get(verbosity), get(tc), "DBG", F, A). printable(_, debug) -> true; printable(info, info) -> true; printable(_,_) -> false. -print(Severity, Verbosity, Ts, Tc, P, F, A) -> - print(printable(Severity,Verbosity), Ts, Tc, P, F, A). +print(Severity, Verbosity, Tc, P, F, A) -> + print(printable(Severity,Verbosity), Tc, P, F, A). -print(true, Ts, Tc, P, F, A) -> +print(true, Tc, P, F, A) -> io:format("*** [~s] ~s ~p ~s:~w ***" "~n " ++ F ++ "~n", - [format_timestamp(Ts), P, self(), get(sname), Tc | A]); -print(_, _, _, _, _, _) -> + [?FTS(), P, self(), get(sname), Tc | A]); +print(_, _, _, _, _) -> ok. -%% print(F, A) -> -%% io:format("*** [~s] ***" -%% "~n " ++ F ++ "~n", -%% [format_timestamp(now()) | A]). - -format_timestamp(Now) -> megaco:format_timestamp(Now). - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% random_init() -> -%% {A,B,C} = now(), -%% random:seed(A,B,C). - -%% random() -> -%% 10 * random:uniform(50). - -%% apply_load_timer() -> -%% erlang:send_after(random(), self(), apply_load_timeout). - - - diff --git a/lib/megaco/test/megaco_segment_test.erl b/lib/megaco/test/megaco_segment_test.erl index ddb8b9f06b..47f708a14b 100644 --- a/lib/megaco/test/megaco_segment_test.erl +++ b/lib/megaco/test/megaco_segment_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2016. All Rights Reserved. +%% Copyright Ericsson AB 2006-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -7718,29 +7718,9 @@ await_completion(Ids) -> ?ERROR({failed, Reply}) end. -%% await_completion(Ids, Timeout) -> -%% case megaco_test_generator_lib:await_completion(Ids, Timeout) of -%% {ok, Reply} -> -%% d("OK => Reply: ~n~p", [Reply]), -%% ok; -%% {error, {OK, ERROR}} -> -%% d("ERROR => " -%% "~n OK: ~p" -%% "~n ERROR: ~p", [OK, ERROR]), -%% ?ERROR({failed, ERROR}); -%% {error, Reply} -> -%% d("ERROR => Reply: ~n~p", [Reply]), -%% ?ERROR({failed, Reply}) -%% end. - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% tim() -> -%% {A,B,C} = erlang:now(), -%% A*1000000000+B*1000+(C div 1000). - - make_node_name(Name) -> case string:tokens(atom_to_list(node()), [$@]) of [_,Host] -> @@ -7754,8 +7734,6 @@ make_node_name(Name) -> sleep(X) -> receive after X -> ok end. -%% error_msg(F,A) -> error_logger:error_msg(F ++ "~n",A). - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -7763,44 +7741,31 @@ i(F) -> i(F, []). i(F, A) -> - print(info, get(verbosity), now(), get(tc), "INF", F, A). + print(info, get(verbosity), get(tc), "INF", F, A). d(F) -> d(F, []). d(F, A) -> - print(debug, get(verbosity), now(), get(tc), "DBG", F, A). + print(debug, get(verbosity), get(tc), "DBG", F, A). printable(_, debug) -> true; printable(info, info) -> true; printable(_,_) -> false. -print(Severity, Verbosity, Ts, Tc, P, F, A) -> - print(printable(Severity,Verbosity), Ts, Tc, P, F, A). +print(Severity, Verbosity, Tc, P, F, A) -> + print(printable(Severity, Verbosity), Tc, P, F, A). -print(true, Ts, Tc, P, F, A) -> +print(true, Tc, P, F, A) -> io:format("*** [~s] ~s ~p ~s:~w ***" "~n " ++ F ++ "~n", - [format_timestamp(Ts), P, self(), get(sname), Tc | A]); -print(_, _, _, _, _, _) -> + [?FTS(), P, self(), get(sname), Tc | A]); +print(_, _, _, _, _) -> ok. -format_timestamp(Now) -> megaco:format_timestamp(Now). - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% random_init() -> -%% {A,B,C} = now(), -%% random:seed(A,B,C). - -%% random() -> -%% 10 * random:uniform(50). - -%% apply_load_timer() -> -%% erlang:send_after(random(), self(), apply_load_timeout). - - diff --git a/lib/megaco/test/megaco_tcp_test.erl b/lib/megaco/test/megaco_tcp_test.erl index a1865ad690..cc66a40f43 100644 --- a/lib/megaco/test/megaco_tcp_test.erl +++ b/lib/megaco/test/megaco_tcp_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2016. All Rights Reserved. +%% Copyright Ericsson AB 2000-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -117,15 +117,39 @@ end_per_testcase(Case, Config) -> %% Test case definitions %%====================================================================== all() -> - [{group, start}, {group, sending}, {group, errors}]. + [ + {group, start}, + {group, sending}, + {group, errors} + ]. groups() -> - [{start, [], - [start_normal, start_invalid_opt, start_and_stop]}, - {sending, [], [sendreceive, block_unblock]}, - {errors, [], - [socket_failure, accept_process, accept_supervisor, - connection_supervisor, tcp_server]}]. + [{start, [], start_cases()}, + {sending, [], sending_cases()}, + {errors, [], errors_cases()}]. + +start_cases() -> + [ + start_normal, + start_invalid_opt, + start_and_stop + ]. + +sending_cases() -> + [ + sendreceive, + block_unblock + ]. + +errors_cases() -> + [ + socket_failure, + accept_process, + accept_supervisor, + connection_supervisor, + tcp_server + ]. + init_per_group(_GroupName, Config) -> Config. @@ -196,17 +220,8 @@ start_and_stop(Config) when is_list(Config) -> Client = client_start_command_handler(ClientNode, ClientCmds), p("client command handler started: ~p", [Client]), - ok = - receive - {listening, Server} -> - p("received listening message from server [~p] => " - "send continue to client [~p]~n", [Server, Client]), - Client ! {continue, self()}, - ok - after 5000 -> - {error, server_timeout} - end, - + await_server_listening(Server, Client), + await_command_handler_completion([Server, Client], timer:seconds(20)), p("done"), ok. @@ -335,16 +350,7 @@ sendreceive(Config) when is_list(Config) -> Client = client_start_command_handler(ClientNode, ClientCmds), p("client command handler started: ~p", [Client]), - ok = - receive - {listening, Server} -> - p("received listening message from server [~p] => " - "send continue to client [~p]~n", [Server, Client]), - Client ! {continue, self()}, - ok - after 5000 -> - {error, server_timeout} - end, + await_server_listening(Server, Client), await_command_handler_completion([Server, Client], timer:seconds(20)), p("done"), @@ -544,27 +550,9 @@ block_unblock(Config) when is_list(Config) -> Client = client_start_command_handler(ClientNode, ClientCmds), p("client command handler started: ~p", [Client]), - ok = - receive - {listening, Server} -> - p("received listening message from server [~p] => " - "send continue to client [~p]~n", [Server, Client]), - Client ! {continue, self()}, - ok - after 5000 -> - {error, server_timeout} - end, - - ok = - receive - {blocked, Client} -> - p("received blocked message from client [~p] => " - "send continue to server [~p]~n", [Client, Server]), - Server ! {continue, self()}, - ok - after 5000 -> - {error, timeout} - end, + await_server_listening(Server, Client), + + await_client_blocked(Server, Client), await_command_handler_completion([Server, Client], timer:seconds(30)), p("done"), @@ -908,6 +896,42 @@ process_received_message(ReceiveHandle, ControlPid, SendHandle, BinMsg) %% Internal functions %%====================================================================== +await_server_listening(Server, Client) -> + receive + {listening, Server} -> + p("received listening message from server [~p] => " + "send continue to client [~p]" + "~n", [Server, Client]), + Client ! {continue, self()}, + ok + after 5000 -> + %% There is no normal reason why this should take any time. + %% Normally, this takes a few milli seconds. So, if we are not + %% up and running after 5 seconds, we give up and skip!! + exit(Server, kill), + exit(Client, kill), + ?SKIP("Server timeout (listen)") + end. + + +await_client_blocked(Server, Client) -> + receive + {blocked, Client} -> + p("received blocked message from client [~p] => " + "send continue to server [~p]~n", [Client, Server]), + Server ! {continue, self()}, + ok + after 5000 -> + %% There is no normal reason why this should take any time. + %% Normally, this takes a few milli seconds. So, if we are not + %% up and running after 5 seconds, we give up and skip!! + exit(Client, kill), + exit(Server, kill), + ?SKIP("Client timeout (blocked)") + end. + + + %% ------- Server command handler and utility functions ---------- server_start_command_handler(Node, Commands) -> @@ -1214,23 +1238,14 @@ p(F, A) -> p(S, F, A) when is_list(S) -> io:format("*** [~s] ~p ~s ***" "~n " ++ F ++ "~n", - [format_timestamp(now()), self(), S | A]); + [?FTS(), self(), S | A]); p(_S, F, A) -> io:format("*** [~s] ~p ~s *** " "~n " ++ F ++ "~n", - [format_timestamp(now()), self(), "undefined" | A]). + [?FTS(), self(), "undefined" | A]). ms() -> - {A,B,C} = erlang:now(), - A*1000000000+B*1000+(C div 1000). - + erlang:monotonic_time(milli_seconds). + -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). diff --git a/lib/megaco/test/megaco_test_deliver.erl b/lib/megaco/test/megaco_test_deliver.erl index 78033f0e36..c042d9c9a7 100644 --- a/lib/megaco/test/megaco_test_deliver.erl +++ b/lib/megaco/test/megaco_test_deliver.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2016. All Rights Reserved. +%% Copyright Ericsson AB 2007-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -186,4 +186,4 @@ i(F) -> i(F, []). i(F, A) -> - io:format("~p ~w:" ++ F ++ "~n", [self(), ?MODULE | A]). + io:format("*** [~s] ~p ~w:" ++ F ++ "~n", [?FTS(), self(), ?MODULE | A]). diff --git a/lib/megaco/test/megaco_test_generator.erl b/lib/megaco/test/megaco_test_generator.erl index 63f66bda07..8ea7f5ddf7 100644 --- a/lib/megaco/test/megaco_test_generator.erl +++ b/lib/megaco/test/megaco_test_generator.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2016. All Rights Reserved. +%% Copyright Ericsson AB 2007-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -47,7 +47,6 @@ print/3, print/4 ]). --export([behaviour_info/1]). %% Internal exports -export([start/4]). @@ -65,6 +64,7 @@ -include_lib("megaco/include/megaco.hrl"). +-include("megaco_test_lib.hrl"). %%---------------------------------------------------------------------- @@ -90,15 +90,32 @@ %%% API %%%========================================================================= -behaviour_info(callbacks) -> - [ - {init, 1}, - {handle_parse, 2}, - {handle_exec, 2}, - {terminate, 2} - ]; -behaviour_info(_Other) -> - undefined. +-callback init(Args) -> {ok, State} | {error, Reason} when + Args :: term(), + State :: term(), + Reason :: term(). + +-callback handle_parse(Instruction, State) -> + {ok, NewInstruction, NewState} | + {error, Reason} when + Instruction :: term(), + State :: term(), + NewInstruction :: term(), + NewState :: term(), + Reason :: term(). + +-callback handle_exec(Instruction, State) -> + {ok, NewState} | + {error, Reason} when + Instruction :: term(), + State :: term(), + NewState :: term(), + Reason :: term(). + +-callback terminate(Reason, State) -> + megaco:void() when + Reason :: term(), + State :: term(). %%---------------------------------------------------------------------- @@ -533,22 +550,13 @@ print(P, F, A) -> print([], undefined, F, A) -> io:format("*** [~s] ~p *** " ++ "~n " ++ F ++ "~n", - [format_timestamp(now()),self()|A]); + [?FTS(), self() | A]); print(P, undefined, F, A) -> io:format("*** [~s] ~p ~s *** " ++ "~n " ++ F ++ "~n", - [format_timestamp(now()),self(),P|A]); + [?FTS(), self(), P | A]); print(P, N, F, A) -> io:format("*** [~s] ~p ~s~s *** " ++ "~n " ++ F ++ "~n", - [format_timestamp(now()),self(),N,P|A]). - + [?FTS(), self(), N, P | 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). diff --git a/lib/megaco/test/megaco_test_generic_transport.erl b/lib/megaco/test/megaco_test_generic_transport.erl index 3185e4c6b6..cd387f748a 100644 --- a/lib/megaco/test/megaco_test_generic_transport.erl +++ b/lib/megaco/test/megaco_test_generic_transport.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2016. All Rights Reserved. +%% Copyright Ericsson AB 2007-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -59,7 +59,7 @@ receive_handle}). -include_lib("megaco/include/megaco.hrl"). -%% -include("megaco_test_lib.hrl"). +-include("megaco_test_lib.hrl"). -define(SERVER, ?MODULE). @@ -335,21 +335,11 @@ d(F) -> d(F, []). d(F, A) -> - print(now(), F, A). + print(F, A). -print(Ts, F, A) -> +print(F, A) -> io:format("*** [~s] GENERIC TRANSPORT [~p] ***" "~n " ++ F ++ "~n", - [format_timestamp(Ts), self() | 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). - + [?FTS(), self() | A]). diff --git a/lib/megaco/test/megaco_test_lib.erl b/lib/megaco/test/megaco_test_lib.erl index 0617b96456..7c8c287e7c 100644 --- a/lib/megaco/test/megaco_test_lib.erl +++ b/lib/megaco/test/megaco_test_lib.erl @@ -318,9 +318,9 @@ t({Mod, {group, Name} = Group, Groups}, Config) [Name, Error]), [{failed, {Mod, Group}, Error}] catch - exit:{skipped, SkipReason} -> + exit:{skip, SkipReason} -> io:format(" => skipping group: ~p~n", [SkipReason]), - [{skipped, {Mod, Group}, SkipReason, 0}]; + [{skip, {Mod, Group}, SkipReason, 0}]; error:undef -> [t({Mod, Case, Groups}, Config) || Case <- GroupsAndCases]; @@ -383,9 +383,9 @@ t(Mod, Config) when is_atom(Mod) -> io:format(" => suite init failed: ~p~n", [Error]), [{failed, {Mod, init_per_suite}, Error}] catch - exit:{skipped, SkipReason} -> + exit:{skip, SkipReason} -> io:format(" => skipping suite: ~p~n", [SkipReason]), - [{skipped, {Mod, init_per_suite}, SkipReason, 0}]; + [{skip, {Mod, init_per_suite}, SkipReason, 0}]; error:undef -> [t({Mod, Case, Groups}, Config) || Case <- Cases]; T:E -> @@ -458,10 +458,10 @@ wait_for_evaluator(Pid, Mod, Fun, Config, Errors, AccTime) -> megaco:report_event(20, Mod, ?MODULE, Label ++ " failed", [TestCase, Config, {return, Fail}, Errors]), {failed, {Mod,Fun}, Fail, Time}; - {'EXIT', Pid, {skipped, Reason}, Time} -> + {'EXIT', Pid, {skip, Reason}, Time} -> megaco:report_event(20, Mod, ?MODULE, Label ++ " skipped", - [TestCase, Config, {skipped, Reason}]), - {skipped, {Mod, Fun}, Errors, Time}; + [TestCase, Config, {skip, Reason}]), + {skip, {Mod, Fun}, Errors, Time}; {'EXIT', Pid, Reason, Time} -> megaco:report_event(20, Mod, ?MODULE, Label ++ " crashed", [TestCase, Config, {'EXIT', Reason}]), @@ -492,14 +492,14 @@ do_eval(ReplyTo, Mod, Fun, Config) -> error:undef -> %% p("do_eval -> error - undef", []), ReplyTo ! {'EXIT', self(), undef, 0}; - exit:{skipped, Reason} -> + exit:{skip, Reason} -> %% p("do_eval -> exit - skipped" %% "~n Reason: ~p", [Reason]), T2 = os:timestamp(), Time = timer:now_diff(T2, T1), display_tc_time(Time), display_system_info("after (skipped)", Mod, Fun), - ReplyTo ! {'EXIT', self(), {skipped, Reason}, Time}; + ReplyTo ! {'EXIT', self(), {skip, Reason}, Time}; exit:{suite_failed, Reason} -> %% p("do_eval -> exit - suite-failed" %% "~n Reason: ~p", [Reason]), @@ -616,9 +616,9 @@ display_result(Res) when is_list(Res) -> Ok = [{MF, Time} || {ok, MF, _, Time} <- Res], Nyi = [MF || {nyi, MF, _, _Time} <- Res], SkippedGrps = [{{M,G}, Reason} || - {skipped, {M, {group, G}}, Reason, _Time} <- Res], + {skip, {M, {group, G}}, Reason, _Time} <- Res], SkippedCases = [{MF, Reason} || - {skipped, {_M, F} = MF, Reason, _Time} <- Res, + {skip, {_M, F} = MF, Reason, _Time} <- Res, is_atom(F)], FailedGrps = [{{M,G}, Reason} || {failed, {M, {group, G}}, Reason, _Time} <- Res], @@ -730,15 +730,18 @@ log(Format, Args, Mod, Line) -> [self(), Mod, Line] ++ Args) end. +skip(Reason) -> + exit({skip, Reason}). + skip(Actual, File, Line) -> - log("Skipping test case~n", [], File, Line), - String = lists:flatten(io_lib:format("Skipping test case ~p(~p): ~p~n", - [File, Line, Actual])), - exit({skipped, String}). + log("Skipping test case: ~p~n", [Actual], File, Line), + String = f("~p(~p): ~p~n", [File, Line, Actual]), + skip(String). fatal_skip(Actual, File, Line) -> error(Actual, File, Line), - exit({skipped, {fatal, Actual, File, Line}}). + skip({fatal, Actual, File, Line}). + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -750,7 +753,8 @@ flush() -> after 1000 -> [] end. - + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Check if process is alive and kicking still_alive(Pid) -> @@ -988,11 +992,14 @@ node_to_name_and_host(Node) -> start_nodes([Node | Nodes], File, Line) -> case net_adm:ping(Node) of pong -> + p("node ~p already running", [Node]), start_nodes(Nodes, File, Line); pang -> [Name, Host] = node_to_name_and_host(Node), + p("try start node ~p", [Node]), case slave:start_link(Host, Name) of {ok, NewNode} when NewNode =:= Node -> + p("node ~p started - now set path, cwd and sync", [Node]), Path = code:get_path(), {ok, Cwd} = file:get_cwd(), true = rpc:call(Node, code, set_path, [Path]), @@ -1001,6 +1008,7 @@ start_nodes([Node | Nodes], File, Line) -> {_, []} = rpc:multicall(global, sync, []), start_nodes(Nodes, File, Line); Other -> + p("failed starting node ~p: ~p", [Node, Other]), fatal_skip({cannot_start_node, Node, Other}, File, Line) end end; @@ -1014,4 +1022,4 @@ f(F, A) -> lists:flatten(io_lib:format(F, A)). p(F, A) -> - io:format("~p~w:" ++ F ++ "~n", [self(), ?MODULE |A]). + io:format("~s ~p " ++ F ++ "~n", [?FTS(), self() | A]). diff --git a/lib/megaco/test/megaco_test_lib.hrl b/lib/megaco/test/megaco_test_lib.hrl index 409f8d52e5..546ecaab9a 100644 --- a/lib/megaco/test/megaco_test_lib.hrl +++ b/lib/megaco/test/megaco_test_lib.hrl @@ -32,8 +32,6 @@ -define(ERROR(Reason), megaco_test_lib:error(Reason, ?MODULE, ?LINE)). --define(F(FMT, ARGS), lists:flatten(io_lib:format(FMT, ARGS))). - -define(OS_BASED_SKIP(Skippable), megaco_test_lib:os_based_skip(Skippable)). @@ -83,7 +81,10 @@ -define(SLEEP(MSEC), megaco_test_lib:sleep(MSEC)). -define(HOURS(T), megaco_test_lib:hours(T)). --define(MINUTES(T), megaco_test_lib:minutes(T)). --define(SECONDS(T), megaco_test_lib:seconds(T)). +-define(MINS(T), megaco_test_lib:minutes(T)). +-define(MINUTES(T), ?MINS(T)). +-define(SECS(T), megaco_test_lib:seconds(T)). +-define(SECONDS(T), ?SECS(T)). -define(FTS(), megaco:format_timestamp(erlang:timestamp())). - +-define(FTS(TS), megaco:format_timestamp(TS)). +-define(F(F,A), lists:flatten(io_lib:format(F, A))). diff --git a/lib/megaco/test/megaco_test_megaco_generator.erl b/lib/megaco/test/megaco_test_megaco_generator.erl index 8a37fa33fe..4e0f2e334c 100644 --- a/lib/megaco/test/megaco_test_megaco_generator.erl +++ b/lib/megaco/test/megaco_test_megaco_generator.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2016. All Rights Reserved. +%% Copyright Ericsson AB 2007-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -118,7 +118,7 @@ init([]) -> %% ----- instruction parser ----- handle_parse({debug, Debug} = Instruction, State) - when (Debug == true) orelse (Debug == false) -> + when is_boolean(Debug) -> {ok, Instruction, State}; handle_parse({expect_nothing, To} = Instruction, State) @@ -126,9 +126,9 @@ handle_parse({expect_nothing, To} = Instruction, State) {ok, Instruction, State}; handle_parse({megaco_trace, Level} = Instruction, State) - when (Level == disable) orelse - (Level == max) orelse - (Level == min) orelse + when (Level =:= disable) orelse + (Level =:= max) orelse + (Level =:= min) orelse is_integer(Level) -> {ok, Instruction, State}; @@ -1096,11 +1096,10 @@ handle_megaco_callback_reply(_, _, _, _) -> %%---------------------------------------------------------------------- random_init() -> - {A,B,C} = now(), - random:seed(A,B,C). + ok. random(N) -> - random:uniform(N). + rand:uniform(N). get_config(Key, Opts) -> diff --git a/lib/megaco/test/megaco_test_mg.erl b/lib/megaco/test/megaco_test_mg.erl index d6a9a8c314..38883c94f0 100644 --- a/lib/megaco/test/megaco_test_mg.erl +++ b/lib/megaco/test/megaco_test_mg.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2016. All Rights Reserved. +%% Copyright Ericsson AB 2003-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -79,7 +79,10 @@ reply_counter = 0, mload_info = undefined, parent = undefined, - dsi_timer}). + dsi_timer, + evs = []}). + +-define(EVS_MAX, 10). %%% -------------------------------------------------------------------- @@ -364,7 +367,7 @@ mg(Parent, Verbosity, Config) -> MG = #mg{parent = Parent, mid = Mid, dsi_timer = DSITimer}, i("mg -> started"), put(verbosity, Verbosity), - case (catch loop(MG)) of + case (catch loop(evs(MG, started))) of {'EXIT', normal} -> exit(normal); {'EXIT', Reason} -> @@ -438,12 +441,12 @@ loop(#mg{parent = Parent, mid = Mid} = S) -> {display_system_info, Time} -> display_system_info(S#mg.mid), NewTimer = create_timer(Time, display_system_info), - loop(S#mg{dsi_timer = NewTimer}); + loop(evs(S#mg{dsi_timer = NewTimer}, {dsi, Time})); {verbosity, V, Parent} -> i("loop -> received new verbosity: ~p", [V]), put(verbosity,V), - loop(S); + loop(evs(S, {verb, V})); {stop, Parent} -> @@ -453,7 +456,7 @@ loop(#mg{parent = Parent, mid = Mid} = S) -> Res = do_stop(Mid), d("loop -> stop result: ~p", [Res]), server_reply(Parent, stopped, {ok, Res}), - exit(normal); + done(evs(S, stop), normal); {{enable_test_code, Tag, Fun}, Parent} -> i("loop -> enable_test_code: ~p, ~p", [Tag, Fun]), @@ -463,52 +466,52 @@ loop(#mg{parent = Parent, mid = Mid} = S) -> "~n ets:tab2list(megaco_test_data): ~p", [Reply,ets:tab2list(megaco_test_data)]), server_reply(Parent, enable_test_code_reply, Reply), - loop(S); + loop(evs(S, {enable_test_code, Tag})); {{encode_ar_first, EAF}, Parent} -> i("loop -> encode_ar_first: ~p", [EAF]), {Reply, S1} = handle_encode_ar_first(S, EAF), server_reply(Parent, encode_ar_first_reply, Reply), - loop(S1#mg{encode_ar_first = EAF}); + loop(evs(S1#mg{encode_ar_first = EAF}, {enc_arf, EAF})); %% Give me statistics {statistics, Parent} -> i("loop -> got request for statistics", []), Stats = do_get_statistics(Mid), server_reply(Parent, statistics_reply, {ok, Stats}), - loop(S); + loop(evs(S, stats)); {reset_stats, Parent} -> i("loop -> got request to reset stats counters", []), do_reset_stats(Mid), server_reply(Parent, reset_stats_ack, ok), - loop(S); + loop(evs(S, rst_stats)); {{user_info, Tag}, Parent} -> i("loop -> got user_info request for ~w", [Tag]), Res = do_get_user_info(Mid, Tag), d("loop -> Res: ~p", [Res]), server_reply(Parent, user_info_ack, Res), - loop(S); + loop(evs(S, {ui, Tag})); {{update_user_info, Tag, Val}, Parent} -> i("loop -> got update_user_info: ~w -> ~p", [Tag, Val]), Res = do_update_user_info(Mid, Tag, Val), d("loop -> Res: ~p", [Res]), server_reply(Parent, update_user_info_ack, Res), - loop(S); + loop(evs(S, {uui, {Tag, Val}})); {{conn_info, Tag}, Parent} -> i("loop -> got conn_info request for ~w", [Tag]), Res = do_get_conn_info(Mid, Tag), server_reply(Parent, conn_info_ack, Res), - loop(S); + loop(evs(S, {ci, Tag})); {{update_conn_info, Tag, Val}, Parent} -> i("loop -> got update_conn_info: ~w -> ~p", [Tag, Val]), Res = do_update_conn_info(Mid, Tag, Val), server_reply(Parent, update_conn_info_ack, Res), - loop(S); + loop(evs(S, {uci, {Tag, Val}})); %% Do a service change @@ -526,28 +529,28 @@ loop(#mg{parent = Parent, mid = Mid} = S) -> server_reply(Parent, service_change_reply, Error), S end, - loop(S1); + loop(evs(S1, svc_ch)); {{group_requests, N}, Parent} when N > 0 -> i("loop -> received group_requests ~p", [N]), Reply = {ok, S#mg.group_size}, server_reply(Parent, group_requests_reply, Reply), - loop(S#mg{group_size = N}); + loop(evs(S#mg{group_size = N}, {grp_reqs, N})); {{ack_info, To}, Parent} -> i("loop -> received request to inform about received ack's ", []), - loop(S#mg{ack_info = To}); + loop(evs(S#mg{ack_info = To}, {acki, To})); {{rep_info, To}, Parent} -> i("loop -> received request to inform about received rep's ", []), - loop(S#mg{rep_info = To}); + loop(evs(S#mg{rep_info = To}, {repi, To})); %% Make a sync-call {notify_request, Parent} -> i("loop -> received request to send notify request ", []), {Res, S1} = do_handle_notify_request(S), d("loop -> notify request result: ~p", [Res]), - loop(S1); + loop(evs(S1, not_req)); %% sync-call complete {notify_request_complete, NotifyReply, Pid} -> @@ -556,7 +559,7 @@ loop(#mg{parent = Parent, mid = Mid} = S) -> "~n NotifyReply: ~p", [Pid, NotifyReply]), server_reply(Parent, notify_request_reply, NotifyReply), - loop(S#mg{req_handler = undefined}); + loop(evs(S#mg{req_handler = undefined}, {not_reqc, NotifyReply})); %% cancel requests @@ -564,14 +567,14 @@ loop(#mg{parent = Parent, mid = Mid} = S) -> i("loop -> received request to cancel (all) megaco requests ", []), Res = do_cancel_requests(Mid, Reason), server_reply(Parent, cancel_request_reply, Res), - loop(S); + loop(evs(S, {creq, Reason})); %% Apply multi-load {apply_multi_load, {NL, NR}, Parent} -> i("loop -> received apply_multi_load request: ~w, ~w", [NL, NR]), S1 = start_loaders(S, NL, NR), - loop(S1); + loop(evs(S1, {apply_mload, {NL, NR}})); %% Apply some load @@ -587,12 +590,12 @@ loop(#mg{parent = Parent, mid = Mid} = S) -> server_reply(Parent, apply_load_ack, Error), S end, - loop(S1); + loop(evs(S1, {apply_load, Times})); {apply_load_timeout, _} -> d("loop -> received apply_load timeout", []), S1 = do_apply_load(S), - loop(S1); + loop(evs(S1, apply_loadto)); %% Megaco callback messages @@ -604,22 +607,35 @@ loop(#mg{parent = Parent, mid = Mid} = S) -> {Reply, S1} = handle_megaco_request(S, Request), d("loop -> send (megaco callback) request reply: ~n~p", [Reply]), From ! {reply, Reply, self()}, - loop(S1); + loop(evs(S1, {req, {Request, Mid, From}})); {'EXIT', Pid, Reason} -> - i("loop -> received exit signal from ~p: ~n~p", [Pid, Reason]), + i("loop -> received exit signal from ~p: " + "~n ~p", [Pid, Reason]), S1 = handle_exit(S, Pid, Reason), - loop(S1); + loop(evs(S1, {exit, {Pid, Reason}})); Invalid -> error_msg("received invalid request: ~n~p", [Invalid]), - loop(S) + loop(evs(S, {invalid, Invalid})) end. +evs(#mg{evs = EVS} = S, Ev) when (length(EVS) < ?EVS_MAX) -> + S#mg{evs = [{?FTS(), Ev}|EVS]}; +evs(#mg{evs = EVS} = S, Ev) -> + S#mg{evs = [{?FTS(), Ev}|lists:droplast(EVS)]}. + +done(#mg{evs = EVS}, Reason) -> + info_msg("Exiting with latest event(s): " + "~n ~p" + "~n", [EVS]), + exit(Reason). + + handle_encode_ar_first(#mg{encode_ar_first = Old} = MG, New) when (New =:= true) orelse (New =:= false) -> {{ok, Old}, MG#mg{encode_ar_first = New}}; @@ -776,7 +792,7 @@ do_service_change(#mg{state = State} = MG) -> {{error, {invalid_state, State}}, MG}. do_service_change(ConnHandle, Method, EAF, Reason) -> - d("sending service change using:" + d("send service change using:" "~n ConnHandle: ~p" "~n Method: ~p" "~n EAF: ~p" @@ -844,10 +860,10 @@ loader_main(EAF, N, CH) -> -handle_exit(#mg{parent = Pid}, Pid, Reason) -> +handle_exit(#mg{parent = Pid} = S, Pid, Reason) -> error_msg("received exit from the parent:" "~n ~p", [Reason]), - exit({parent_terminated, Reason}); + done(S, {parent_terminated, Reason}); handle_exit(#mg{parent = Parent, req_handler = Pid} = MG, Pid, Reason) -> error_msg("received unexpected exit from the request handler:" @@ -1423,6 +1439,7 @@ sleep(X) -> receive after X -> ok end. +info_msg(F,A) -> error_logger:info_msg("MG: " ++ F ++ "~n",A). error_msg(F,A) -> error_logger:error_msg("MG: " ++ F ++ "~n",A). @@ -1536,37 +1553,28 @@ print(Severity, Verbosity, P, F, A) -> print(true, P, F, A) -> io:format("*** [~s] ~s ~p ~s ***" "~n " ++ F ++ "~n~n", - [format_timestamp(now()), P, self(), get(sname) | A]); + [?FTS(), P, self(), get(sname) | A]); print(_, _, _, _) -> 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). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% random_init() -> - {A,B,C} = now(), - random:seed(A,B,C). + ok. random() -> random(50). random(N) -> - random:uniform(N). + rand:uniform(N). display_system_info(Mid) -> display_system_info(Mid, ""). display_system_info(Mid, Pre) -> - TimeStr = format_timestamp(now()), + TimeStr = ?FTS(), MibStr = lists:flatten(io_lib:format("~p ", [Mid])), megaco_test_lib:display_system_info(MibStr ++ Pre ++ TimeStr). diff --git a/lib/megaco/test/megaco_test_mgc.erl b/lib/megaco/test/megaco_test_mgc.erl index 045bc7c9fd..a9027ca68e 100644 --- a/lib/megaco/test/megaco_test_mgc.erl +++ b/lib/megaco/test/megaco_test_mgc.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2016. All Rights Reserved. +%% Copyright Ericsson AB 2003-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -75,7 +75,10 @@ abort_info = undefined, req_info = undefined, mg = [], - dsi_timer}). + dsi_timer, + evs = []}). + +-define(EVS_MAX, 10). %%% ------------------------------------------------------------------ @@ -297,7 +300,7 @@ mgc(Parent, Verbosity, Config) -> dsi_timer = DSITimer}, i("mgc -> started"), display_system_info("at start "), - loop(S) + loop(evs(S, started)) end. init(Config) -> @@ -359,7 +362,7 @@ loop(S) -> {display_system_info, Time} -> display_system_info(S#mgc.mid), NewTimer = create_timer(Time, display_system_info), - loop(S#mgc{dsi_timer = NewTimer}); + loop(evs(S#mgc{dsi_timer = NewTimer}, {dsi, Time})); {stop, Parent} when S#mgc.parent =:= Parent -> i("loop -> stopping", []), @@ -371,7 +374,7 @@ loop(S) -> application:stop(megaco), i("loop -> stopped", []), server_reply(Parent, stopped, ok), - exit(normal); + done(evs(S, stop), normal); {{disconnect, Reason}, Parent} when S#mgc.parent == Parent -> i("loop -> disconnecting", []), @@ -379,22 +382,22 @@ loop(S) -> [Conn|_] = megaco:user_info(Mid, connections), Res = megaco:disconnect(Conn, {self(), Reason}), server_reply(Parent, disconnected, Res), - loop(S); + loop(evs(S, {disconnect, Reason})); {{update_user_info, Tag, Val}, Parent} when S#mgc.parent == Parent -> i("loop -> got update_user_info: ~w -> ~p", [Tag, Val]), Res = (catch megaco:update_user_info(S#mgc.mid, Tag, Val)), d("loop -> Res: ~p", [Res]), server_reply(Parent, update_user_info_ack, Res), - loop(S); - - {{user_info, Tag}, Parent} when S#mgc.parent == Parent -> - i("loop -> got user_info request for ~w", [Tag]), - Res = (catch megaco:user_info(S#mgc.mid, Tag)), - d("loop -> Res: ~p", [Res]), - server_reply(Parent, user_info_ack, Res), - loop(S); - + loop(evs(S, {uui, {Tag, Val}})); + + {{user_info, Tag}, Parent} when S#mgc.parent == Parent -> + i("loop -> got user_info request for ~w", [Tag]), + Res = (catch megaco:user_info(S#mgc.mid, Tag)), + d("loop -> Res: ~p", [Res]), + server_reply(Parent, user_info_ack, Res), + loop(evs(S, {ui, Tag})); + {{update_conn_info, Tag, Val}, Parent} when S#mgc.parent == Parent -> i("loop -> got update_conn_info: ~w -> ~p", [Tag, Val]), Conns = megaco:user_info(S#mgc.mid, connections), @@ -404,7 +407,7 @@ loop(S) -> Res = lists:map(Fun, Conns), d("loop -> Res: ~p", [Res]), server_reply(Parent, update_conn_info_ack, Res), - loop(S); + loop(evs(S, {uci, {Tag, Val}})); {{conn_info, Tag}, Parent} when S#mgc.parent == Parent -> i("loop -> got conn_info request for ~w", [Tag]), @@ -415,11 +418,11 @@ loop(S) -> Res = lists:map(Fun, Conns), d("loop -> Res: ~p", [Res]), server_reply(Parent, conn_info_ack, Res), - loop(S); + loop(evs(S, {ci, Tag})); %% - {request_action, {Action, To}, Parent} when S#mgc.parent == Parent -> + {request_action, {Action, To}, Parent} when S#mgc.parent == Parent -> i("loop -> got new request_action: ~p:~w", [Action,To]), {Reply, S1} = case lists:member(Action, ?valid_actions) of @@ -432,7 +435,7 @@ loop(S) -> {{error, {invalid_action, Action}}, S} end, server_reply(Parent, request_action_ack, Reply), - loop(S1); + loop(evs(S1, {req_act, {Action, To}})); %% Reset stats @@ -440,7 +443,7 @@ loop(S) -> i("loop -> got request to reset stats counters"), do_reset_stats(S#mgc.mid), server_reply(Parent, reset_stats_ack, ok), - loop(S); + loop(evs(S, rst_stats)); %% Give me statistics @@ -466,7 +469,7 @@ loop(S) -> lists:map(GetTrans, megaco:user_info(Mid, connections)), Reply = {ok, [{gen, Gen}, {trans, Trans}]}, server_reply(Parent, {statistics_reply, 1}, Reply), - loop(S); + loop(evs(S, {stats, 1})); {{statistics, 2}, Parent} when S#mgc.parent == Parent -> @@ -477,7 +480,7 @@ loop(S) -> UdpStats = get_trans_stats(UdpSup, megaco_udp), Reply = {ok, [{gen, Gen}, {trans, [TcpStats, UdpStats]}]}, server_reply(Parent, {statistics_reply, 2}, Reply), - loop(S); + loop(evs(S, {stats, 2})); %% Megaco callback messages @@ -487,28 +490,28 @@ loop(S) -> {Reply, S1} = handle_megaco_request(Request, S), d("loop -> send request reply: ~n~p", [Reply]), reply(From, Reply), - loop(S1); + loop(evs(S1, {req, Request})); {ack_info, To, Parent} when S#mgc.parent == Parent -> i("loop -> received request to inform about received ack's ", []), - loop(S#mgc{ack_info = To}); + loop(evs(S#mgc{ack_info = To}, {acki, To})); {abort_info, To, Parent} when S#mgc.parent == Parent -> i("loop -> received request to inform about received aborts ", []), - loop(S#mgc{abort_info = To}); + loop(evs(S#mgc{abort_info = To}, {abi, To})); {req_info, To, Parent} when S#mgc.parent == Parent -> i("loop -> received request to inform about received req's ", []), - loop(S#mgc{req_info = To}); + loop(evs(S#mgc{req_info = To}, {reqi, To})); {verbosity, V, Parent} when S#mgc.parent == Parent -> i("loop -> received new verbosity: ~p", [V]), put(verbosity,V), - loop(S); + loop(evs(S, {verb, V})); {'EXIT', Pid, Reason} when S#mgc.tcp_sup =:= Pid -> @@ -525,7 +528,7 @@ loop(S) -> i("loop -> stopped", []), StopReason = {error, {tcp_terminated, Pid, Reason}}, server_reply(S#mgc.parent, stopped, StopReason), - exit(StopReason); + done(evs(S, {tcp_sup_exit, Reason}), StopReason); {'EXIT', Pid, Reason} when S#mgc.udp_sup =:= Pid -> @@ -542,15 +545,27 @@ loop(S) -> i("loop -> stopped", []), StopReason = {error, {udp_terminated, Pid, Reason}}, server_reply(S#mgc.parent, stopped, StopReason), - exit(StopReason); + done(evs(S, {udp_sup_exit, Reason}), StopReason); Invalid -> i("loop -> received invalid request: ~p", [Invalid]), - loop(S) + loop(evs(S, {invalid, Invalid})) end. +evs(#mgc{evs = EVS} = S, Ev) when (length(EVS) < ?EVS_MAX) -> + S#mgc{evs = [{?FTS(), Ev}|EVS]}; +evs(#mgc{evs = EVS} = S, Ev) -> + S#mgc{evs = [{?FTS(), Ev}|lists:droplast(EVS)]}. + +done(#mgc{evs = EVS}, Reason) -> + info_msg("Exiting with latest event(s): " + "~n ~p" + "~n", [EVS]), + exit(Reason). + + do_reset_stats(Mid) -> megaco:reset_stats(), do_reset_trans_stats(megaco:user_info(Mid, connections), []). @@ -825,10 +840,10 @@ handle_megaco_request({handle_trans_ack, CH, PV, AS, AD}, handle_megaco_request({handle_trans_ack, CH, PV, AS, AD}, S) -> d("handle_megaco_request(handle_trans_ack) -> entry with" - "~n CH: ~p" - "~n PV: ~p" - "~n AS: ~p" - "~n AD: ~p", [CH, PV, AS, AD]), + "~n Conn Handle: ~p" + "~n Prot Version: ~p" + "~n Ack Status: ~p" + "~n Ack Data: ~p", [CH, PV, AS, AD]), {ok, S}; handle_megaco_request({handle_unexpected_trans, CH, PV, TR}, S) -> @@ -1090,6 +1105,7 @@ sleep(X) -> receive after X -> ok end. +info_msg(F,A) -> error_logger:info_msg("MGC: " ++ F ++ "~n",A). error_msg(F,A) -> error_logger:error_msg("MGC: " ++ F ++ "~n",A). @@ -1153,18 +1169,17 @@ get_conf(Key, Config, Default) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% random_init() -> - {A,B,C} = now(), - random:seed(A,B,C). + ok. random(N) -> - random:uniform(N). + rand:uniform(N). display_system_info(Mid) -> display_system_info(Mid, ""). display_system_info(Mid, Pre) -> - TimeStr = format_timestamp(now()), + TimeStr = ?FTS(), MibStr = lists:flatten(io_lib:format("~p ", [Mid])), megaco_test_lib:display_system_info(MibStr ++ Pre ++ TimeStr). @@ -1209,14 +1224,6 @@ print(_, _, _, _) -> print(P, F, A) -> io:format("*** [~s] ~s ~p ~s ***" "~n " ++ F ++ "~n~n", - [format_timestamp(now()), P, self(), get(sname) | 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). + [?FTS(), P, self(), get(sname) | A]). + diff --git a/lib/megaco/test/megaco_timer_test.erl b/lib/megaco/test/megaco_timer_test.erl index d3e8e27636..84c314d8ed 100644 --- a/lib/megaco/test/megaco_timer_test.erl +++ b/lib/megaco/test/megaco_timer_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2016. All Rights Reserved. +%% Copyright Ericsson AB 2007-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -362,6 +362,8 @@ integer_timer_start_and_stop(Config) when is_list(Config) -> case tmr_stop(Ref) of ok -> ok; + {ok, _} -> + ok; CancelRes -> ?SKIP({cancel_failed, CancelRes}) end diff --git a/lib/megaco/test/megaco_trans_test.erl b/lib/megaco/test/megaco_trans_test.erl index fb44a3c6e6..37bc134c8d 100644 --- a/lib/megaco/test/megaco_trans_test.erl +++ b/lib/megaco/test/megaco_trans_test.erl @@ -295,7 +295,7 @@ multi_ack_timeout(doc) -> []; multi_ack_timeout(Config) when is_list(Config) -> %% <CONDITIONAL-SKIP> - Skippable = [win32, {unix, [darwin, linux]}], + Skippable = [win32, {unix, [darwin, linux, sunos]}], % Is there any left? Condition = fun() -> ?OS_BASED_SKIP(Skippable) end, ?NON_PC_TC_MAYBE_SKIP(Config, Condition), %% </CONDITIONAL-SKIP> @@ -9247,10 +9247,10 @@ await_ack(User, N, Timeout, Expected) when (N > 0) andalso is_integer(Timeout) - T = tim(), receive {ack_received, User, Expected} -> - d("await_ack -> received another ack"), + d("await_ack -> received another expected ack"), await_ack(User, N-1, Timeout - (tim() - T), Expected); {ack_received, User, UnExpected} -> - e("await_ack -> unexpected ack result: ~p", [UnExpected]), + e("await_ack -> received unexpected ack result: ~p", [UnExpected]), exit({unexpected_ack_result, UnExpected, Expected}) after Timeout -> exit({await_ack_timeout, N}) @@ -9266,35 +9266,6 @@ await_ack(User, N, infinity, Expected) when N > 0 -> exit({unexpected_ack_result, UnExpected, Expected}) end. -%% await_req(_User, 0, Timeout) -> -%% d("await_req -> done when Timeout = ~p", [Timeout]), -%% ok; -%% await_req(User, N, Timeout) when (N > 0) andalso is_integer(Timeout) -> -%% d("await_req -> entry with N: ~p, Timeout: ~p", [N,Timeout]), -%% T = tim(), -%% receive -%% {req_received, User, ARs} -> -%% d("await_req -> received req(s) when N = ~w", [N]), -%% N1 = await_req1(N, ARs), -%% await_req(User, N1, Timeout - (tim() - T)) -%% after Timeout -> -%% exit({await_req_timeout, N}) -%% end; -%% await_req(User, N, infinity) when N > 0 -> -%% d("await_req -> entry with N: ~p", [N]), -%% receive -%% {req_received, User, ARs} -> -%% d("await_req -> received req(s) when N = ~2",[N]), -%% N1 = await_req1(N, ARs), -%% await_req(User, N1, infinity) -%% end. - -%% await_req1(N, []) when N >= 0 -> -%% N; -%% await_req1(N, [AR|ARs]) when (N > 0) andalso is_record(AR, 'ActionRequest') -> -%% await_req1(N-1, ARs); -%% await_req1(N, ARs) -> -%% exit({unexpected_req_result, N, ARs}). tim() -> {A,B,C} = erlang:timestamp(), diff --git a/lib/megaco/test/megaco_udp_test.erl b/lib/megaco/test/megaco_udp_test.erl index cc03ec733a..39ff44709e 100644 --- a/lib/megaco/test/megaco_udp_test.erl +++ b/lib/megaco/test/megaco_udp_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2016. All Rights Reserved. +%% Copyright Ericsson AB 2000-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -1211,23 +1211,14 @@ p(F, A) -> p(S, F, A) when is_list(S) -> io:format("*** [~s] ~p ~s ***" "~n " ++ F ++ "~n", - [format_timestamp(now()), self(), S | A]); + [?FTS(), self(), S | A]); p(_S, F, A) -> io:format("*** [~s] ~p ~s *** " "~n " ++ F ++ "~n", - [format_timestamp(now()), self(), "undefined" | A]). + [?FTS(), self(), "undefined" | A]). ms() -> - {A,B,C} = erlang:now(), - A*1000000000+B*1000+(C div 1000). + erlang:monotonic_time(milli_seconds). -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). diff --git a/lib/snmp/src/agent/snmpa_supervisor.erl b/lib/snmp/src/agent/snmpa_supervisor.erl index 2cb0556001..7d5c6da2c8 100644 --- a/lib/snmp/src/agent/snmpa_supervisor.erl +++ b/lib/snmp/src/agent/snmpa_supervisor.erl @@ -22,7 +22,7 @@ -behaviour(supervisor). %% External exports --export([start_link/2]). +-export([start_link/2, stop/0, stop/1]). -export([start_sub_sup/1, start_master_sup/1]). -export([start_sub_agent/3, stop_sub_agent/1]). @@ -91,6 +91,39 @@ start_link(master, Opts, {takeover, Node}) -> Else end. + +stop() -> + stop(0). + +stop(Timeout) -> + case whereis(?SERVER) of + Pid when is_pid(Pid) -> + stop(Pid, Timeout); + _ -> + not_running + end. + +%% For some unfathomable reason there is no "nice" way to stop +%% a supervisor. The "normal" way to do it is: +%% 1) exit(Pid, kill) (kaboom) +%% 2) If the caller is the *parent*: exit(Pid, shutdown) +%% So, here we do it the really ugly way...but since this function is +%% intended for testing (mostly)... +stop(Pid, Timeout) when (Timeout =:= 0) -> + sys:terminate(Pid, shutdown), + ok; +stop(Pid, Timeout) -> + MRef = erlang:monitor(process, Pid), + sys:terminate(Pid, shutdown), + receive + {'DOWN', MRef, process, Pid, _} -> + ok + after Timeout -> + erlang:demonitor(MRef, [flush]), + {error, timeout} + end. + + get_own_loaded_mibs() -> AgentInfo = snmpa:info(snmp_master_agent), [ Name || {Name, _, _} <- loaded_mibs(AgentInfo) ]. diff --git a/lib/snmp/src/manager/snmpm.erl b/lib/snmp/src/manager/snmpm.erl index cf8c95d69f..8e60cecaf9 100644 --- a/lib/snmp/src/manager/snmpm.erl +++ b/lib/snmp/src/manager/snmpm.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2016. All Rights Reserved. +%% Copyright Ericsson AB 2004-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -32,7 +32,7 @@ %% Management API start/0, start/1, start_link/0, start_link/1, - stop/0, + stop/0, stop/1, monitor/0, demonitor/1, notify_started/1, cancel_notify_started/1, @@ -196,7 +196,12 @@ start(Opts) -> ok. stop() -> - snmpm_supervisor:stop(). + stop(0). + +stop(Timeout) when (Timeout =:= infinity) orelse + (is_integer(Timeout) andalso (Timeout >= 0)) -> + snmpm_supervisor:stop(Timeout). + monitor() -> diff --git a/lib/snmp/src/manager/snmpm_supervisor.erl b/lib/snmp/src/manager/snmpm_supervisor.erl index c36bbe1bdd..bc66025c6f 100644 --- a/lib/snmp/src/manager/snmpm_supervisor.erl +++ b/lib/snmp/src/manager/snmpm_supervisor.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2016. All Rights Reserved. +%% Copyright Ericsson AB 2004-2019. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -24,7 +24,7 @@ %% External exports --export([start_link/2, stop/0]). +-export([start_link/2, stop/0, stop/1]). %% supervisor callbacks -export([init/1]). @@ -38,26 +38,54 @@ %%%------------------------------------------------------------------- %%% API %%%------------------------------------------------------------------- + start_link(Type, Opts) -> ?d("start_link -> entry with" "~n Opts: ~p", [Opts]), SupName = {local, ?MODULE}, supervisor:start_link(SupName, ?MODULE, [Type, Opts]). + stop() -> + stop(0). + +stop(Timeout) -> ?d("stop -> entry", []), case whereis(?SERVER) of Pid when is_pid(Pid) -> - ?d("stop -> Pid: ~p", [Pid]), - exit(Pid, shutdown), - ?d("stop -> stopped", []), - ok; + stop(Pid, Timeout); _ -> ?d("stop -> not running", []), not_running end. +%% For some unfathomable reason there is no "nice" way to stop +%% a supervisor. The "normal" way to do it is: +%% 1) exit(Pid, kill) (kaboom) +%% 2) If the caller is the *parent*: exit(Pid, shutdown) +%% So, here we do it the really ugly way...but since this function is +%% intended for testing (mostly)... +stop(Pid, Timeout) when (Timeout =:= 0) -> + ?d("stop -> Pid: ~p", [Pid]), + sys:terminate(Pid, shutdown), + ?d("stop -> stopped", []), + ok; +stop(Pid, Timeout) -> + ?d("stop -> Pid: ~p", [Pid]), + MRef = erlang:monitor(process, Pid), + sys:terminate(Pid, shutdown), + receive + {'DOWN', MRef, process, Pid, _} -> + ?d("stop -> stopped", []), + ok + after Timeout -> + ?d("stop -> timeout", []), + erlang:demonitor(MRef, [flush]), + {error, timeout} + end. + + %%%------------------------------------------------------------------- %%% Callback functions from supervisor %%%------------------------------------------------------------------- diff --git a/lib/snmp/test/snmp_agent_test_lib.erl b/lib/snmp/test/snmp_agent_test_lib.erl index 615d6774b9..c0da47dc4c 100644 --- a/lib/snmp/test/snmp_agent_test_lib.erl +++ b/lib/snmp/test/snmp_agent_test_lib.erl @@ -423,7 +423,18 @@ tc_wait(From, Env, M, F, A) -> "~n ~p" "~n", [Res]), From ! {tc_runner_done, self(), Res, get(test_server_loc)}, - exit(Res). + %% The point of this is that in some cases we have seen that the + %% exit signal having been "passed on" to the CT, which consider any + %% exit a fail (even if its {'EXIT', ok}). + %% So, just to be on the safe side, convert an 'ok' to a 'normal'. + case Res of + ok -> + exit(normal); + {ok, _} -> + exit(normal); + _ -> + exit(Res) + end. tc_run(Mod, Func, Args, Opts) -> ?PRINT2("tc_run -> entry with" diff --git a/lib/snmp/test/snmp_manager_test.erl b/lib/snmp/test/snmp_manager_test.erl index 7cd3eae0c7..c31bb92e1f 100644 --- a/lib/snmp/test/snmp_manager_test.erl +++ b/lib/snmp/test/snmp_manager_test.erl @@ -62,7 +62,7 @@ register_user1/1, - register_agent1/1, + register_agent_old/1, register_agent2/1, register_agent3/1, @@ -185,7 +185,6 @@ end_per_suite(Config) when is_list(Config) -> init_per_testcase(Case, Config) when is_list(Config) -> - io:format(user, "~n~n*** INIT ~w:~w ***~n~n", [?MODULE, Case]), p(Case, "init_per_testcase begin when" "~n Nodes: ~p~n~n", [erlang:nodes()]), %% This version of the API, based on Addr and Port, has been deprecated @@ -204,13 +203,15 @@ init_per_testcase(Case, Config) when is_list(Config) -> Result = case lists:member(Case, DeprecatedApiCases) of true -> - {skip, api_no_longer_supported}; + {skip, "API no longer supported"}; false -> try init_per_testcase2(Case, Config) catch - C:{skip, _} = E:_ when ((C =:= throw) orelse (C =:= exit)) -> + C:{skip, _} = E:_ when ((C =:= throw) orelse + (C =:= exit)) -> E; - C:E:_ when ((C =:= throw) orelse (C =:= exit)) -> + C:E:_ when ((C =:= throw) orelse + (C =:= exit)) -> {skip, {catched, C, E}} end end, @@ -479,7 +480,7 @@ groups() -> }, {agent_tests, [], [ - register_agent1, + register_agent_old, register_agent2, register_agent3 ] @@ -595,7 +596,7 @@ groups() -> ipv6_tests() -> [ - register_agent1, + register_agent_old, simple_sync_get_next3, simple_async_get2, simple_sync_get3, @@ -671,11 +672,11 @@ end_per_group(_GroupName, Config) -> simple_start_and_stop1(suite) -> []; simple_start_and_stop1(Config) when is_list(Config) -> - %% ?SKIP(not_yet_implemented), - process_flag(trap_exit, true), - put(tname,ssas1), - p("starting with Config: ~n~p", [Config]), + ?TC_TRY(simple_start_and_stop1, + fun() -> do_simple_start_and_stop1(Config) end). +do_simple_start_and_stop1(Config) -> + p("starting with Config: ~n~p", [Config]), ConfDir = ?config(manager_conf_dir, Config), DbDir = ?config(manager_db_dir, Config), @@ -696,7 +697,6 @@ simple_start_and_stop1(Config) when is_list(Config) -> ?SLEEP(1000), - p("end"), ok. @@ -704,9 +704,10 @@ simple_start_and_stop1(Config) when is_list(Config) -> simple_start_and_stop2(suite) -> []; simple_start_and_stop2(Config) when is_list(Config) -> - %% ?SKIP(not_yet_implemented), - process_flag(trap_exit, true), - put(tname,ssas2), + ?TC_TRY(simple_start_and_stop2, + fun() -> do_simple_start_and_stop2(Config) end). + +do_simple_start_and_stop2(Config) -> p("starting with Config: ~p~n", [Config]), ManagerNode = start_manager_node(), @@ -744,7 +745,6 @@ simple_start_and_stop2(Config) when is_list(Config) -> ?SLEEP(1000), - p("end"), ok. @@ -752,8 +752,10 @@ simple_start_and_stop2(Config) when is_list(Config) -> simple_start_and_monitor_crash1(suite) -> []; simple_start_and_monitor_crash1(Config) when is_list(Config) -> - process_flag(trap_exit, true), - put(tname,ssamc1), + ?TC_TRY(simple_start_and_monitor_crash1, + fun() -> do_simple_start_and_monitor_crash1(Config) end). + +do_simple_start_and_monitor_crash1(Config) -> p("starting with Config: ~n~p", [Config]), ConfDir = ?config(manager_conf_dir, Config), @@ -797,7 +799,6 @@ simple_start_and_monitor_crash1(Config) when is_list(Config) -> ?FAIL(timeout) end, - p("end"), ok. @@ -805,8 +806,10 @@ simple_start_and_monitor_crash1(Config) when is_list(Config) -> simple_start_and_monitor_crash2(suite) -> []; simple_start_and_monitor_crash2(Config) when is_list(Config) -> - process_flag(trap_exit, true), - put(tname,ssamc2), + ?TC_TRY(simple_start_and_monitor_crash2, + fun() -> do_simple_start_and_monitor_crash2(Config) end). + +do_simple_start_and_monitor_crash2(Config) -> p("starting with Config: ~n~p", [Config]), ConfDir = ?config(manager_conf_dir, Config), @@ -851,7 +854,6 @@ simple_start_and_monitor_crash2(Config) when is_list(Config) -> ?FAIL(timeout) end, - p("end"), ok. @@ -897,8 +899,10 @@ simulate_crash(NumKills, _) -> notify_started01(suite) -> []; notify_started01(Config) when is_list(Config) -> - process_flag(trap_exit, true), - put(tname,ns01), + ?TC_TRY(notify_started01, + fun() -> do_notify_started01(Config) end). + +do_notify_started01(Config) -> p("starting with Config: ~n~p", [Config]), ConfDir = ?config(manager_conf_dir, Config), @@ -985,37 +989,34 @@ snmpm_starter(Opts, To) -> notify_started02(suite) -> []; notify_started02(Config) when is_list(Config) -> - process_flag(trap_exit, true), - put(tname,ns02), + ?TC_TRY(notify_started02, + fun() -> notify_started02_cond(Config) end, + fun() -> do_notify_started02(Config) end). - %% <CONDITIONAL-SKIP> - %% The point of this is to catch machines running - %% SLES9 (2.6.5) +notify_started02_cond(Config) -> LinuxVersionVerify = fun() -> case os:cmd("uname -m") of "i686" ++ _ -> -%% io:format("found an i686 machine, " -%% "now check version~n", []), case os:version() of {2, 6, Rev} when Rev >= 16 -> - true; + false; {2, Min, _} when Min > 6 -> - true; + false; {Maj, _, _} when Maj > 2 -> - true; + false; _ -> - false + true end; _ -> - true + false end end, Skippable = [{unix, [{linux, LinuxVersionVerify}]}], Condition = fun() -> ?OS_BASED_SKIP(Skippable) end, - ?NON_PC_TC_MAYBE_SKIP(Config, Condition), - %% </CONDITIONAL-SKIP> - + ?NON_PC_TC_MAYBE_SKIP(Config, Condition). + +do_notify_started02(Config) -> p("starting with Config: ~n~p", [Config]), ConfDir = ?config(manager_conf_dir, Config), @@ -1023,10 +1024,10 @@ notify_started02(Config) when is_list(Config) -> write_manager_conf(ConfDir), - Opts = [{server, [{verbosity, log}]}, - {net_if, [{verbosity, silence}]}, + Opts = [{server, [{verbosity, log}]}, + {net_if, [{verbosity, silence}]}, {note_store, [{verbosity, silence}]}, - {config, [{verbosity, log}, {dir, ConfDir}, {db_dir, DbDir}]}], + {config, [{verbosity, debug}, {dir, ConfDir}, {db_dir, DbDir}]}], p("start snmpm client process"), NumIterations = 5, @@ -1056,8 +1057,14 @@ notify_started02(Config) when is_list(Config) -> p("await snmpm client process exit (max ~p+10000 msec)", [ApproxStartTime]), receive + %% We take this opportunity to check if we got a skip from + %% the ctrl process. + {'EXIT', Pid2, {skip, SkipReason1}} -> + ?SKIP(SkipReason1); {'EXIT', Pid1, normal} -> ok; + {'EXIT', Pid1, {suite_failed, Reason1}} -> + ?FAIL({client, Reason1}); {'EXIT', Pid1, Reason1} -> ?FAIL({client, Reason1}) after ApproxStartTime + 10000 -> @@ -1070,6 +1077,9 @@ notify_started02(Config) when is_list(Config) -> receive {'EXIT', Pid2, normal} -> ok; + {'EXIT', Pid2, {skip, SkipReason2}} -> + %% In case of a race + ?SKIP(SkipReason2); {'EXIT', Pid2, Reason2} -> ?FAIL({ctrl, Reason2}) after 5000 -> @@ -1094,7 +1104,7 @@ ns02_client_await_approx_runtime(Pid) -> "~n ~p", [Pid, Reason]), {error, Reason} - after 15000 -> + after 30000 -> %% Either something is *really* wrong or this machine %% is dog slow. Either way, this is a skip-reason... {skip, approx_runtime_timeout} @@ -1159,6 +1169,12 @@ ns02_ctrl(Opts, N) -> p("starting"), ns02_ctrl_loop(Opts, N). + +%% We have seen that some times it takes unreasonably long time to +%% start the manager (it got "stuck" in snmpm_config). But since +%% we did not have enough verbosity, we do not know how far it got. +%% So, we try to monitor each start attempt. We allow 5 sec (just +%% to give slow boxes a chance). ns02_ctrl_loop(_Opts, 0) -> p("done"), exit(normal); @@ -1166,19 +1182,45 @@ ns02_ctrl_loop(Opts, N) -> p("entry when N: ~p", [N]), ?SLEEP(2000), p("start manager"), - snmpm:start(Opts), + TS1 = erlang:system_time(millisecond), + {StarterPid, StarterMRef} = + erlang:spawn_monitor(fun() -> exit(snmpm:start(Opts)) end), + receive + {'DOWN', StarterMRef, process, StarterPid, ok} -> + TS2 = erlang:system_time(millisecond), + p("manager started: ~w ms", [TS2-TS1]), + ok + after 5000 -> + p("manager (~p) start timeout - kill", [StarterPid]), + exit(StarterPid, kill), + exit({skip, start_timeout}) + end, ?SLEEP(2000), p("stop manager"), - snmpm:stop(), + ?SLEEP(100), % Give the verbosity to take effect... + TS3 = erlang:system_time(millisecond), + case snmpm:stop(5000) of + ok -> + TS4 = erlang:system_time(millisecond), + p("manager stopped: ~p ms", [TS4-TS3]), + ok; + {error, timeout} -> + p("manager stop timeout - kill (cleanup) and skip"), + exit(whereis(snmpm_supervisor), kill), + exit({skip, stop_timeout}) + end, ns02_ctrl_loop(Opts, N-1). + %%====================================================================== info(suite) -> []; info(Config) when is_list(Config) -> - process_flag(trap_exit, true), - put(tname,info), + ?TC_TRY(info, + fun() -> do_info(Config) end). + +do_info(Config) -> p("starting with Config: ~n~p", [Config]), ConfDir = ?config(manager_conf_dir, Config), @@ -1206,7 +1248,6 @@ info(Config) when is_list(Config) -> ?SLEEP(1000), - p("end"), ok. verify_info(Info) when is_list(Info) -> @@ -1246,9 +1287,10 @@ verify_info([{Key, SubKeys}|Keys], Info) -> register_user1(suite) -> []; register_user1(Config) when is_list(Config) -> - %% ?SKIP(not_yet_implemented). - process_flag(trap_exit, true), - put(tname,ru1), + ?TC_TRY(register_user1, + fun() -> do_register_user1(Config) end). + +do_register_user1(Config) -> p("starting with Config: ~p~n", [Config]), ManagerNode = start_manager_node(), @@ -1322,7 +1364,6 @@ register_user1(Config) when is_list(Config) -> ?SLEEP(1000), - p("end"), ok. verify_users([], []) -> @@ -1340,14 +1381,15 @@ verify_users(ActualUsers0, [User|RegUsers]) -> %%====================================================================== -register_agent1(doc) -> +register_agent_old(doc) -> ["Test registration of agents with the OLD interface functions"]; -register_agent1(suite) -> +register_agent_old(suite) -> []; -register_agent1(Config) when is_list(Config) -> - process_flag(trap_exit, true), - put(tname,ra1), - +register_agent_old(Config) when is_list(Config) -> + ?TC_TRY(register_agent_old, + fun() -> do_register_agent_old(Config) end). + +do_register_agent_old(Config) -> p("starting with Config: ~p~n", [Config]), ManagerNode = start_manager_node(), @@ -1462,7 +1504,6 @@ register_agent1(Config) when is_list(Config) -> ?SLEEP(1000), - p("end"), ok. @@ -1473,8 +1514,10 @@ register_agent2(doc) -> register_agent2(suite) -> []; register_agent2(Config) when is_list(Config) -> - process_flag(trap_exit, true), - put(tname, ra2), + ?TC_TRY(register_agent2, + fun() -> do_register_agent2(Config) end). + +do_register_agent2(Config) -> p("starting with Config: ~p~n", [Config]), ManagerNode = start_manager_node(), @@ -1607,7 +1650,6 @@ register_agent2(Config) when is_list(Config) -> ?SLEEP(1000), - p("end"), ok. @@ -1619,8 +1661,10 @@ register_agent3(doc) -> register_agent3(suite) -> []; register_agent3(Config) when is_list(Config) -> - process_flag(trap_exit, true), - put(tname, ra3), + ?TC_TRY(register_agent3, + fun() -> do_register_agent3(Config) end). + +do_register_agent3(Config) -> p("starting with Config: ~p~n", [Config]), ManagerNode = start_manager_node(), @@ -1757,7 +1801,6 @@ register_agent3(Config) when is_list(Config) -> ?SLEEP(1000), - p("end"), ok. @@ -1766,10 +1809,11 @@ register_agent3(Config) when is_list(Config) -> simple_sync_get1(doc) -> ["Simple sync get-request - Old style (Addr & Port)"]; simple_sync_get1(suite) -> []; simple_sync_get1(Config) when is_list(Config) -> - ?SKIP(api_no_longer_supported), + ?TC_TRY(simple_sync_get1, + fun() -> {skip, "API no longer supported"} end, + fun() -> do_simple_sync_get1(Config) end). - process_flag(trap_exit, true), - put(tname, ssg1), +do_simple_sync_get1(Config) -> p("starting with Config: ~p~n", [Config]), Node = ?config(manager_node, Config), @@ -1828,18 +1872,18 @@ simple_sync_get2(doc) -> ["Simple sync get-request - Version 2 API (TargetName)"]; simple_sync_get2(suite) -> []; simple_sync_get2(Config) when is_list(Config) -> - process_flag(trap_exit, true), - put(tname, ssg2), - do_simple_sync_get2(Config), - display_log(Config), - ok. + ?TC_TRY(simple_sync_get2, + fun() -> do_simple_sync_get2(Config) end). do_simple_sync_get2(Config) -> + p("starting with Config: ~n~p", [Config]), Get = fun(Node, TargetName, Oids) -> mgr_user_sync_get(Node, TargetName, Oids) end, PostVerify = fun() -> ok end, - do_simple_sync_get2(Config, Get, PostVerify). + do_simple_sync_get2(Config, Get, PostVerify), + display_log(Config), + ok. do_simple_sync_get2(Config, Get, PostVerify) -> p("starting with Config: ~p~n", [Config]), @@ -1895,13 +1939,11 @@ simple_sync_get3(doc) -> ["Simple sync get-request - Version 3 API (TargetName and send-opts)"]; simple_sync_get3(suite) -> []; simple_sync_get3(Config) when is_list(Config) -> - process_flag(trap_exit, true), - put(tname, ssg3), - do_simple_sync_get3(Config), - display_log(Config), - ok. + ?TC_TRY(simple_sync_get3, + fun() -> do_simple_sync_get3(Config) end). do_simple_sync_get3(Config) -> + p("starting with Config: ~n~p", [Config]), Self = self(), Msg = simple_sync_get3, Fun = fun() -> Self ! Msg end, @@ -1920,7 +1962,9 @@ do_simple_sync_get3(Config) -> ok end end, - do_simple_sync_get2(Config, Get, PostVerify). + do_simple_sync_get2(Config, Get, PostVerify), + display_log(Config), + ok. %%====================================================================== @@ -1929,10 +1973,11 @@ simple_async_get1(doc) -> ["Simple (async) get-request - Old style (Addr & Port)"]; simple_async_get1(suite) -> []; simple_async_get1(Config) when is_list(Config) -> - ?SKIP(api_no_longer_supported), + ?TC_TRY(simple_async_get1, + fun() -> {skip, "API no longer supported"} end, + fun() -> do_simple_async_get1(Config) end). - process_flag(trap_exit, true), - put(tname, sag1), +do_simple_async_get1(Config) -> p("starting with Config: ~p~n", [Config]), MgrNode = ?config(manager_node, Config), @@ -2033,8 +2078,10 @@ simple_async_get2(doc) -> ["Simple (async) get-request - Version 2 API (TargetName)"]; simple_async_get2(suite) -> []; simple_async_get2(Config) when is_list(Config) -> - process_flag(trap_exit, true), - put(tname, sag2), + ?TC_TRY(simple_async_get2, + fun() -> do_simple_async_get2(Config) end). + +do_simple_async_get2(Config) -> p("starting with Config: ~p~n", [Config]), MgrNode = ?config(manager_node, Config), AgentNode = ?config(agent_node, Config), @@ -2114,8 +2161,10 @@ simple_async_get3(doc) -> ["Simple (async) get-request - Version 3 API (TargetName and send-opts)"]; simple_async_get3(suite) -> []; simple_async_get3(Config) when is_list(Config) -> - process_flag(trap_exit, true), - put(tname, sag3), + ?TC_TRY(simple_async_get3, + fun() -> do_simple_async_get3(Config) end). + +do_simple_async_get3(Config) -> p("starting with Config: ~p~n", [Config]), MgrNode = ?config(manager_node, Config), AgentNode = ?config(agent_node, Config), @@ -2146,10 +2195,11 @@ simple_sync_get_next1(doc) -> ["Simple (sync) get_next-request - " "Old style (Addr & Port)"]; simple_sync_get_next1(suite) -> []; simple_sync_get_next1(Config) when is_list(Config) -> - ?SKIP(api_no_longer_supported), + ?TC_TRY(simple_sync_get_next1, + fun() -> {skip, "API no longer supported"} end, + fun() -> do_simple_sync_get_next1(Config) end). - process_flag(trap_exit, true), - put(tname, ssgn1), +do_simple_sync_get_next1(Config) -> p("starting with Config: ~p~n", [Config]), MgrNode = ?config(manager_node, Config), @@ -2287,8 +2337,10 @@ simple_sync_get_next2(doc) -> ["Simple (sync) get_next-request - Version 2 API (TargetName)"]; simple_sync_get_next2(suite) -> []; simple_sync_get_next2(Config) when is_list(Config) -> - process_flag(trap_exit, true), - put(tname, ssgn2), + ?TC_TRY(simple_sync_get_next2, + fun() -> do_simple_sync_get_next2(Config) end). + +do_simple_sync_get_next2(Config) -> p("starting with Config: ~p~n", [Config]), GetNext = fun(Node, TargetName, Oids) -> @@ -2440,10 +2492,11 @@ simple_async_get_next1(doc) -> ["Simple (async) get_next-request - " "Old style (Addr & Port)"]; simple_async_get_next1(suite) -> []; simple_async_get_next1(Config) when is_list(Config) -> - ?SKIP(api_no_longer_supported), + ?TC_TRY(simple_async_get_next1, + fun() -> {skip, "API no longer supported"} end, + fun() -> do_simple_async_get_next1(Config) end). - process_flag(trap_exit, true), - put(tname, ssgn1), +do_simple_async_get_next1(Config) -> p("starting with Config: ~p~n", [Config]), MgrNode = ?config(manager_node, Config), @@ -2540,8 +2593,10 @@ simple_async_get_next2(doc) -> ["Simple (async) get_next-request - Version 2 API (TargetName)"]; simple_async_get_next2(suite) -> []; simple_async_get_next2(Config) when is_list(Config) -> - process_flag(trap_exit, true), - put(tname, ssgn2), + ?TC_TRY(simple_async_get_next2, + fun() -> do_simple_async_get_next2(Config) end). + +do_simple_async_get_next2(Config) -> p("starting with Config: ~p~n", [Config]), MgrNode = ?config(manager_node, Config), @@ -2651,8 +2706,10 @@ simple_async_get_next3(doc) -> "Version 3 API (TargetName with send-opts)"]; simple_async_get_next3(suite) -> []; simple_async_get_next3(Config) when is_list(Config) -> - process_flag(trap_exit, true), - put(tname, ssgn2), + ?TC_TRY(simple_async_get_next3, + fun() -> do_simple_async_get_next3(Config) end). + +do_simple_async_get_next3(Config) -> p("starting with Config: ~p~n", [Config]), MgrNode = ?config(manager_node, Config), @@ -2694,10 +2751,11 @@ simple_sync_set1(doc) -> ["Simple (sync) set-request - " "Old style (Addr & Port)"]; simple_sync_set1(suite) -> []; simple_sync_set1(Config) when is_list(Config) -> - ?SKIP(api_no_longer_supported), + ?TC_TRY(simple_sync_set1, + fun() -> {skip, "API no longer supported"} end, + fun() -> do_simple_sync_set1(Config) end). - process_flag(trap_exit, true), - put(tname, sss1), +do_simple_sync_set1(Config) -> p("starting with Config: ~p~n", [Config]), Node = ?config(manager_node, Config), @@ -2767,8 +2825,10 @@ simple_sync_set2(doc) -> ["Simple (sync) set-request - Version 2 API (TargetName)"]; simple_sync_set2(suite) -> []; simple_sync_set2(Config) when is_list(Config) -> - process_flag(trap_exit, true), - put(tname, sss2), + ?TC_TRY(simple_sync_set2, + fun() -> do_simple_sync_set2(Config) end). + +do_simple_sync_set2(Config) -> p("starting with Config: ~p~n", [Config]), Set = fun(Node, TargetName, VAVs) -> @@ -2837,8 +2897,10 @@ simple_sync_set3(doc) -> ["Simple (sync) set-request - Version 3 API (TargetName with send-opts)"]; simple_sync_set3(suite) -> []; simple_sync_set3(Config) when is_list(Config) -> - process_flag(trap_exit, true), - put(tname, sss3), + ?TC_TRY(simple_sync_set3, + fun() -> do_simple_sync_set3(Config) end). + +do_simple_sync_set3(Config) -> p("starting with Config: ~p~n", [Config]), Self = self(), @@ -2866,10 +2928,11 @@ simple_async_set1(doc) -> ["Simple (async) set-request - " "Old style (Addr & Port)"]; simple_async_set1(suite) -> []; simple_async_set1(Config) when is_list(Config) -> - ?SKIP(api_no_longer_supported), + ?TC_TRY(simple_async_set1, + fun() -> {skip, "API no longer supported"} end, + fun() -> do_simple_async_set1(Config) end). - process_flag(trap_exit, true), - put(tname, sas1), +do_simple_async_set1(Config) -> p("starting with Config: ~p~n", [Config]), MgrNode = ?config(manager_node, Config), @@ -2961,8 +3024,10 @@ simple_async_set2(doc) -> ["Simple (async) set-request - Version 2 API (TargetName)"]; simple_async_set2(suite) -> []; simple_async_set2(Config) when is_list(Config) -> - process_flag(trap_exit, true), - put(tname, sas2), + ?TC_TRY(simple_async_set2, + fun() -> do_simple_async_set2(Config) end). + +do_simple_async_set2(Config) -> p("starting with Config: ~p~n", [Config]), MgrNode = ?config(manager_node, Config), @@ -3034,8 +3099,10 @@ simple_async_set3(doc) -> ["Simple (async) set-request - Version 3 API (TargetName with send-opts)"]; simple_async_set3(suite) -> []; simple_async_set3(Config) when is_list(Config) -> - process_flag(trap_exit, true), - put(tname, sas3), + ?TC_TRY(simple_async_set3, + fun() -> do_simple_async_set3(Config) end). + +do_simple_async_set3(Config) -> p("starting with Config: ~p~n", [Config]), MgrNode = ?config(manager_node, Config), @@ -3078,10 +3145,11 @@ simple_sync_get_bulk1(doc) -> ["Simple (sync) get_bulk-request - " "Old style (Addr & Port)"]; simple_sync_get_bulk1(suite) -> []; simple_sync_get_bulk1(Config) when is_list(Config) -> - ?SKIP(api_no_longer_supported), + ?TC_TRY(simple_sync_get_bulk1, + fun() -> {skip, "API no longer supported"} end, + fun() -> do_simple_sync_get_bulk1(Config) end). - process_flag(trap_exit, true), - put(tname, ssgb1), +do_simple_sync_get_bulk1(Config) -> p("starting with Config: ~p~n", [Config]), MgrNode = ?config(manager_node, Config), @@ -3252,8 +3320,10 @@ simple_sync_get_bulk2(doc) -> ["Simple (sync) get_bulk-request - Version 2 API (TargetName)"]; simple_sync_get_bulk2(suite) -> []; simple_sync_get_bulk2(Config) when is_list(Config) -> - process_flag(trap_exit, true), - put(tname, ssgb2), + ?TC_TRY(simple_sync_get_bulk2, + fun() -> do_simple_sync_get_bulk2(Config) end). + +do_simple_sync_get_bulk2(Config) -> p("starting with Config: ~p~n", [Config]), MgrNode = ?config(manager_node, Config), @@ -3408,8 +3478,10 @@ simple_sync_get_bulk3(doc) -> "Version 3 API (TargetName with send-opts)"]; simple_sync_get_bulk3(suite) -> []; simple_sync_get_bulk3(Config) when is_list(Config) -> - process_flag(trap_exit, true), - put(tname, ssgb3), + ?TC_TRY(simple_sync_get_bulk3, + fun() -> do_simple_sync_get_bulk3(Config) end). + +do_simple_sync_get_bulk3(Config) -> p("starting with Config: ~p~n", [Config]), MgrNode = ?config(manager_node, Config), @@ -3445,10 +3517,11 @@ simple_async_get_bulk1(doc) -> ["Simple (async) get_bulk-request - " "Old style (Addr & Port)"]; simple_async_get_bulk1(suite) -> []; simple_async_get_bulk1(Config) when is_list(Config) -> - ?SKIP(api_no_longer_supported), + ?TC_TRY(simple_async_get_bulk1, + fun() -> {skip, "API no longer supported"} end, + fun() -> do_simple_async_get_bulk1(Config) end). - process_flag(trap_exit, true), - put(tname, sagb1), +do_simple_async_get_bulk1(Config) -> p("starting with Config: ~p~n", [Config]), MgrNode = ?config(manager_node, Config), @@ -3591,8 +3664,10 @@ simple_async_get_bulk2(doc) -> ["Simple (async) get_bulk-request - Version 2 API (TargetName)"]; simple_async_get_bulk2(suite) -> []; simple_async_get_bulk2(Config) when is_list(Config) -> - process_flag(trap_exit, true), - put(tname, sagb2), + ?TC_TRY(simple_async_get_bulk2, + fun() -> do_simple_async_get_bulk2(Config) end). + +do_simple_async_get_bulk2(Config) -> p("starting with Config: ~p~n", [Config]), MgrNode = ?config(manager_node, Config), @@ -3747,8 +3822,10 @@ simple_async_get_bulk3(doc) -> "Version 3 API (TargetName with send-opts)"]; simple_async_get_bulk3(suite) -> []; simple_async_get_bulk3(Config) when is_list(Config) -> - process_flag(trap_exit, true), - put(tname, sagb3), + ?TC_TRY(simple_async_get_bulk3, + fun() -> do_simple_async_get_bulk3(Config) end). + +do_simple_async_get_bulk3(Config) -> p("starting with Config: ~p~n", [Config]), MgrNode = ?config(manager_node, Config), @@ -3791,10 +3868,11 @@ misc_async1(doc) -> ["Misc (async) request(s) - " "Old style (Addr & Port)"]; misc_async1(suite) -> []; misc_async1(Config) when is_list(Config) -> - ?SKIP(api_no_longer_supported), + ?TC_TRY(misc_async1, + fun() -> {skip, "API no longer supported"} end, + fun() -> do_misc_async1(Config) end). - process_flag(trap_exit, true), - put(tname, ms1), +do_misc_async1(Config) -> p("starting with Config: ~p~n", [Config]), MgrNode = ?config(manager_node, Config), @@ -3983,8 +4061,10 @@ misc_async2(doc) -> ["Misc (async) request(s) - Version 2 API (TargetName)"]; misc_async2(suite) -> []; misc_async2(Config) when is_list(Config) -> - process_flag(trap_exit, true), - put(tname, ms2), + ?TC_TRY(misc_async2, + fun() -> do_misc_async2(Config) end). + +do_misc_async2(Config) -> p("starting with Config: ~p~n", [Config]), MgrNode = ?config(manager_node, Config), @@ -4233,8 +4313,10 @@ verify_trap(Trap, [{Id, Verifier}|Verifiers]) -> trap1(suite) -> []; trap1(Config) when is_list(Config) -> - process_flag(trap_exit, true), - put(tname,t1), + ?TC_TRY(trap1, + fun() -> do_trap1(Config) end). + +do_trap1(Config) -> p("starting with Config: ~p~n", [Config]), MgrNode = ?config(manager_node, Config), @@ -4386,8 +4468,10 @@ trap1(Config) when is_list(Config) -> trap2(suite) -> []; trap2(Config) when is_list(Config) -> - process_flag(trap_exit, true), - put(tname,t2), + ?TC_TRY(trap2, + fun() -> do_trap2(Config) end). + +do_trap2(Config) -> p("starting with Config: ~p~n", [Config]), MgrNode = ?config(manager_node, Config), @@ -4579,8 +4663,10 @@ trap2(Config) when is_list(Config) -> inform1(suite) -> []; inform1(Config) when is_list(Config) -> - process_flag(trap_exit, true), - put(tname,i1), + ?TC_TRY(inform1, + fun() -> do_inform1(Config) end). + +do_inform1(Config) -> p("starting with Config: ~p~n", [Config]), MgrNode = ?config(manager_node, Config), @@ -4706,8 +4792,10 @@ inform1(Config) when is_list(Config) -> inform2(suite) -> []; inform2(Config) when is_list(Config) -> - process_flag(trap_exit, true), - put(tname, i2), + ?TC_TRY(inform2, + fun() -> do_inform2(Config) end). + +do_inform2(Config) -> p("starting with Config: ~p~n", [Config]), MgrNode = ?config(manager_node, Config), @@ -4878,8 +4966,10 @@ inform2(Config) when is_list(Config) -> inform3(suite) -> []; inform3(Config) when is_list(Config) -> - process_flag(trap_exit, true), - put(tname,i3), + ?TC_TRY(inform3, + fun() -> do_inform3(Config) end). + +do_inform3(Config) -> p("starting with Config: ~p~n", [Config]), MgrNode = ?config(manager_node, Config), @@ -5014,8 +5104,10 @@ inform3(Config) when is_list(Config) -> inform4(suite) -> []; inform4(Config) when is_list(Config) -> - process_flag(trap_exit, true), - put(tname,i4), + ?TC_TRY(inform4, + fun() -> do_inform4(Config) end). + +do_inform4(Config) -> p("starting with Config: ~p~n", [Config]), MgrNode = ?config(manager_node, Config), @@ -5134,8 +5226,10 @@ inform4(Config) when is_list(Config) -> inform_swarm(suite) -> []; inform_swarm(Config) when is_list(Config) -> - process_flag(trap_exit, true), - put(tname, is), + ?TC_TRY(inform_swarm, + fun() -> do_inform_swarm(Config) end). + +do_inform_swarm(Config) -> p("starting with Config: ~p~n", [Config]), MgrNode = ?config(manager_node, Config), @@ -5306,8 +5400,10 @@ report(Config) when is_list(Config) -> otp8015_1(doc) -> ["OTP-8015:1 - testing the new api-function."]; otp8015_1(suite) -> []; otp8015_1(Config) when is_list(Config) -> - process_flag(trap_exit, true), - put(tname, otp8015_1), + ?TC_TRY(otp8015_1, + fun() -> do_otp8015_1(Config) end). + +do_otp8015_1(Config) -> p("starting with Config: ~p~n", [Config]), ConfDir = ?config(manager_conf_dir, Config), @@ -5354,8 +5450,10 @@ otp8015_1(Config) when is_list(Config) -> otp8395_1(doc) -> ["OTP-8395:1 - simple get with ATL sequence numbering."]; otp8395_1(suite) -> []; otp8395_1(Config) when is_list(Config) -> - process_flag(trap_exit, true), - put(tname, otp8395_1), + ?TC_TRY(otp8395_1, + fun() -> do_otp8395_1(Config) end). + +do_otp8395_1(Config) -> do_simple_sync_get2(Config). diff --git a/lib/snmp/test/snmp_test_lib.erl b/lib/snmp/test/snmp_test_lib.erl index 35bc535a80..26b68501e2 100644 --- a/lib/snmp/test/snmp_test_lib.erl +++ b/lib/snmp/test/snmp_test_lib.erl @@ -23,6 +23,7 @@ -include_lib("kernel/include/file.hrl"). +-export([tc_try/2, tc_try/3]). -export([hostname/0, hostname/1, localhost/0, localhost/1, os_type/0, sz/1, display_suite_info/1]). -export([non_pc_tc_maybe_skip/4, os_based_skip/1, @@ -43,10 +44,107 @@ -export([watchdog/3, watchdog_start/1, watchdog_start/2, watchdog_stop/1]). -export([del_dir/1]). -export([cover/1]). --export([p/2, print1/2, print2/2, print/5, formated_timestamp/0]). +-export([f/2, p/2, print1/2, print2/2, print/5, formated_timestamp/0]). %% ---------------------------------------------------------------------- +%% Run test-case +%% + +%% *** tc_try/2,3 *** +%% Case: Basically the test case name +%% TCCondFun: A fun that is evaluated before the actual test case +%% The point of this is that it can performs checks to +%% see if we shall run the test case at all. +%% For instance, the test case may only work in specific +%% conditions. +%% FCFun: The test case fun +tc_try(Case, TCFun) -> + tc_try(Case, fun() -> ok end, TCFun). + +tc_try(Case, TCCondFun, TCFun) + when is_atom(Case) andalso + is_function(TCCondFun, 0) andalso + is_function(TCFun, 0) -> + tc_begin(Case), + try TCCondFun() of + ok -> + try + begin + TCFun(), + sleep(seconds(1)), + tc_end("ok") + end + catch + C:{skip, _} = SKIP when ((C =:= throw) orelse (C =:= exit)) -> + tc_end( f("skipping(catched,~w,tc)", [C]) ), + SKIP; + C:E:S -> + tc_end( f("failed(catched,~w,tc)", [C]) ), + erlang:raise(C, E, S) + end; + {skip, _} = SKIP -> + tc_end("skipping(tc)"), + SKIP; + {error, Reason} -> + tc_end("failed(tc)"), + exit({tc_cond_failed, Reason}) + catch + C:{skip, _} = SKIP when ((C =:= throw) orelse (C =:= exit)) -> + tc_end( f("skipping(catched,~w,cond)", [C]) ), + SKIP; + C:E:S -> + tc_end( f("failed(catched,~w,cond)", [C]) ), + erlang:raise(C, E, S) + end. + + +tc_set_name(N) when is_atom(N) -> + tc_set_name(atom_to_list(N)); +tc_set_name(N) when is_list(N) -> + put(tc_name, N). + +tc_get_name() -> + get(tc_name). + +tc_begin(TC) -> + OldVal = process_flag(trap_exit, true), + put(old_trap_exit, OldVal), + tc_set_name(TC), + tc_print("begin ***", + "~n----------------------------------------------------~n", ""). + +tc_end(Result) when is_list(Result) -> + OldVal = erase(old_trap_exit), + process_flag(trap_exit, OldVal), + tc_print("done: ~s", [Result], + "", "----------------------------------------------------~n~n"), + ok. + +tc_print(F, Before, After) -> + tc_print(F, [], Before, After). + +tc_print(F, A, Before, After) -> + Name = tc_which_name(), + FStr = f("*** [~s][~s][~p] " ++ F ++ "~n", + [formated_timestamp(),Name,self()|A]), + io:format(user, Before ++ FStr ++ After, []). + +tc_which_name() -> + case tc_get_name() of + undefined -> + case get(sname) of + undefined -> + ""; + SName when is_list(SName) -> + SName + end; + Name when is_list(Name) -> + Name + end. + + +%% ---------------------------------------------------------------------- %% Misc functions %% @@ -202,11 +300,14 @@ non_pc_tc_maybe_skip(Config, Condition, File, Line) %% test-server... ok; _ -> - case Condition() of + try Condition() of true -> skip(non_pc_testcase, File, Line); false -> ok + catch + C:E:S -> + skip({condition, C, E, S}, File, Line) end end end. @@ -712,6 +813,9 @@ cover([Suite, Case] = Args) when is_atom(Suite) andalso is_atom(Case) -> %% (debug) Print functions %% +f(F, A) -> + lists:flatten(io_lib:format(F, A)). + p(Mod, Case) when is_atom(Mod) andalso is_atom(Case) -> case get(test_case) of undefined -> diff --git a/lib/snmp/test/snmp_test_lib.hrl b/lib/snmp/test/snmp_test_lib.hrl index 99b86a928c..f077f15d3e 100644 --- a/lib/snmp/test/snmp_test_lib.hrl +++ b/lib/snmp/test/snmp_test_lib.hrl @@ -18,15 +18,11 @@ %% The Initial Developer of the Original Code is Ericsson AB. %% %CopyrightEnd% %% + %%---------------------------------------------------------------------- -%% Purpose: Define common macros for testing +%% Purpose: Define common macros for (the snmp) testing %%---------------------------------------------------------------------- -%% - (some of the) Macros stolen from the test server - - -%% -define(line,put(test_server_loc,{?MODULE,?LINE}),). - - %% - Misc macros - -ifndef(APPLICATION). @@ -45,6 +41,8 @@ %% - Test case macros - +-define(TC_TRY(C, TC), snmp_test_lib:tc_try(C, TC)). +-define(TC_TRY(C, TCCond, TC), snmp_test_lib:tc_try(C, TCCond, TC)). -define(OS_BASED_SKIP(Skippable), snmp_test_lib:os_based_skip(Skippable)). -define(NON_PC_TC_MAYBE_SKIP(Config, Condition), diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl index 8f32966a12..9df4f1e2d7 100644 --- a/lib/ssh/src/ssh_connection_handler.erl +++ b/lib/ssh/src/ssh_connection_handler.erl @@ -386,16 +386,24 @@ init_connection_handler(Role, Socket, Opts) -> D); {stop, Error} -> - Sups = ?GET_INTERNAL_OPT(supervisors, Opts), - C = #connection{system_supervisor = proplists:get_value(system_sup, Sups), - sub_system_supervisor = proplists:get_value(subsystem_sup, Sups), - connection_supervisor = proplists:get_value(connection_sup, Sups) - }, + D = try + %% Only servers have supervisorts defined in Opts + Sups = ?GET_INTERNAL_OPT(supervisors, Opts), + #connection{system_supervisor = proplists:get_value(system_sup, Sups), + sub_system_supervisor = proplists:get_value(subsystem_sup, Sups), + connection_supervisor = proplists:get_value(connection_sup, Sups) + } + of + C -> + #data{connection_state=C} + catch + _:_ -> + #data{connection_state=#connection{}} + end, gen_statem:enter_loop(?MODULE, [], {init_error,Error}, - #data{connection_state=C, - socket=Socket}) + D#data{socket=Socket}) end. @@ -1550,7 +1558,7 @@ terminate({shutdown,"Connection closed"}, _StateName, D) -> terminate({shutdown,{init,Reason}}, StateName, D) -> %% Error in initiation. "This error should not occur". - log(error, D, io_lib:format("Shutdown in init (StateName=~p): ~p~n",[StateName,Reason])), + log(error, D, "Shutdown in init (StateName=~p): ~p~n", [StateName,Reason]), stop_subsystem(D), close_transport(D); @@ -1952,12 +1960,12 @@ send_disconnect(Code, Reason, DetailedText, Module, Line, StateName, D0) -> call_disconnectfun_and_log_cond(LogMsg, DetailedText, Module, Line, StateName, D) -> case disconnect_fun(LogMsg, D) of void -> - log(info, D, - io_lib:format("~s~n" - "State = ~p~n" - "Module = ~p, Line = ~p.~n" - "Details:~n ~s~n", - [LogMsg, StateName, Module, Line, DetailedText])); + log(info, D, + "~s~n" + "State = ~p~n" + "Module = ~p, Line = ~p.~n" + "Details:~n ~s~n", + [LogMsg, StateName, Module, Line, DetailedText]); _ -> ok end. @@ -2021,6 +2029,9 @@ fold_keys(Keys, Fun, Extra) -> end, [], Keys). %%%---------------------------------------------------------------- +log(Tag, D, Format, Args) -> + log(Tag, D, io_lib:format(Format,Args)). + log(Tag, D, Reason) -> case atom_to_list(Tag) of % Dialyzer-technical reasons... "error" -> do_log(error_msg, Reason, D); @@ -2028,36 +2039,50 @@ log(Tag, D, Reason) -> "info" -> do_log(info_msg, Reason, D) end. -do_log(F, Reason, #data{ssh_params = #ssh{role = Role} = S - }) -> - VSN = - case application:get_key(ssh,vsn) of - {ok,Vsn} -> Vsn; - undefined -> "" - end, - PeerVersion = - case Role of - server -> S#ssh.c_version; - client -> S#ssh.s_version - end, - CryptoInfo = - try - [{_,_,CI}] = crypto:info_lib(), - <<"(",CI/binary,")">> - catch - _:_ -> "" - end, - Other = - case Role of - server -> "Client"; - client -> "Server" - end, - error_logger:F("Erlang SSH ~p ~s ~s.~n" - "~s: ~p~n" - "~s~n", - [Role, VSN, CryptoInfo, - Other, PeerVersion, - Reason]). + +do_log(F, Reason, #data{ssh_params = S}) -> + case S of + #ssh{role = Role} when Role==server ; + Role==client -> + {PeerRole,PeerVersion} = + case Role of + server -> {"Client", S#ssh.c_version}; + client -> {"Server", S#ssh.s_version} + end, + error_logger:F("Erlang SSH ~p ~s ~s.~n" + "~s: ~p~n" + "~s~n", + [Role, + ssh_log_version(), crypto_log_info(), + PeerRole, PeerVersion, + Reason]); + _ -> + error_logger:F("Erlang SSH ~s ~s.~n" + "~s~n", + [ssh_log_version(), crypto_log_info(), + Reason]) + end. + +crypto_log_info() -> + try + [{_,_,CI}] = crypto:info_lib(), + case crypto:info_fips() of + enabled -> + <<"(",CI/binary,". FIPS enabled)">>; + not_enabled -> + <<"(",CI/binary,". FIPS available but not enabled)">>; + _ -> + <<"(",CI/binary,")">> + end + catch + _:_ -> "" + end. + +ssh_log_version() -> + case application:get_key(ssh,vsn) of + {ok,Vsn} -> Vsn; + undefined -> "" + end. %%%---------------------------------------------------------------- not_connected_filter({connection_reply, _Data}) -> true; diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl index ce639e8fde..7ff9aed8ea 100644 --- a/lib/ssl/src/ssl.erl +++ b/lib/ssl/src/ssl.erl @@ -982,7 +982,8 @@ cipher_suites(all) -> %% Description: Returns all default and all supported cipher suites for a %% TLS/DTLS version %%-------------------------------------------------------------------- -cipher_suites(Base, Version) when Version == 'tlsv1.2'; +cipher_suites(Base, Version) when Version == 'tlsv1.3'; + Version == 'tlsv1.2'; Version == 'tlsv1.1'; Version == tlsv1; Version == sslv3 -> diff --git a/lib/ssl/test/openssl_alpn_SUITE.erl b/lib/ssl/test/openssl_alpn_SUITE.erl index fa095b4bdb..5008dba922 100644 --- a/lib/ssl/test/openssl_alpn_SUITE.erl +++ b/lib/ssl/test/openssl_alpn_SUITE.erl @@ -36,7 +36,7 @@ all() -> %% Note: ALPN not supported in sslv3 - case ssl_test_lib:openssl_sane_dtls() of + case ssl_test_lib:openssl_sane_dtls_alpn() of true -> [ {group, 'tlsv1.3'}, @@ -52,15 +52,15 @@ all() -> end. groups() -> - case ssl_test_lib:openssl_sane_dtls() of + case ssl_test_lib:openssl_sane_dtls_alpn() of true -> [ {'tlsv1.3', [], alpn_tests()}, {'tlsv1.2', [], alpn_tests() ++ alpn_npn_coexist() ++ rengotiation_tests()}, {'tlsv1.1', [], alpn_tests() ++ alpn_npn_coexist() ++ rengotiation_tests()}, {'tlsv1', [], alpn_tests() ++ alpn_npn_coexist() ++ rengotiation_tests()}, - {'dtlsv1.2', [], alpn_tests() ++ alpn_npn_coexist()}, - {'dtlsv1', [], alpn_tests() ++ alpn_npn_coexist()} + {'dtlsv1.2', [], alpn_tests()}, + {'dtlsv1', [], alpn_tests()} ]; false -> [ @@ -85,9 +85,13 @@ alpn_npn_coexist() -> erlang_server_alpn_npn_openssl_client_alpn_npn ]. rengotiation_tests() -> - [erlang_client_alpn_openssl_server_alpn_renegotiate, - erlang_server_alpn_openssl_client_alpn_renegotiate]. - + case ssl_test_lib:sane_openssl_alpn_npn_renegotiate() of + true -> + [erlang_client_alpn_openssl_server_alpn_renegotiate, + erlang_server_alpn_openssl_client_alpn_renegotiate]; + false -> + [] + end. init_per_suite(Config0) -> case os:find_executable("openssl") of false -> diff --git a/lib/ssl/test/openssl_client_cert_SUITE.erl b/lib/ssl/test/openssl_client_cert_SUITE.erl index 08c1534eb0..b327988744 100644 --- a/lib/ssl/test/openssl_client_cert_SUITE.erl +++ b/lib/ssl/test/openssl_client_cert_SUITE.erl @@ -37,7 +37,7 @@ all() -> groups() -> [ {openssl_client, [], protocol_groups()}, - %%{'tlsv1.3', [], tls_1_3_protocol_groups()}, + {'tlsv1.3', [], tls_1_3_protocol_groups()}, {'tlsv1.2', [], pre_tls_1_3_protocol_groups()}, {'tlsv1.1', [], pre_tls_1_3_protocol_groups()}, {'tlsv1', [], pre_tls_1_3_protocol_groups()}, @@ -46,13 +46,14 @@ groups() -> {'dtlsv1', [], pre_tls_1_3_protocol_groups()}, {rsa, [], all_version_tests()}, {ecdsa, [], all_version_tests()}, - {dsa, [], all_version_tests()} - %%{rsa_1_3, [], all_version_tests() ++ tls_1_3_tests() ++ [unsupported_sign_algo_cert_client_auth]}, - %%{ecdsa_1_3, [], all_version_tests() ++ tls_1_3_tests()} + {dsa, [], all_version_tests()}, + {rsa_1_3, [], all_version_tests() ++ tls_1_3_tests() ++ [unsupported_sign_algo_client_auth, + unsupported_sign_algo_cert_client_auth]}, + {ecdsa_1_3, [], all_version_tests() ++ tls_1_3_tests()} ]. protocol_groups() -> - [%%{group, 'tlsv1.3'}, + [{group, 'tlsv1.3'}, {group, 'tlsv1.2'}, {group, 'tlsv1.1'}, {group, 'tlsv1'}, @@ -225,7 +226,21 @@ end_per_group(GroupName, Config) -> false -> Config end. - +init_per_testcase(TestCase, Config) when + TestCase == client_auth_empty_cert_accepted; + TestCase == client_auth_empty_cert_rejected -> + Version = proplists:get_value(version,Config), + case Version of + sslv3 -> + %% Openssl client sends "No Certificate Reserved" warning ALERT + %% instead of sending EMPTY cert message in SSL-3.0 so empty cert test are not + %% relevant + {skip, openssl_behaves_differently}; + _ -> + ssl_test_lib:ct_log_supported_protocol_versions(Config), + ct:timetrap({seconds, 10}), + Config + end; init_per_testcase(_TestCase, Config) -> ssl_test_lib:ct_log_supported_protocol_versions(Config), ct:timetrap({seconds, 10}), @@ -314,6 +329,10 @@ unsupported_sign_algo_cert_client_auth() -> ssl_cert_tests:unsupported_sign_algo_cert_client_auth(). unsupported_sign_algo_cert_client_auth(Config) -> ssl_cert_tests:unsupported_sign_algo_cert_client_auth(Config). +unsupported_sign_algo_client_auth() -> + ssl_cert_tests:unsupported_sign_algo_client_auth(). +unsupported_sign_algo_client_auth(Config) -> + ssl_cert_tests:unsupported_sign_algo_client_auth(Config). %%-------------------------------------------------------------------- hello_retry_client_auth() -> ssl_cert_tests:hello_retry_client_auth(). diff --git a/lib/ssl/test/openssl_npn_SUITE.erl b/lib/ssl/test/openssl_npn_SUITE.erl index 9bd11f05d6..0294f4997f 100644 --- a/lib/ssl/test/openssl_npn_SUITE.erl +++ b/lib/ssl/test/openssl_npn_SUITE.erl @@ -33,51 +33,36 @@ %%-------------------------------------------------------------------- %% Common Test interface functions ----------------------------------- %%-------------------------------------------------------------------- - all() -> - %% Note: NPN not supported in sslv3 - case ssl_test_lib:openssl_sane_dtls() of - true -> - [{group, 'tlsv1.2'}, - {group, 'tlsv1.1'}, - {group, 'tlsv1'}, - {group, 'dtlsv1.2'}, - {group, 'dtlsv1'}]; - false -> - [{group, 'tlsv1.2'}, - {group, 'tlsv1.1'}, - {group, 'tlsv1'}] - end. + %% NPN is not supported in TLS-1.3 (replaced by ALPN and deprecated in TLS 1.2) + %% OpenSSL DTLS support for NPN is either not there or broken. + [{group, 'tlsv1.2'}, + {group, 'tlsv1.1'}, + {group, 'tlsv1'}]. groups() -> - case ssl_test_lib:openssl_sane_dtls() of - true -> - [{'tlsv1.2', [], npn_tests()}, - {'tlsv1.1', [], npn_tests()}, - {'tlsv1', [], npn_tests()}, - {'dtlsv1.2', [], npn_tests() -- [erlang_server_openssl_client_npn_renegotiate, - erlang_client_openssl_server_npn_renegotiate]}, - {'dtlsv1', [], npn_tests() -- [erlang_server_openssl_client_npn_renegotiate, - erlang_client_openssl_server_npn_renegotiate] - } - ]; - false -> - [{'tlsv1.2', [], npn_tests()}, - {'tlsv1.1', [], npn_tests()}, - {'tlsv1', [], npn_tests()} - ] - end. + [{'tlsv1.2', [], npn_tests() ++ npn_renegotiate_tests()}, + {'tlsv1.1', [], npn_tests() ++ npn_renegotiate_tests()}, + {'tlsv1', [], npn_tests() ++ npn_renegotiate_tests()} + ]. npn_tests() -> [erlang_client_openssl_server_npn, erlang_server_openssl_client_npn, - erlang_server_openssl_client_npn_renegotiate, - erlang_client_openssl_server_npn_renegotiate, erlang_server_openssl_client_npn_only_client, erlang_server_openssl_client_npn_only_server, erlang_client_openssl_server_npn_only_client, erlang_client_openssl_server_npn_only_server]. +npn_renegotiate_tests() -> + case ssl_test_lib:sane_openssl_alpn_npn_renegotiate() of + true -> + [erlang_server_openssl_client_npn_renegotiate, + erlang_client_openssl_server_npn_renegotiate]; + false -> + [] + end. + init_per_suite(Config0) -> case os:find_executable("openssl") of false -> diff --git a/lib/ssl/test/openssl_server_cert_SUITE.erl b/lib/ssl/test/openssl_server_cert_SUITE.erl index abac2647a9..c2af864a92 100644 --- a/lib/ssl/test/openssl_server_cert_SUITE.erl +++ b/lib/ssl/test/openssl_server_cert_SUITE.erl @@ -36,7 +36,7 @@ all() -> groups() -> [ {openssl_server, [], protocol_groups()}, - %%{'tlsv1.3', [], tls_1_3_protocol_groups()}, + {'tlsv1.3', [], tls_1_3_protocol_groups()}, {'tlsv1.2', [], pre_tls_1_3_protocol_groups()}, {'tlsv1.1', [], pre_tls_1_3_protocol_groups()}, {'tlsv1', [], pre_tls_1_3_protocol_groups()}, @@ -45,13 +45,16 @@ groups() -> {'dtlsv1', [], pre_tls_1_3_protocol_groups()}, {rsa, [], all_version_tests()}, {ecdsa, [], all_version_tests()}, - {dsa, [], all_version_tests()} - %%{rsa_1_3, [], all_version_tests() ++ tls_1_3_tests() ++ [unsupported_sign_algo_cert_client_auth]}, - %%{ecdsa_1_3, [], all_version_tests() ++ tls_1_3_tests()} + {dsa, [], all_version_tests()}, + {rsa_1_3, [], all_version_tests() ++ tls_1_3_tests()}, + %% TODO: Create proper conf of openssl server + %%++ [unsupported_sign_algo_client_auth, + %% unsupported_sign_algo_cert_client_auth]}, + {ecdsa_1_3, [], all_version_tests() ++ tls_1_3_tests()} ]. protocol_groups() -> - [%%{group, 'tlsv1.3'}, + [{group, 'tlsv1.3'}, {group, 'tlsv1.2'}, {group, 'tlsv1.1'}, {group, 'tlsv1'}, @@ -108,8 +111,7 @@ end_per_suite(_Config) -> init_per_group(openssl_server, Config0) -> Config = proplists:delete(server_type, proplists:delete(client_type, Config0)), [{client_type, erlang}, {server_type, openssl} | Config]; -init_per_group(Group, Config0) when Group == rsa; - Group == rsa_1_3 -> +init_per_group(rsa = Group, Config0) -> Config = ssl_test_lib:make_rsa_cert(Config0), COpts = proplists:get_value(client_rsa_opts, Config), SOpts = proplists:get_value(server_rsa_opts, Config), @@ -133,8 +135,25 @@ init_per_group(Group, Config0) when Group == rsa; [] -> {skip, {no_sup, Group, Version}} end; -init_per_group(Group, Config0) when Group == ecdsa; - Group == ecdsa_1_3 -> +init_per_group(rsa_1_3 = Group, Config0) -> + Config = ssl_test_lib:make_rsa_cert(Config0), + COpts = proplists:get_value(client_rsa_opts, Config), + SOpts = proplists:get_value(server_rsa_opts, Config), + %% Make sure _rsa* suite is choosen by ssl_test_lib:start_server + Version = proplists:get_value(version,Config), + Ciphers = ssl_cert_tests:test_ciphers(undefined, Version), + case Ciphers of + [_|_] -> + [{cert_key_alg, rsa} | + lists:delete(cert_key_alg, + [{client_cert_opts, [{ciphers, Ciphers} | COpts]}, + {server_cert_opts, SOpts} | + lists:delete(server_cert_opts, + lists:delete(client_cert_opts, Config))])]; + [] -> + {skip, {no_sup, Group, Version}} + end; +init_per_group(ecdsa = Group, Config0) -> PKAlg = crypto:supports(public_keys), case lists:member(ecdsa, PKAlg) andalso (lists:member(ecdh, PKAlg) orelse lists:member(dh, PKAlg)) of @@ -166,6 +185,32 @@ init_per_group(Group, Config0) when Group == ecdsa; false -> {skip, "Missing EC crypto support"} end; +init_per_group(ecdsa_1_3 = Group, Config0) -> + PKAlg = crypto:supports(public_keys), + case lists:member(ecdsa, PKAlg) andalso (lists:member(ecdh, PKAlg) orelse + lists:member(dh, PKAlg)) of + true -> + Config = ssl_test_lib:make_ecdsa_cert(Config0), + COpts = proplists:get_value(client_ecdsa_opts, Config), + SOpts = proplists:get_value(server_ecdsa_opts, Config), + %% Make sure ecdh* suite is choosen by ssl_test_lib:start_server + Version = proplists:get_value(version,Config), + Ciphers = ssl_cert_tests:test_ciphers(undefined, Version), + case Ciphers of + [_|_] -> + [{cert_key_alg, ecdsa} | + lists:delete(cert_key_alg, + [{client_cert_opts, [{ciphers, Ciphers} | COpts]}, + {server_cert_opts, SOpts} | + lists:delete(server_cert_opts, + lists:delete(client_cert_opts, Config))] + )]; + [] -> + {skip, {no_sup, Group, Version}} + end; + false -> + {skip, "Missing EC crypto support"} + end; init_per_group(Group, Config0) when Group == dsa -> PKAlg = crypto:supports(public_keys), case lists:member(dss, PKAlg) andalso lists:member(dh, PKAlg) of @@ -300,18 +345,22 @@ hello_retry_request(Config) -> ssl_cert_tests:hello_retry_request(Config). %%-------------------------------------------------------------------- custom_groups() -> - ssl_cert_tests:custom_groups(). + ssl_cert_tests:custom_groups(). custom_groups(Config) -> - ssl_cert_tests:custom_groups(Config). + ssl_cert_tests:custom_groups(Config). unsupported_sign_algo_cert_client_auth() -> - ssl_cert_tests:unsupported_sign_algo_cert_client_auth(). + ssl_cert_tests:unsupported_sign_algo_cert_client_auth(). unsupported_sign_algo_cert_client_auth(Config) -> ssl_cert_tests:unsupported_sign_algo_cert_client_auth(Config). +unsupported_sign_algo_client_auth() -> + ssl_cert_tests:unsupported_sign_algo_client_auth(). +unsupported_sign_algo_client_auth(Config) -> + ssl_cert_tests:unsupported_sign_algo_client_auth(Config). %%-------------------------------------------------------------------- hello_retry_client_auth() -> - ssl_cert_tests:hello_retry_client_auth(). + ssl_cert_tests:hello_retry_client_auth(). hello_retry_client_auth(Config) -> - ssl_cert_tests:hello_retry_client_auth(Config). + ssl_cert_tests:hello_retry_client_auth(Config). %%-------------------------------------------------------------------- hello_retry_client_auth_empty_cert_accepted() -> ssl_cert_tests:hello_retry_client_auth_empty_cert_accepted(). @@ -321,4 +370,4 @@ hello_retry_client_auth_empty_cert_accepted(Config) -> hello_retry_client_auth_empty_cert_rejected() -> ssl_cert_tests:hello_retry_client_auth_empty_cert_rejected(). hello_retry_client_auth_empty_cert_rejected(Config) -> - ssl_cert_tests:hello_retry_client_auth_empty_cert_rejected(Config). + ssl_cert_tests:hello_retry_client_auth_empty_cert_rejected(Config). diff --git a/lib/ssl/test/ssl_cert_SUITE.erl b/lib/ssl/test/ssl_cert_SUITE.erl index 571e7428ea..fb1695f38a 100644 --- a/lib/ssl/test/ssl_cert_SUITE.erl +++ b/lib/ssl/test/ssl_cert_SUITE.erl @@ -53,7 +53,8 @@ groups() -> {rsa, [], all_version_tests()}, {ecdsa, [], all_version_tests()}, {dsa, [], all_version_tests()}, - {rsa_1_3, [], all_version_tests() ++ tls_1_3_tests() ++ [unsupported_sign_algo_cert_client_auth]}, + {rsa_1_3, [], all_version_tests() ++ tls_1_3_tests() ++ [unsupported_sign_algo_client_auth, + unsupported_sign_algo_cert_client_auth]}, {ecdsa_1_3, [], all_version_tests() ++ tls_1_3_tests()} ]. @@ -208,12 +209,12 @@ auth(Config) -> ssl_cert_tests:auth(Config). %%-------------------------------------------------------------------- client_auth_empty_cert_accepted() -> - ssl_cert_tests:client_auth_empty_cert_accepted(). + ssl_cert_tests:client_auth_empty_cert_accepted(). client_auth_empty_cert_accepted(Config) -> ssl_cert_tests:client_auth_empty_cert_accepted(Config). %%-------------------------------------------------------------------- client_auth_empty_cert_rejected() -> - ssl_cert_tests:client_auth_empty_cert_rejected(). + ssl_cert_tests:client_auth_empty_cert_rejected(). client_auth_empty_cert_rejected(Config) -> ssl_cert_tests:client_auth_empty_cert_rejected(Config). %%-------------------------------------------------------------------- @@ -239,7 +240,6 @@ client_auth_partial_chain_fun_fail() -> client_auth_partial_chain_fun_fail(Config) when is_list(Config) -> ssl_cert_tests:client_auth_partial_chain_fun_fail(Config). - %%-------------------------------------------------------------------- missing_root_cert_no_auth() -> ssl_cert_tests:missing_root_cert_no_auth(). @@ -484,11 +484,27 @@ unsupported_sign_algo_cert_client_auth(Config) -> ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config), ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']}, {verify, verify_peer}, + {signature_algs, [rsa_pkcs1_sha256, rsa_pkcs1_sha384, rsa_pss_rsae_sha256]}, + %% Skip rsa_pkcs1_sha256! + {signature_algs_cert, [rsa_pkcs1_sha384, rsa_pkcs1_sha512]}, + {fail_if_no_peer_cert, true}|ServerOpts0], + ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0], + ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, certificate_required). + +%%-------------------------------------------------------------------- +unsupported_sign_algo_client_auth() -> + [{doc,"TLS 1.3: Test client authentication with unsupported signature_algorithm"}]. + +unsupported_sign_algo_client_auth(Config) -> + ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config), + ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config), + ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']}, + {verify, verify_peer}, %% Skip rsa_pkcs1_sha256! - {signature_algs, [rsa_pkcs1_sha384, rsa_pss_rsae_sha256]}, + {signature_algs, [rsa_pkcs1_sha384, rsa_pkcs1_sha512]}, {fail_if_no_peer_cert, true}|ServerOpts0], ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0], - ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, handshake_failure). + ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, insufficient_security). %%-------------------------------------------------------------------- hello_retry_client_auth() -> [{doc, "TLS 1.3 (HelloRetryRequest): Test client authentication."}]. diff --git a/lib/ssl/test/ssl_cert_tests.erl b/lib/ssl/test/ssl_cert_tests.erl index f330c716bc..c88daa2185 100644 --- a/lib/ssl/test/ssl_cert_tests.erl +++ b/lib/ssl/test/ssl_cert_tests.erl @@ -243,9 +243,9 @@ custom_groups(Config) -> ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config), ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config), - {ServerOpts, ClientOpts} = group_config(Config, - [{versions, ['tlsv1.2','tlsv1.3']} | ServerOpts0], - [{versions, ['tlsv1.2','tlsv1.3']} | ClientOpts0]), + {ServerOpts, ClientOpts} = group_config_custom(Config, + [{versions, ['tlsv1.2','tlsv1.3']} | ServerOpts0], + [{versions, ['tlsv1.2','tlsv1.3']} | ClientOpts0]), ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config). @@ -262,11 +262,26 @@ unsupported_sign_algo_cert_client_auth(Config) -> ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config), ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']}, {verify, verify_peer}, + {signature_algs, [rsa_pkcs1_sha256, rsa_pkcs1_sha384, rsa_pss_rsae_sha256]}, + %% Skip rsa_pkcs1_sha256! + {signature_algs_cert, [rsa_pkcs1_sha384, rsa_pkcs1_sha512]}, + {fail_if_no_peer_cert, true}|ServerOpts0], + ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0], + ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, certificate_required). +%%-------------------------------------------------------------------- +unsupported_sign_algo_client_auth() -> + [{doc,"TLS 1.3: Test client authentication with unsupported signature_algorithm"}]. + +unsupported_sign_algo_client_auth(Config) -> + ClientOpts0 = ssl_test_lib:ssl_options(client_cert_opts, Config), + ServerOpts0 = ssl_test_lib:ssl_options(server_cert_opts, Config), + ServerOpts = [{versions, ['tlsv1.2','tlsv1.3']}, + {verify, verify_peer}, %% Skip rsa_pkcs1_sha256! - {signature_algs, [rsa_pkcs1_sha384, rsa_pss_rsae_sha256]}, + {signature_algs, [rsa_pkcs1_sha384, rsa_pkcs1_sha512]}, {fail_if_no_peer_cert, true}|ServerOpts0], ClientOpts = [{versions, ['tlsv1.2','tlsv1.3']}|ClientOpts0], - ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, handshake_failure). + ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, insufficient_security). %%-------------------------------------------------------------------- hello_retry_client_auth() -> [{doc, "TLS 1.3 (HelloRetryRequest): Test client authentication."}]. @@ -278,14 +293,14 @@ hello_retry_client_auth(Config) -> {ServerOpts, ClientOpts} = group_config(Config, [{versions, ['tlsv1.2','tlsv1.3']}, {verify, verify_peer}, - {fail_if_no_peer_cert, false} | ServerOpts0], + {fail_if_no_peer_cert, true} | ServerOpts0], [{versions, ['tlsv1.2','tlsv1.3']}, {verify, verify_peer} | ClientOpts0]), ssl_test_lib:basic_test(ClientOpts, ServerOpts, Config). %%-------------------------------------------------------------------- hello_retry_client_auth_empty_cert_accepted() -> [{doc,"TLS 1.3 (HelloRetryRequest): Test client authentication when client sends an empty " - "certificate and fail_if_no_peer_cert is set to true."}]. + "certificate and fail_if_no_peer_cert is set to false."}]. hello_retry_client_auth_empty_cert_accepted(Config) -> ClientOpts0 = proplists:delete(keyfile, @@ -314,7 +329,7 @@ hello_retry_client_auth_empty_cert_rejected(Config) -> {ServerOpts, ClientOpts} = group_config(Config, [{versions, ['tlsv1.2','tlsv1.3']}, {verify, verify_peer}, - {fail_if_no_peer_cert, false} | ServerOpts0], + {fail_if_no_peer_cert, true} | ServerOpts0], [{versions, ['tlsv1.2','tlsv1.3']}, {verify, verify_peer} | ClientOpts0]), ssl_test_lib:basic_alert(ClientOpts, ServerOpts, Config, certificate_required). @@ -324,16 +339,35 @@ hello_retry_client_auth_empty_cert_rejected(Config) -> %% Internal functions ----------------------------------------------- %%-------------------------------------------------------------------- +group_config_custom(Config, ServerOpts, ClientOpts) -> + case proplists:get_value(client_type, Config) of + erlang -> + {[{groups,"X448:P-256:P-384"} | ServerOpts], + [{supported_groups, [secp384r1, secp256r1, x25519]} | ClientOpts]}; + openssl -> + {[{supported_groups, [x448, secp256r1, secp384r1]} | ServerOpts], + [{groups,"P-384:P-256:X25519"} | ClientOpts]} + end. + group_config(Config, ServerOpts, ClientOpts) -> case proplists:get_value(client_type, Config) of erlang -> - {[{groups,"P-256:X25519"} | ServerOpts], + {[{groups,"X448:X25519"} | ServerOpts], [{supported_groups, [secp256r1, x25519]} | ClientOpts]}; openssl -> {[{supported_groups, [x448, x25519]} | ServerOpts], [{groups,"P-256:X25519"} | ClientOpts]} end. +test_ciphers(_, 'tlsv1.3' = Version) -> + Ciphers = ssl:cipher_suites(default, Version), + ct:log("Version ~p Testing ~p~n", [Version, Ciphers]), + OpenSSLCiphers = openssl_ciphers(), + ct:log("OpenSSLCiphers ~p~n", [OpenSSLCiphers]), + lists:filter(fun(C) -> + ct:log("Cipher ~p~n", [C]), + lists:member(ssl_cipher_format:suite_map_to_openssl_str(C), OpenSSLCiphers) + end, Ciphers); test_ciphers(Kex, Version) -> Ciphers = ssl:filter_cipher_suites(ssl:cipher_suites(default, Version), [{key_exchange, Kex}]), @@ -345,6 +379,8 @@ test_ciphers(Kex, Version) -> lists:member(ssl_cipher_format:suite_map_to_openssl_str(C), OpenSSLCiphers) end, Ciphers). + + openssl_ciphers() -> Str = os:cmd("openssl ciphers"), string:split(string:strip(Str, right, $\n), ":", all). diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl index 5d0d09b33a..7dd27fb5cb 100644 --- a/lib/ssl/test/ssl_test_lib.erl +++ b/lib/ssl/test/ssl_test_lib.erl @@ -648,8 +648,7 @@ cert_options(Config) -> "badcert.pem"]), BadKeyFile = filename:join([proplists:get_value(priv_dir, Config), "badkey.pem"]), - PskSharedSecret = <<1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>, - + [{client_opts, [{cacertfile, ClientCaCertFile}, {certfile, ClientCertFile}, {keyfile, ClientKeyFile}]}, @@ -1227,6 +1226,11 @@ basic_test(COpts, SOpts, Config) -> stop(Server, Client). basic_alert(ClientOpts, ServerOpts, Config, Alert) -> + SType = proplists:get_value(server_type, Config), + CType = proplists:get_value(client_type, Config), + run_basic_alert(SType, CType, ClientOpts, ServerOpts, Config, Alert). + +run_basic_alert(erlang, erlang, ClientOpts, ServerOpts, Config, Alert) -> {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), Server = start_server_error([{node, ServerNode}, {port, 0}, @@ -1242,7 +1246,30 @@ basic_alert(ClientOpts, ServerOpts, Config, Alert) -> {mfa, {ssl_test_lib, no_result, []}}, {options, ClientOpts}]), - check_server_alert(Server, Client, Alert). + check_server_alert(Server, Client, Alert); +run_basic_alert(openssl = SType, erlang, ClientOpts, ServerOpts, Config, Alert) -> + {ClientNode, _, Hostname} = ssl_test_lib:run_where(Config), + {_Server, Port} = start_server(SType, ClientOpts, ServerOpts, Config), + ssl_test_lib:wait_for_openssl_server(Port, proplists:get_value(protocol, Config)), + Client = start_client_error([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {ssl_test_lib, no_result, []}}, + {options, ClientOpts}]), + + check_client_alert(Client, Alert); +run_basic_alert(erlang, openssl = CType, ClientOpts, ServerOpts, Config, Alert) -> + {_, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + Server = start_server_error([{node, ServerNode}, {port, 0}, + {host, Hostname}, + {from, self()}, + {mfa, {ssl_test_lib, no_result, []}}, + {options, ServerOpts}]), + Port = inet_port(Server), + start_client(CType, Port, ClientOpts, Config), + + check_server_alert(Server, Alert). + ecc_test(Expect, COpts, SOpts, CECCOpts, SECCOpts, Config) -> {Server, Port} = start_server_ecc(erlang, SOpts, Expect, SECCOpts, Config), @@ -1285,32 +1312,23 @@ start_basic_client(openssl, Version, Port, ClientOpts) -> OpenSslPort. start_client(openssl, Port, ClientOpts, Config) -> - Cert = proplists:get_value(certfile, ClientOpts), - Key = proplists:get_value(keyfile, ClientOpts), - CA = proplists:get_value(cacertfile, ClientOpts), Version = ssl_test_lib:protocol_version(Config), Exe = "openssl", + Ciphers = proplists:get_value(ciphers, ClientOpts, ssl:cipher_suites(default,Version)), Groups0 = proplists:get_value(groups, ClientOpts), + CertArgs = openssl_cert_options(ClientOpts, client), Exe = "openssl", - Args0 = ["s_client", "-verify", "2", "-port", integer_to_list(Port), - ssl_test_lib:version_flag(Version), - "-CAfile", CA, "-host", "localhost", "-msg", "-debug"], - Args1 = - case Groups0 of - undefined -> - Args0; - G -> - Args0 ++ ["-groups", G] - end, - Args2 = - case {Cert, Key} of - {C, K} when C =:= undefined orelse - K =:= undefined -> - Args1; - {C, K} -> - Args1 ++ ["-cert", C, "-key", K] - end, - Args = maybe_force_ipv4(Args2), + Args0 = case Groups0 of + undefined -> + ["s_client", "-verify", "2", "-port", integer_to_list(Port), cipher_flag(Version), + ciphers(Ciphers, Version), + ssl_test_lib:version_flag(Version)] ++ CertArgs ++ ["-msg", "-debug"]; + Group -> + ["s_client", "-verify", "2", "-port", integer_to_list(Port), cipher_flag(Version), + ciphers(Ciphers, Version), "-groups", Group, + ssl_test_lib:version_flag(Version)] ++ CertArgs ++ ["-msg", "-debug"] + end, + Args = maybe_force_ipv4(Args0), OpenSslPort = ssl_test_lib:portable_open_port(Exe, Args), true = port_command(OpenSslPort, "Hello world"), OpenSslPort; @@ -1361,11 +1379,19 @@ start_server(openssl, ClientOpts, ServerOpts, Config) -> Port = inet_port(node()), Version = protocol_version(Config), Exe = "openssl", - CertArgs = openssl_cert_options(ServerOpts), - [Cipher|_] = proplists:get_value(ciphers, ClientOpts, ssl:cipher_suites(default,Version)), - Args = ["s_server", "-accept", integer_to_list(Port), "-cipher", - ssl_cipher_format:suite_map_to_openssl_str(Cipher), - ssl_test_lib:version_flag(Version)] ++ CertArgs ++ ["-msg", "-debug"], + CertArgs = openssl_cert_options(ServerOpts, server), + Ciphers = proplists:get_value(ciphers, ClientOpts, ssl:cipher_suites(default,Version)), + Groups0 = proplists:get_value(groups, ServerOpts), + Args = case Groups0 of + undefined -> + ["s_server", "-accept", integer_to_list(Port), cipher_flag(Version), + ciphers(Ciphers, Version), + ssl_test_lib:version_flag(Version)] ++ CertArgs ++ ["-msg", "-debug"]; + Group -> + ["s_server", "-accept", integer_to_list(Port), cipher_flag(Version), + ciphers(Ciphers, Version), "-groups", Group, + ssl_test_lib:version_flag(Version)] ++ CertArgs ++ ["-msg", "-debug"] + end, OpenSslPort = portable_open_port(Exe, Args), true = port_command(OpenSslPort, "Hello world"), {OpenSslPort, Port}; @@ -1380,6 +1406,27 @@ start_server(erlang, _, ServerOpts, Config) -> [KeyEx]}}, {options, [{verify, verify_peer}, {versions, Versions} | ServerOpts]}]), {Server, inet_port(Server)}. + +cipher_flag('tlsv1.3') -> + "-ciphersuites"; +cipher_flag(_) -> + "-cipher". + +ciphers(Ciphers, Version) -> + Strs = [ssl_cipher_format:suite_map_to_openssl_str(Cipher) || Cipher <- Ciphers], + ciphers_concat(Version, Strs, ""). + +ciphers_concat(_, [], [":" | Acc]) -> + lists:append(lists:reverse(Acc)); +ciphers_concat('tlsv1.3' = Version, [Head| Tail], Acc) -> + case Head of + "TLS" ++ _ -> + ciphers_concat(Version, Tail, [":", Head | Acc]); + _ -> + ciphers_concat(Version, Tail, Acc) + end; +ciphers_concat(Version, [Head| Tail], Acc) -> + ciphers_concat(Version, Tail, [":", Head | Acc]). start_server_with_raw_key(erlang, ServerOpts, Config) -> {_, ServerNode, _} = ssl_test_lib:run_where(Config), @@ -1434,23 +1481,31 @@ stop(Client, Server) -> close(Client). -openssl_cert_options(ServerOpts) -> - Cert = proplists:get_value(certfile, ServerOpts, undefined), - Key = proplists:get_value(keyfile, ServerOpts, undefined), - CA = proplists:get_value(cacertfile, ServerOpts, undefined), +openssl_cert_options(Opts, Role) -> + Cert = proplists:get_value(certfile, Opts, undefined), + Key = proplists:get_value(keyfile, Opts, undefined), + CA = proplists:get_value(cacertfile, Opts, undefined), case CA of undefined -> case cert_option("-cert", Cert) ++ cert_option("-key", Key) of - [] -> + [] when Role == server -> ["-nocert"]; Other -> Other end; _ -> cert_option("-cert", Cert) ++ cert_option("-CAfile", CA) ++ - cert_option("-key", Key) ++ ["-verify", "2"] + cert_option("-key", Key) ++ openssl_verify(Opts) ++ ["2"] end. +openssl_verify(Opts) -> + case proplists:get_value(fail_if_no_peer_cert, Opts, undefined) of + true -> + ["-Verify"]; + _ -> + ["-verify"] + end. + cert_option(_, undefined) -> []; cert_option(Opt, Value) -> @@ -2711,3 +2766,25 @@ new_config(PrivDir, ServerOpts0) -> [{cacertfile, NewCaCertFile}, {certfile, NewCertFile}, {keyfile, NewKeyFile} | ServerOpts]. + +sane_openssl_alpn_npn_renegotiate() -> + case os:cmd("openssl version") of + "LibreSSL 2.9.1" ++ _ -> + false; + "LibreSSL 2.6.4" ++ _ -> + false; + "OpenSSL 1.1.1a-freebsd" ++ _ -> + false; + _ -> + true + end. + +openssl_sane_dtls_alpn() -> + case os:cmd("openssl version") of + "OpenSSL 1.1.0g" ++ _ -> + false; + "OpenSSL 1.1.1a" ++ _ -> + false; + _-> + openssl_sane_dtls() + end. |