diff options
Diffstat (limited to 'lib')
126 files changed, 7001 insertions, 6611 deletions
diff --git a/lib/asn1/doc/src/asn1ct.xml b/lib/asn1/doc/src/asn1ct.xml index 9a9bb7ec1b..bb3c6a4f0f 100644 --- a/lib/asn1/doc/src/asn1ct.xml +++ b/lib/asn1/doc/src/asn1ct.xml @@ -120,9 +120,7 @@ File3.asn </pre> <c>Options</c> is a list with options specific for the asn1 compiler and options that are applied to the Erlang compiler. The latter are those that not is recognized as asn1 specific. - For <em>preferred option use</em> see <seealso - marker="asn1_ug#preferred option use">Preferred Option Use - section in users guide</seealso>. Available options are: + Available options are: </p> <taglist> <tag><c>ber | per | uper</c></tag> diff --git a/lib/asn1/src/asn1ct.erl b/lib/asn1/src/asn1ct.erl index 90882462ac..98877320a0 100644 --- a/lib/asn1/src/asn1ct.erl +++ b/lib/asn1/src/asn1ct.erl @@ -1288,35 +1288,35 @@ pretty2(Module,AbsFile) -> {ok,F} = file:open(AbsFile,[write]), M = asn1_db:dbget(Module,'MODULE'), io:format(F,"%%%%%%%%%%%%%%%%%%% ~p %%%%%%%%%%%%%%%%%%%~n",[Module]), - io:format(F,"~s\n",[asn1ct_pretty_format:term(M#module.defid)]), - io:format(F,"~s\n",[asn1ct_pretty_format:term(M#module.tagdefault)]), - io:format(F,"~s\n",[asn1ct_pretty_format:term(M#module.exports)]), - io:format(F,"~s\n",[asn1ct_pretty_format:term(M#module.imports)]), - io:format(F,"~s\n\n",[asn1ct_pretty_format:term(M#module.extensiondefault)]), + io:format(F,"~s.\n",[asn1ct_pretty_format:term(M#module.defid)]), + io:format(F,"~s.\n",[asn1ct_pretty_format:term(M#module.tagdefault)]), + io:format(F,"~s.\n",[asn1ct_pretty_format:term(M#module.exports)]), + io:format(F,"~s.\n",[asn1ct_pretty_format:term(M#module.imports)]), + io:format(F,"~s.\n\n",[asn1ct_pretty_format:term(M#module.extensiondefault)]), {Types,Values,ParameterizedTypes,Classes,Objects,ObjectSets} = M#module.typeorval, io:format(F,"%%%%%%%%%%%%%%%%%%% TYPES in ~p %%%%%%%%%%%%%%%%%%%~n",[Module]), - lists:foreach(fun(T)-> io:format(F,"~s\n", + lists:foreach(fun(T)-> io:format(F,"~s.\n", [asn1ct_pretty_format:term(asn1_db:dbget(Module,T))]) end,Types), io:format(F,"%%%%%%%%%%%%%%%%%%% VALUES in ~p %%%%%%%%%%%%%%%%%%%~n",[Module]), - lists:foreach(fun(T)-> io:format(F,"~s\n", + lists:foreach(fun(T)-> io:format(F,"~s.\n", [asn1ct_pretty_format:term(asn1_db:dbget(Module,T))]) end,Values), io:format(F,"%%%%%%%%%%%%%%%%%%% Parameterized Types in ~p %%%%%%%%%%%%%%%%%%%~n",[Module]), - lists:foreach(fun(T)-> io:format(F,"~s\n", + lists:foreach(fun(T)-> io:format(F,"~s.\n", [asn1ct_pretty_format:term(asn1_db:dbget(Module,T))]) end,ParameterizedTypes), io:format(F,"%%%%%%%%%%%%%%%%%%% Classes in ~p %%%%%%%%%%%%%%%%%%%~n",[Module]), - lists:foreach(fun(T)-> io:format(F,"~s\n", + lists:foreach(fun(T)-> io:format(F,"~s.\n", [asn1ct_pretty_format:term(asn1_db:dbget(Module,T))]) end,Classes), io:format(F,"%%%%%%%%%%%%%%%%%%% Objects in ~p %%%%%%%%%%%%%%%%%%%~n",[Module]), - lists:foreach(fun(T)-> io:format(F,"~s\n", + lists:foreach(fun(T)-> io:format(F,"~s.\n", [asn1ct_pretty_format:term(asn1_db:dbget(Module,T))]) end,Objects), io:format(F,"%%%%%%%%%%%%%%%%%%% Object Sets in ~p %%%%%%%%%%%%%%%%%%%~n",[Module]), - lists:foreach(fun(T)-> io:format(F,"~s\n", + lists:foreach(fun(T)-> io:format(F,"~s.\n", [asn1ct_pretty_format:term(asn1_db:dbget(Module,T))]) end,ObjectSets). start() -> diff --git a/lib/asn1/src/asn1ct_check.erl b/lib/asn1/src/asn1ct_check.erl index fe1b2e14a8..dd77085c39 100644 --- a/lib/asn1/src/asn1ct_check.erl +++ b/lib/asn1/src/asn1ct_check.erl @@ -4340,11 +4340,33 @@ permitted_alphabet_merge([C1|Rest],UorI,Acc) -> %% there will be no extension if the last constraint is without extension. %% The rootset of all constraints are considered in the "outermoust %% intersection". See section 13.1.2 in Dubuisson. -constraint_merge(_S,C=[H])when is_tuple(H) -> +constraint_merge(St, Cs0) -> + Cs = constraint_merge_1(St, Cs0), + normalize_cs(Cs). + +normalize_cs([{'SingleValue',[V]}|Cs]) -> + [{'SingleValue',V}|normalize_cs(Cs)]; +normalize_cs([{'SingleValue',[_|_]=L0}|Cs]) -> + [H|T] = L = lists:usort(L0), + [case is_range(H, T) of + false -> {'SingleValue',L}; + true -> {'ValueRange',{H,lists:last(T)}} + end|normalize_cs(Cs)]; +normalize_cs([{'ValueRange',{Sv,Sv}}|Cs]) -> + [{'SingleValue',Sv}|normalize_cs(Cs)]; +normalize_cs([{'ValueRange',{'MIN','MAX'}}|Cs]) -> + normalize_cs(Cs); +normalize_cs(Other) -> Other. + +is_range(Prev, [H|T]) when Prev =:= H - 1 -> is_range(H, T); +is_range(_, [_|_]) -> false; +is_range(_, []) -> true. + +constraint_merge_1(_S, [H]=C) when is_tuple(H) -> C; -constraint_merge(_S,[]) -> +constraint_merge_1(_S, []) -> []; -constraint_merge(S,C) -> +constraint_merge_1(S, C) -> %% skip all extension but the last extension C1 = filter_extensions(C), %% perform all internal level intersections, intersections first @@ -4367,17 +4389,16 @@ constraint_merge(S,C) -> %% get the least common size constraint SZs = get_constraints(C3,'SizeConstraint'), CombSZ = intersection_of_size(S,SZs), - CminusSVs=ordsets:subtract(ordsets:from_list(C3),ordsets:from_list(SVs)), - % CminusSVsVRs = ordsets:subtract(ordsets:from_list(CminusSVs), -% ordsets:from_list(VRs)), - RestC = ordsets:subtract(ordsets:from_list(CminusSVs), - ordsets:from_list(SZs)), + RestC = ordsets:subtract(ordsets:from_list(C3), + ordsets:from_list(SZs ++ VRs ++ SVs)), %% get the least common combined constraint. That is the union of each - %% deep costraint and merge of single value and value range constraints - NewCs = combine_constraints(S,CombSV,CombVR,CombSZ++RestC), - [X||X <- lists:flatten(NewCs), - X /= intersection, - X /= union]. + %% deep constraint and merge of single value and value range constraints. + %% FIXME: Removing 'intersection' from the flattened list essentially + %% means that intersections are converted to unions! + Cs = combine_constraints(S, CombSV, CombVR, CombSZ++RestC), + [X || X <- lists:flatten(Cs), + X =/= intersection, + X =/= union]. %% constraint_union(S,C) takes a list of constraints as input and %% merge them to a union. Unions are performed when two @@ -4407,16 +4428,16 @@ constraint_union(_S,C) -> constraint_union1(S,[A={'ValueRange',_},union,B={'ValueRange',_}|Rest],Acc) -> AunionB = constraint_union_vr([A,B]), - constraint_union1(S,Rest,Acc ++ AunionB); + constraint_union1(S, AunionB++Rest, Acc); constraint_union1(S,[A={'SingleValue',_},union,B={'SingleValue',_}|Rest],Acc) -> AunionB = constraint_union_sv(S,[A,B]), constraint_union1(S,Rest,Acc ++ AunionB); constraint_union1(S,[A={'SingleValue',_},union,B={'ValueRange',_}|Rest],Acc) -> AunionB = union_sv_vr(S,A,B), - constraint_union1(S,Rest,Acc ++ AunionB); + constraint_union1(S, AunionB++Rest, Acc); constraint_union1(S,[A={'ValueRange',_},union,B={'SingleValue',_}|Rest],Acc) -> AunionB = union_sv_vr(S,B,A), - constraint_union1(S,Rest,Acc ++ AunionB); + constraint_union1(S, AunionB++Rest, Acc); constraint_union1(S,[union|Rest],Acc) -> %skip when unsupported constraints constraint_union1(S,Rest,Acc); constraint_union1(S,[A|Rest],Acc) -> @@ -4449,15 +4470,8 @@ constraint_union_vr(VR) -> ({_,{A1,_B1}},{_,{A2,_B2}}) when is_integer(A1),is_integer(A2),A1<A2 -> true; ({_,{A,B1}},{_,{A,B2}}) when B1=<B2->true; (_,_)->false end, - % sort and remove duplicates - SortedVR = lists:sort(Fun,VR), - RemoveDup = fun([],_) ->[]; - ([H],_) -> [H]; - ([H,H|T],F) -> F([H|T],F); - ([H|T],F) -> [H|F(T,F)] - end, - - constraint_union_vr(RemoveDup(SortedVR,RemoveDup),[]). + SortedVR = lists:usort(Fun,VR), + constraint_union_vr(SortedVR, []). constraint_union_vr([],Acc) -> lists:reverse(Acc); @@ -4467,8 +4481,8 @@ constraint_union_vr([{_,{Lb,Ub2}}|Rest],[{_,{Lb,_Ub1}}|Acc]) -> %Ub2 > Ub1 constraint_union_vr(Rest,[{'ValueRange',{Lb,Ub2}}|Acc]); constraint_union_vr([{_,{_,Ub}}|Rest],A=[{_,{_,Ub}}|_Acc]) -> constraint_union_vr(Rest,A); -constraint_union_vr([{_,{Lb2,Ub2}}|Rest],[{_,{Lb1,Ub1}}|Acc]) when Lb2=<Ub1, - Ub2>Ub1-> +constraint_union_vr([{_,{Lb2,Ub2}}|Rest], [{_,{Lb1,Ub1}}|Acc]) + when Ub1 =< Lb2, Ub1 < Ub2 -> constraint_union_vr(Rest,[{'ValueRange',{Lb1,Ub2}}|Acc]); constraint_union_vr([{_,{_,Ub2}}|Rest],A=[{_,{_,Ub1}}|_Acc]) when Ub2=<Ub1-> constraint_union_vr(Rest,A); @@ -4589,9 +4603,11 @@ constraint_intersection(_S,C) -> constraint_intersection1(S,[A,intersection,B|Rest],Acc) -> AisecB = c_intersect(S,A,B), - constraint_intersection1(S,Rest,AisecB++Acc); + constraint_intersection1(S, AisecB++Rest, Acc); constraint_intersection1(S,[A|Rest],Acc) -> constraint_intersection1(S,Rest,[A|Acc]); +constraint_intersection1(_, [], [C]) -> + C; constraint_intersection1(_,[],Acc) -> lists:reverse(Acc). diff --git a/lib/asn1/src/asn1ct_constructed_per.erl b/lib/asn1/src/asn1ct_constructed_per.erl index b29a7b3048..27070be966 100644 --- a/lib/asn1/src/asn1ct_constructed_per.erl +++ b/lib/asn1/src/asn1ct_constructed_per.erl @@ -108,7 +108,10 @@ gen_encode_constructed(Erule,Typename,D) when is_record(D,type) -> emit([ {next,val}," = case [X || X <- [",Elements, "],X =/= asn1_NOVALUE] of",nl, - "[] -> ",{curr,val},";",nl, + "[] -> setelement(", + {asis,ExtActualGroupPos+1},",", + {curr,val},",", + "asn1_NOVALUE);",nl, "_ -> setelement(",{asis,ExtActualGroupPos+1},",", {curr,val},",", "{extaddgroup,", Elements,"})",nl, @@ -1099,10 +1102,11 @@ gen_dec_components_call(Erule,TopType,CL={Root1,ExtList,Root2}, {EmitExts,_} = gen_dec_comp_calls(NewExtList, Erule, TopType, OptTable, DecInfObj, Ext, NumberOfOptionals, Tpos, []), + NumExtsToSkip = ext_length(ExtList), Finish = fun(St) -> emit([{next,bytes},"= ?RT_PER:skipextensions(",{curr,bytes},",", - length(ExtList)+1,",Extensions)"]), + NumExtsToSkip+1,",Extensions)"]), asn1ct_name:new(bytes), St end, @@ -1361,7 +1365,7 @@ gen_dec_line_open_type(_, _, _) -> fun() -> St end} end}. -gen_dec_line_special(_, {typefield,_}, _TopType, Comp, +gen_dec_line_special(Erule, {typefield,_}, _TopType, Comp, DecInfObj, Ext) -> #'ComponentType'{name=Cname,typespec=Type,prop=Prop} = Comp, fun({_BytesVar,PrevSt}) -> @@ -1370,13 +1374,14 @@ gen_dec_line_special(_, {typefield,_}, _TopType, Comp, {Name,RestFieldNames} = (Type#type.def)#'ObjectClassFieldType'.fieldname, - asn1ct_name:new(tmpterm), asn1ct_name:new(reason), - emit([indent(2),"{",{curr,tmpterm},", ",{next,bytes}, - "} = ?RT_PER:decode_open_type(",{curr,bytes}, - ", []),",nl]), - emit([indent(2),"case (catch ObjFun(", - {asis,Name},",",{curr,tmpterm},",telltype,", + Imm = asn1ct_imm:per_dec_open_type(is_aligned(Erule)), + BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)), + {TmpTerm,TempBuf} = asn1ct_imm:dec_slim_cg(Imm, BytesVar), + emit([com,nl, + {next,bytes}," = ",TempBuf,com,nl, + indent(2),"case (catch ObjFun(", + {asis,Name},",",TmpTerm,",telltype,", {asis,RestFieldNames},")) of", nl]), emit([indent(4),"{'EXIT',",{curr,reason},"} ->",nl]), emit([indent(6),"exit({'Type not ", @@ -1402,8 +1407,10 @@ gen_dec_line_special(_, {typefield,_}, _TopType, Comp, end, {Name,RestFieldNames} = (Type#type.def)#'ObjectClassFieldType'.fieldname, - emit(["?RT_PER:decode_open_type(",{curr,bytes}, - ", []),",nl]), + Imm = asn1ct_imm:per_dec_open_type(is_aligned(Erule)), + BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)), + asn1ct_imm:dec_code_gen(Imm, BytesVar), + emit([com,nl]), if Ext == noext andalso Prop == mandatory -> emit([{curr,term}," =",nl," "]); @@ -1429,8 +1436,9 @@ gen_dec_line_special(_, {typefield,_}, _TopType, Comp, end, {[],PrevSt}; _ -> - emit(["?RT_PER:decode_open_type(",{curr,bytes}, - ", [])"]), + Imm = asn1ct_imm:per_dec_open_type(is_aligned(Erule)), + BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)), + asn1ct_imm:dec_code_gen(Imm, BytesVar), RefedFieldName = (Type#type.def)#'ObjectClassFieldType'.fieldname, @@ -1440,10 +1448,12 @@ gen_dec_line_special(_, {typefield,_}, _TopType, Comp, Prop}],PrevSt} end end; -gen_dec_line_special(_, {objectfield,PrimFieldName1,PFNList}, _TopType, +gen_dec_line_special(Erule, {objectfield,PrimFieldName1,PFNList}, _TopType, Comp, _DecInfObj, _Ext) -> fun({_BytesVar,PrevSt}) -> - emit(["?RT_PER:decode_open_type(",{curr,bytes},", [])"]), + Imm = asn1ct_imm:per_dec_open_type(is_aligned(Erule)), + BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)), + asn1ct_imm:dec_code_gen(Imm, BytesVar), #'ComponentType'{name=Cname,prop=Prop} = Comp, SaveBytes = [{Cname,{PrimFieldName1,PFNList}, asn1ct_gen:mk_var(asn1ct_name:curr(term)), @@ -1666,20 +1676,15 @@ gen_dec_choice1(Erule,TopType,CompList,{ext,ExtPos,ExtNum}) -> length(CompList)-ExtNum,",Ext ),",nl}), emit({"{Cname,{Val,NewBytes}} = case Choice + Ext*",ExtPos-1," of",nl}), gen_dec_choice2(Erule,TopType,CompList,{ext,ExtPos,ExtNum}), - case Erule of - per -> - emit([";",nl,"_ -> {asn1_ExtAlt,",nl, - " fun() -> ",nl, - " {XTerm,XBytes} = ?RT_PER:decode_open_type(", - {curr,bytes},",[]),",nl, - " {binary_to_list(XTerm),XBytes}",nl, - " end()}"]); - _ -> - emit([";",nl,"_ -> {asn1_ExtAlt, ?RT_PER:decode_open_type(", - {curr,bytes},",[])}"]) - end, - emit({nl,"end,",nl}), - emit({nl,"{{Cname,Val},NewBytes}"}). + Imm = asn1ct_imm:per_dec_open_type(is_aligned(Erule)), + BytesVar = asn1ct_gen:mk_var(asn1ct_name:curr(bytes)), + emit([";",nl, + "_ ->",nl]), + {TmpTerm,TmpBuf} = asn1ct_imm:dec_slim_cg(Imm, BytesVar), + emit([com,nl, + "{asn1_ExtAlt,{",TmpTerm,com,TmpBuf,"}}",nl, + "end,",nl,nl, + "{{Cname,Val},NewBytes}"]). gen_dec_choice2(Erule,TopType,L,Ext) -> diff --git a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl index 00c3dd98b2..664dfc2086 100644 --- a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl +++ b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl @@ -114,16 +114,6 @@ gen_encode(Erules,Typename,Type) when is_record(Type,type) -> _ -> % embedded type with constructed name true end, - case lists:member(InnerType,['SET','SEQUENCE']) of - true -> - true; - _ -> - emit([nl,"'enc_",asn1ct_gen:list2name(Typename), - "'({'",asn1ct_gen:list2name(Typename), - "',Val}, TagIn",ObjFun,") ->",nl]), - emit([" 'enc_",asn1ct_gen:list2name(Typename), - "'(Val, TagIn",ObjFun,");",nl,nl]) - end, emit(["'enc_",asn1ct_gen:list2name(Typename), "'(Val, TagIn",ObjFun,") ->",nl," "]), asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,Type); @@ -157,15 +147,6 @@ gen_encode_user(Erules,D) when is_record(D,typedef) -> "'(Val",") ->",nl]), emit([" 'enc_",asn1ct_gen:list2name(Typename), "'(Val, ", {asis,lists:reverse(Tag)},").",nl,nl]), - - case lists:member(InnerType,['SET','SEQUENCE']) of - true -> - true; - _ -> - emit({nl,"'enc_",asn1ct_gen:list2name(Typename), - "'({'",asn1ct_gen:list2name(Typename),"',Val}, TagIn) ->",nl}), - emit({" 'enc_",asn1ct_gen:list2name(Typename),"'(Val, TagIn);",nl,nl}) - end, emit({"'enc_",asn1ct_gen:list2name(Typename),"'(Val, TagIn) ->",nl}), CurrentMod = get(currmod), case asn1ct_gen:type(InnerType) of diff --git a/lib/asn1/src/asn1ct_gen_per.erl b/lib/asn1/src/asn1ct_gen_per.erl index eb4cfdccc6..af19edb908 100644 --- a/lib/asn1/src/asn1ct_gen_per.erl +++ b/lib/asn1/src/asn1ct_gen_per.erl @@ -79,18 +79,6 @@ gen_encode(Erules,Typename,Type) when is_record(Type,type) -> end, case asn1ct_gen:type(InnerType) of {constructed,bif} -> - case InnerType of - 'SET' -> - true; - 'SEQUENCE' -> - true; - _ -> - emit({nl,"'enc_",asn1ct_gen:list2name(Typename), - "'({'",asn1ct_gen:list2name(Typename), - "',Val}",ObjFun,") ->",nl}), - emit({"'enc_",asn1ct_gen:list2name(Typename), - "'(Val",ObjFun,");",nl,nl}) - end, emit({"'enc_",asn1ct_gen:list2name(Typename),"'(Val",ObjFun, ") ->",nl}), asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,Type); @@ -943,7 +931,6 @@ gen_objset_dec(ObjSetName,_UniqueName,['EXTENSIONMARK'],_ClName,_ClFields, _NthObj) -> emit({"'getdec_",ObjSetName,"'(_, _) ->",nl}), emit({indent(3),"fun(Attr1, Bytes, _,_) ->",nl}), -%% emit({indent(6),"?RT_PER:decode_open_type(Bytes,[])",nl}), emit({indent(6),"{Bytes,Attr1}",nl}), emit({indent(3),"end.",nl,nl}), ok; @@ -959,76 +946,42 @@ emit_default_getdec(ObjSetName,UniqueName) -> emit([indent(2), "fun(C,V,_,_) -> exit({{component,C},{value,V},{unique_name_and_value,",{asis,UniqueName},",ErrV}}) end"]). -gen_inlined_dec_funs(Fields,[{typefield,Name,_}|Rest], - ObjSetName,NthObj) -> - CurrMod = get(currmod), - InternalDefFunName = [NthObj,Name,ObjSetName], - case lists:keysearch(Name,1,Fields) of - {value,{_,Type}} when is_record(Type,type) -> - emit({indent(3),"fun(Type, Val, _, _) ->",nl, - indent(6),"case Type of",nl}), - N=emit_inner_of_decfun(Type,InternalDefFunName), - gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N); - {value,{_,Type}} when is_record(Type,typedef) -> - emit({indent(3),"fun(Type, Val, _, _) ->",nl, - indent(6),"case Type of",nl}), - emit({indent(9),{asis,Name}," ->",nl}), - N=emit_inner_of_decfun(Type,InternalDefFunName), - gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N); - {value,{_,#'Externaltypereference'{module=CurrMod,type=T}}} -> - emit({indent(3),"fun(Type, Val, _, _) ->",nl, - indent(6),"case Type of",nl}), - emit({indent(9),{asis,Name}," ->",nl}), - emit([indent(12),"'dec_",T,"'(Val, telltype)"]), - gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj); - {value,{_,#'Externaltypereference'{module=M,type=T}}} -> - emit({indent(3),"fun(Type, Val, _, _) ->",nl, - indent(6),"case Type of",nl}), - emit({indent(9),{asis,Name}," ->",nl}), - emit([indent(12),"'",M,"':'dec_",T,"'(Val, telltype)"]), - gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj); - false -> - emit([indent(3),"fun(Type, Val, _, _) ->",nl, - indent(6),"case Type of",nl, - indent(9),{asis,Name}," ->{Val,Type}"]), - gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj) - end; -gen_inlined_dec_funs(Fields,[_|Rest],ObjSetName,NthObj) -> - gen_inlined_dec_funs(Fields,Rest,ObjSetName,NthObj); -gen_inlined_dec_funs(_,[],_,NthObj) -> +gen_inlined_dec_funs(Fields, List, ObjSetName, NthObj0) -> + emit([indent(3),"fun(Type, Val, _, _) ->",nl, + indent(6),"case Type of",nl]), + NthObj = gen_inlined_dec_funs1(Fields, List, ObjSetName, "", NthObj0), + emit([nl,indent(6),"end",nl, + indent(3),"end"]), NthObj. -gen_inlined_dec_funs1(Fields,[{typefield,Name,_}|Rest], - ObjSetName,NthObj) -> +gen_inlined_dec_funs1(Fields, [{typefield,Name,_}|Rest], + ObjSetName, Sep0, NthObj) -> CurrentMod = get(currmod), InternalDefFunName = [NthObj,Name,ObjSetName], - N=case lists:keysearch(Name,1,Fields) of - {value,{_,Type}} when is_record(Type,type) -> - emit({";",nl}), - emit_inner_of_decfun(Type,InternalDefFunName); - {value,{_,Type}} when is_record(Type,typedef) -> - emit({";",nl,indent(9),{asis,Name}," ->",nl}), - emit_inner_of_decfun(Type,InternalDefFunName); - {value,{_,#'Externaltypereference'{module=CurrentMod,type=T}}} -> - emit([";",nl,indent(9),{asis,Name}," ->",nl]), - emit([indent(12),"'dec_",T,"'(Val,telltype)"]), - 0; - {value,{_,#'Externaltypereference'{module=M,type=T}}} -> - emit([";",nl,indent(9),{asis,Name}," ->",nl]), - emit([indent(12),"'",M,"'",":'dec_",T,"'(Val,telltype)"]), - 0; - false -> - emit([";",nl, - indent(9),{asis,Name}," ->{Val,Type}"]), - 0 - end, - gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N); -gen_inlined_dec_funs1(Fields,[_|Rest],ObjSetName,NthObj)-> - gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj); -gen_inlined_dec_funs1(_,[],_,NthObj) -> - emit({nl,indent(6),"end",nl}), - emit({indent(3),"end"}), - NthObj. + emit(Sep0), + Sep = [";",nl], + N = case lists:keyfind(Name, 1, Fields) of + {_,#type{}=Type} -> + emit_inner_of_decfun(Type, InternalDefFunName); + {_,#typedef{}=Type} -> + emit([indent(9),{asis,Name}," ->",nl]), + emit_inner_of_decfun(Type, InternalDefFunName); + {_,#'Externaltypereference'{module=CurrentMod,type=T}} -> + emit([indent(9),{asis,Name}," ->",nl, + indent(12),"'dec_",T,"'(Val,telltype)"]), + 0; + {_,#'Externaltypereference'{module=M,type=T}} -> + emit([indent(9),{asis,Name}," ->",nl, + indent(12),"'",M,"':'dec_",T,"'(Val,telltype)"]), + 0; + false -> + emit([indent(9),{asis,Name}," -> {Val,Type}"]), + 0 + end, + gen_inlined_dec_funs1(Fields, Rest, ObjSetName, Sep, NthObj+N); +gen_inlined_dec_funs1(Fields, [_|Rest], ObjSetName, Sep, NthObj) -> + gen_inlined_dec_funs1(Fields, Rest, ObjSetName, Sep, NthObj); +gen_inlined_dec_funs1(_, [], _, _, NthObj) -> NthObj. emit_inner_of_decfun(#typedef{name={ExtName,Name},typespec=Type}, InternalDefFunName) -> @@ -1147,6 +1100,10 @@ gen_dec_imm(Erule, #type{def=Name,constraint=C}) -> end, gen_dec_imm_1(Name, C, Aligned). +gen_dec_imm_1('ASN1_OPEN_TYPE', Constraint, Aligned) -> + imm_decode_open_type(Constraint, Aligned); +gen_dec_imm_1('ANY', _Constraint, Aligned) -> + imm_decode_open_type([], Aligned); gen_dec_imm_1('BOOLEAN', _Constr, _Aligned) -> asn1ct_imm:per_dec_boolean(); gen_dec_imm_1({'ENUMERATED',{Base,Ext}}, _Constr, Aligned) -> @@ -1239,36 +1196,6 @@ gen_dec_prim_1(Erule, ",",{asis,Constraint},")"}); 'UTF8String' -> emit({"?RT_PER:decode_UTF8String(",BytesVar,")"}); - 'ANY' -> - case Erule of - per -> - emit(["fun() -> {XTerm,YTermXBytes} = ?RT_PER:decode_open_type(",BytesVar,",",{asis,Constraint}, "), {binary_to_list(XTerm),XBytes} end ()"]); - _ -> - emit(["?RT_PER:decode_open_type(",BytesVar,",", - {asis,Constraint}, ")"]) - end; - 'ASN1_OPEN_TYPE' -> - case Constraint of - [#'Externaltypereference'{type=Tname}] -> - emit(["fun(FBytes) ->",nl, - " {XTerm,XBytes} = "]), - emit(["?RT_PER:decode_open_type(FBytes,[]),",nl]), - emit([" {YTerm,_} = dec_",Tname,"(XTerm,mandatory),",nl]), - emit([" {YTerm,XBytes} end(",BytesVar,")"]); - [#type{def=#'Externaltypereference'{type=Tname}}] -> - emit(["fun(FBytes) ->",nl, - " {XTerm,XBytes} = "]), - emit(["?RT_PER:decode_open_type(FBytes,[]),",nl]), - emit([" {YTerm,_} = dec_",Tname,"(XTerm,mandatory),",nl]), - emit([" {YTerm,XBytes} end(",BytesVar,")"]); - _ -> - case Erule of - per -> - emit(["fun() -> {XTerm,XBytes} = ?RT_PER:decode_open_type(",BytesVar,", []), {binary_to_list(XTerm),XBytes} end()"]); - _ -> - emit(["?RT_PER:decode_open_type(",BytesVar,",[])"]) - end - end; #'ObjectClassFieldType'{} -> case asn1ct_gen:get_inner(Typename) of {fixedtypevaluefield,_,InnerType} -> @@ -1334,3 +1261,22 @@ extaddgroup2sequence([C|T],ExtNum,Acc) -> extaddgroup2sequence(T,ExtNum,[C|Acc]); extaddgroup2sequence([],_,Acc) -> lists:reverse(Acc). + +imm_decode_open_type([#'Externaltypereference'{type=Tname}], Aligned) -> + imm_dec_open_type_1(Tname, Aligned); +imm_decode_open_type([#type{def=#'Externaltypereference'{type=Tname}}], + Aligned) -> + imm_dec_open_type_1(Tname, Aligned); +imm_decode_open_type(_, Aligned) -> + asn1ct_imm:per_dec_open_type(Aligned). + +imm_dec_open_type_1(Type, Aligned) -> + D = fun(OpenType, Buf) -> + asn1ct_name:new(tmpval), + emit(["begin",nl, + "{",{curr,tmpval},",_} = ", + "dec_",Type,"(",OpenType,", mandatory),",nl, + "{",{curr,tmpval},com,Buf,"}",nl, + "end"]) + end, + {call,D,asn1ct_imm:per_dec_open_type(Aligned)}. diff --git a/lib/asn1/src/asn1ct_gen_per_rt2ct.erl b/lib/asn1/src/asn1ct_gen_per_rt2ct.erl index ecd212c3e3..4f4563833f 100644 --- a/lib/asn1/src/asn1ct_gen_per_rt2ct.erl +++ b/lib/asn1/src/asn1ct_gen_per_rt2ct.erl @@ -69,18 +69,6 @@ gen_encode(Erules,Typename,Type) when is_record(Type,type) -> end, case asn1ct_gen:type(InnerType) of {constructed,bif} -> - case InnerType of - 'SET' -> - true; - 'SEQUENCE' -> - true; - _ -> - emit({nl,"'enc_",asn1ct_gen:list2name(Typename), - "'({'",asn1ct_gen:list2name(Typename), - "',Val}",ObjFun,") ->",nl}), - emit({"'enc_",asn1ct_gen:list2name(Typename), - "'(Val",ObjFun,");",nl,nl}) - end, emit({"'enc_",asn1ct_gen:list2name(Typename),"'(Val",ObjFun, ") ->",nl}), asn1ct_gen:gen_encode_constructed(Erules,Typename,InnerType,Type); @@ -417,35 +405,46 @@ emit_enc_octet_string(_Erules,Constraint,Value) -> asn1ct_name:new(tmpval), emit({" begin",nl}), emit({" [",{curr,tmpval},"] = ",Value,",",nl}), - emit({" [10,8,",{curr,tmpval},"]",nl}), + emit([" [[10,8],",{curr,tmpval},"]",nl]), emit(" end"); 2 -> asn1ct_name:new(tmpval), - emit({" begin",nl}), - emit({" [",{curr,tmpval},",",{next,tmpval},"] = ", - Value,",",nl}), - emit({" [[10,8,",{curr,tmpval},"],[10,8,", - {next,tmpval},"]]",nl}), - emit(" end"), - asn1ct_name:new(tmpval); - Sv when is_integer(Sv),Sv =< 256 -> + emit([" begin",nl, + " ",{curr,tmpval}," = ",Value,",",nl, + " case length(",{curr,tmpval},") of",nl, + " 2 ->",nl, + " [[45,16,2]|",{curr,tmpval},"];",nl, + " _ ->",nl, + " exit({error,{value_out_of_bounds,", + {curr,tmpval},"}})",nl, + " end",nl, + " end"]); + Sv when is_integer(Sv), Sv < 256 -> asn1ct_name:new(tmpval), - emit({" begin",nl}), - emit({" case length(",Value,") of",nl}), - emit([" ",{curr,tmpval}," when ",{curr,tmpval}," == ",Sv," ->"]), - emit([" [2,20,",{curr,tmpval},",",Value,"];",nl]), - emit({" _ -> exit({error,{value_out_of_bounds,", - Value,"}})", nl," end",nl}), - emit(" end"); + asn1ct_name:new(tmplen), + emit([" begin",nl, + " ",{curr,tmpval}," = ",Value,",",nl, + " case length(",{curr,tmpval},") of",nl, + " ",Sv,"=",{curr,tmplen}," ->",nl, + " [20,",{curr,tmplen},"|",{curr,tmpval},"];",nl, + " _ ->",nl, + " exit({error,{value_out_of_bounds,", + {curr,tmpval},"}})",nl, + " end",nl, + " end"]); Sv when is_integer(Sv),Sv =< 65535 -> asn1ct_name:new(tmpval), - emit({" begin",nl}), - emit({" case length(",Value,") of",nl}), - emit([" ",{curr,tmpval}," when ",{curr,tmpval}," == ",Sv," ->"]), - emit([" [2,21,",{curr,tmpval},",",Value,"];",nl]), - emit({" _ -> exit({error,{value_out_of_bounds,", - Value,"}})",nl," end",nl}), - emit(" end"); + asn1ct_name:new(tmplen), + emit([" begin",nl, + " ",{curr,tmpval}," = ",Value,",",nl, + " case length(",{curr,tmpval},") of",nl, + " ",Sv,"=",{curr,tmplen}," ->",nl, + " [<<21,",{curr,tmplen},":16>>|",Value,"];",nl, + " _ ->",nl, + " exit({error,{value_out_of_bounds,", + {curr,tmpval},"}})",nl, + " end",nl, + " end"]); C -> emit({" ?RT_PER:encode_octet_string(",{asis,C},",false,",Value,")",nl}) end. @@ -1292,7 +1291,6 @@ gen_objset_dec(ObjSetName,_,['EXTENSIONMARK'],_ClName,_ClFields, _NthObj) -> emit({"'getdec_",ObjSetName,"'(_, _) ->",nl}), emit({indent(3),"fun(Attr1, Bytes, _, _) ->",nl}), - %% emit({indent(6),"?RT_PER:decode_open_type(Bytes,[])",nl}), emit({indent(6),"{Bytes,Attr1}",nl}), emit({indent(3),"end.",nl,nl}), ok; @@ -1308,77 +1306,42 @@ emit_default_getdec(ObjSetName,UniqueName) -> emit([indent(2), "fun(C,V,_,_) -> exit({{component,C},{value,V},{unique_name_and_value,",{asis,UniqueName},",ErrV}}) end"]). -gen_inlined_dec_funs(Fields,[{typefield,Name,_}|Rest], - ObjSetName,NthObj) -> - CurrMod = get(currmod), - InternalDefFunName = [NthObj,Name,ObjSetName], - case lists:keysearch(Name,1,Fields) of - {value,{_,Type}} when is_record(Type,type) -> - emit({indent(3),"fun(Type, Val, _, _) ->",nl, - indent(6),"case Type of",nl}), - N=emit_inner_of_decfun(Type,InternalDefFunName), - gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N); - {value,{_,Type}} when is_record(Type,typedef) -> - emit({indent(3),"fun(Type, Val, _, _) ->",nl, - indent(6),"case Type of",nl}), - emit({indent(9),{asis,Name}," ->",nl}), - N=emit_inner_of_decfun(Type,InternalDefFunName), - gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N); - {value,{_,#'Externaltypereference'{module=CurrMod,type=T}}} -> - emit({indent(3),"fun(Type, Val, _, _) ->",nl, - indent(6),"case Type of",nl}), - emit({indent(9),{asis,Name}," ->",nl}), - emit([indent(12),"'dec_",T,"'(Val, telltype)"]), - gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj); - {value,{_,#'Externaltypereference'{module=M,type=T}}} -> - emit({indent(3),"fun(Type, Val, _, _) ->",nl, - indent(6),"case Type of",nl}), - emit({indent(9),{asis,Name}," ->",nl}), - emit([indent(12),"'",M,"':'dec_",T,"'(Val, telltype)"]), - gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj); - false -> - emit([indent(3),"fun(Type, Val, _, _) ->",nl, - indent(6),"case Type of",nl, - indent(9),{asis,Name}," -> {Val,Type}"]), - gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj) - end; -gen_inlined_dec_funs(Fields,[_|Rest],ObjSetName,NthObj) -> - gen_inlined_dec_funs(Fields,Rest,ObjSetName,NthObj); -gen_inlined_dec_funs(_,[],_,NthObj) -> +gen_inlined_dec_funs(Fields, List, ObjSetName, NthObj0) -> + emit([indent(3),"fun(Type, Val, _, _) ->",nl, + indent(6),"case Type of",nl]), + NthObj = gen_inlined_dec_funs1(Fields, List, ObjSetName, "", NthObj0), + emit([nl,indent(6),"end",nl, + indent(3),"end"]), NthObj. -gen_inlined_dec_funs1(Fields,[{typefield,Name,_}|Rest], - ObjSetName,NthObj) -> +gen_inlined_dec_funs1(Fields, [{typefield,Name,_}|Rest], + ObjSetName, Sep0, NthObj) -> CurrentMod = get(currmod), InternalDefFunName = [NthObj,Name,ObjSetName], - N= - case lists:keysearch(Name,1,Fields) of - {value,{_,Type}} when is_record(Type,type) -> - emit({";",nl}), - emit_inner_of_decfun(Type,InternalDefFunName); - {value,{_,Type}} when is_record(Type,typedef) -> - emit({";",nl,indent(9),{asis,Name}," ->",nl}), - emit_inner_of_decfun(Type,InternalDefFunName); - {value,{_,#'Externaltypereference'{module=CurrentMod,type=T}}} -> - emit([";",nl,indent(9),{asis,Name}," ->",nl]), - emit([indent(12),"'dec_",T,"'(Val,telltype)"]), - 0; - {value,{_,#'Externaltypereference'{module=M,type=T}}} -> - emit([";",nl,indent(9),{asis,Name}," ->",nl]), - emit([indent(12),"'",M,"':'dec_",T,"'(Val,telltype)"]), - 0; - false -> - emit([";",nl, - indent(9),{asis,Name}," -> {Val,Type}"]), - 0 - end, - gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj+N); -gen_inlined_dec_funs1(Fields,[_|Rest],ObjSetName,NthObj)-> - gen_inlined_dec_funs1(Fields,Rest,ObjSetName,NthObj); -gen_inlined_dec_funs1(_,[],_,NthObj) -> - emit({nl,indent(6),"end",nl}), - emit({indent(3),"end"}), - NthObj. + emit(Sep0), + Sep = [";",nl], + N = case lists:keyfind(Name, 1, Fields) of + {_,#type{}=Type} -> + emit_inner_of_decfun(Type, InternalDefFunName); + {_,#typedef{}=Type} -> + emit([indent(9),{asis,Name}," ->",nl]), + emit_inner_of_decfun(Type, InternalDefFunName); + {_,#'Externaltypereference'{module=CurrentMod,type=T}} -> + emit([indent(9),{asis,Name}," ->",nl, + indent(12),"'dec_",T,"'(Val,telltype)"]), + 0; + {_,#'Externaltypereference'{module=M,type=T}} -> + emit([indent(9),{asis,Name}," ->",nl, + indent(12),"'",M,"':'dec_",T,"'(Val,telltype)"]), + 0; + false -> + emit([indent(9),{asis,Name}," -> {Val,Type}"]), + 0 + end, + gen_inlined_dec_funs1(Fields, Rest, ObjSetName, Sep, NthObj+N); +gen_inlined_dec_funs1(Fields, [_|Rest], ObjSetName, Sep, NthObj) -> + gen_inlined_dec_funs1(Fields, Rest, ObjSetName, Sep, NthObj); +gen_inlined_dec_funs1(_, [], _, _, NthObj) -> NthObj. emit_inner_of_decfun(#typedef{name={ExtName,Name},typespec=Type}, InternalDefFunName) -> @@ -1579,25 +1542,9 @@ gen_dec_prim(Erules,Att,BytesVar) -> 'UTF8String' -> emit({"?RT_PER:decode_UTF8String(",BytesVar,")"}); 'ANY' -> - emit(["?RT_PER:decode_open_type(",BytesVar,",", - {asis,Constraint}, ")"]); + asn1ct_gen_per:gen_dec_prim(Erules, Att, BytesVar); 'ASN1_OPEN_TYPE' -> - case Constraint of - [#'Externaltypereference'{type=Tname}] -> - emit(["fun(FBytes) ->",nl, - " {XTerm,XBytes} = "]), - emit(["?RT_PER:decode_open_type(FBytes,[]),",nl]), - emit([" {YTerm,_} = dec_",Tname,"(XTerm,mandatory),",nl]), - emit([" {YTerm,XBytes} end(",BytesVar,")"]); - [#type{def=#'Externaltypereference'{type=Tname}}] -> - emit(["fun(FBytes) ->",nl, - " {XTerm,XBytes} = "]), - emit(["?RT_PER:decode_open_type(FBytes,[]),",nl]), - emit([" {YTerm,_} = dec_",Tname,"(XTerm,mandatory),",nl]), - emit([" {YTerm,XBytes} end(",BytesVar,")"]); - _ -> - emit(["?RT_PER:decode_open_type(",BytesVar,",[])"]) - end; + asn1ct_gen_per:gen_dec_prim(Erules, Att, BytesVar); #'ObjectClassFieldType'{} -> case asn1ct_gen:get_inner(Att#type.def) of {fixedtypevaluefield,_,InnerType} -> diff --git a/lib/asn1/src/asn1ct_parser2.erl b/lib/asn1/src/asn1ct_parser2.erl index 7301f49085..9e1fcce2b1 100644 --- a/lib/asn1/src/asn1ct_parser2.erl +++ b/lib/asn1/src/asn1ct_parser2.erl @@ -924,19 +924,8 @@ parse_UnionsRec([{'|',_}|Rest]) -> {V1,V2} -> {[V1,union,V2],Rest3} end; -parse_UnionsRec([{'UNION',_}|Rest]) -> - {InterSec,Rest2} = parse_Intersections(Rest), - {URec,Rest3} = parse_UnionsRec(Rest2), - case {InterSec,URec} of - {V1,[]} -> - {V1,Rest3}; - {{'SingleValue',V1},{'SingleValue',V2}} -> - {{'SingleValue',ordsets:union(to_set(V1),to_set(V2))},Rest3}; - {V1,V2} when is_list(V2) -> - {[V1] ++ [union|V2],Rest3}; - {V1,V2} -> - {[V1,union,V2],Rest3} - end; +parse_UnionsRec([{'UNION',Info}|Rest]) -> + parse_UnionsRec([{'|',Info}|Rest]); parse_UnionsRec(Tokens) -> {[],Tokens}. @@ -971,20 +960,8 @@ parse_IElemsRec([{'^',_}|Rest]) -> {V1,V2} -> {[V1,intersection,V2],Rest3} end; -parse_IElemsRec([{'INTERSECTION',_}|Rest]) -> - {InterSec,Rest2} = parse_IntersectionElements(Rest), - {IRec,Rest3} = parse_IElemsRec(Rest2), - case {InterSec,IRec} of - {{'SingleValue',V1},{'SingleValue',V2}} -> - {{'SingleValue', - ordsets:intersection(to_set(V1),to_set(V2))},Rest3}; - {V1,[]} -> - {V1,Rest3}; - {V1,V2} when is_list(V2) -> - {[V1] ++ [intersection|V2],Rest3}; - {V1,V2} -> - {[V1,intersection,V2],Rest3} - end; +parse_IElemsRec([{'INTERSECTION',Info}|Rest]) -> + parse_IElemsRec([{'^',Info}|Rest]); parse_IElemsRec(Tokens) -> {[],Tokens}. diff --git a/lib/asn1/src/asn1rt_uper_bin.erl b/lib/asn1/src/asn1rt_uper_bin.erl index 9410c3ef90..fc65d80245 100644 --- a/lib/asn1/src/asn1rt_uper_bin.erl +++ b/lib/asn1/src/asn1rt_uper_bin.erl @@ -120,14 +120,15 @@ fixextensions(Pos,ExtPos,Val,Acc) -> end, fixextensions(Pos+1,ExtPos,Val,(Acc bsl 1)+Bit). -skipextensions(Bytes,Nr,ExtensionBitPattern) -> - case (catch element(Nr,ExtensionBitPattern)) of - 1 -> +skipextensions(Bytes,Nr,ExtensionBitstr) when is_bitstring(ExtensionBitstr) -> + Prev = Nr - 1, + case ExtensionBitstr of + <<_:Prev,1:1,_/bitstring>> -> {_,Bytes2} = decode_open_type(Bytes,[]), - skipextensions(Bytes2, Nr+1, ExtensionBitPattern); - 0 -> - skipextensions(Bytes, Nr+1, ExtensionBitPattern); - {'EXIT',_} -> % badarg, no more extensions + skipextensions(Bytes2, Nr+1, ExtensionBitstr); + <<_:Prev,0:1,_/bitstring>> -> + skipextensions(Bytes, Nr+1, ExtensionBitstr); + _ -> Bytes end. diff --git a/lib/asn1/test/asn1_SUITE.erl b/lib/asn1/test/asn1_SUITE.erl index 38ec72c473..325293f35d 100644 --- a/lib/asn1/test/asn1_SUITE.erl +++ b/lib/asn1/test/asn1_SUITE.erl @@ -20,19 +20,10 @@ -module(asn1_SUITE). --define(only_per(Func), - if Rule =:= per -> Func; - true -> ok - end). -define(only_ber(Func), if Rule =:= ber -> Func; true -> ok end). --define(only_uper(Func), - case Rule of - uper -> Func; - _ -> ok - end). -compile(export_all). @@ -62,7 +53,8 @@ groups() -> [{compile, parallel([]), [c_syntax, c_string, - c_implicit_before_choice]}, + c_implicit_before_choice, + constraint_equivalence]}, {ber, parallel([]), [ber_choiceinseq, @@ -188,7 +180,6 @@ groups() -> testDoubleEllipses, test_x691, ticket_6143, - testExtensionAdditionGroup, test_OTP_9688]}, {performance, [], @@ -321,12 +312,12 @@ testCompactBitString(Config, Rule, Opts) -> asn1_test_lib:compile("PrimStrings", Config, [Rule, compact_bit_string|Opts]), testCompactBitString:compact_bit_string(Rule), - ?only_uper(testCompactBitString:bit_string_unnamed(Rule)), - ?only_per(testCompactBitString:bit_string_unnamed(Rule)), - ?only_per(testCompactBitString:ticket_7734(Rule)), - ?only_per(asn1_test_lib:compile("Constraints", Config, - [Rule, compact_bit_string|Opts])), - ?only_per(testCompactBitString:otp_4869(Rule)). + testCompactBitString:bit_string_unnamed(Rule), + testCompactBitString:bit_string_unnamed(Rule), + testCompactBitString:ticket_7734(Rule), + asn1_test_lib:compile("Constraints", Config, + [Rule, compact_bit_string|Opts]), + testCompactBitString:otp_4869(Rule). testPrimStrings(Config) -> test(Config, fun testPrimStrings/3). testPrimStrings(Config, Rule, Opts) -> @@ -439,7 +430,8 @@ testSeqExtension(Config) -> test(Config, fun testSeqExtension/3). testSeqExtension(Config, Rule, Opts) -> asn1_test_lib:compile_all(["External", "SeqExtension"], Config, [Rule|Opts]), - testSeqExtension:main(Rule). + DataDir = ?config(data_dir, Config), + testSeqExtension:main(DataDir, [Rule|Opts]). testSeqExternal(Config) -> test(Config, fun testSeqExternal/3). testSeqExternal(Config, Rule, Opts) -> @@ -627,6 +619,34 @@ c_implicit_before_choice(Config, Rule, Opts) -> {error, _R2} = asn1ct:compile(filename:join(DataDir, "CCSNARG3"), [Rule, {outdir, CaseDir}|Opts]). +constraint_equivalence(Config) -> + DataDir = ?config(data_dir, Config), + CaseDir = ?config(case_dir, Config), + Asn1Spec = "ConstraintEquivalence", + Asn1Src = filename:join(DataDir, Asn1Spec), + ok = asn1ct:compile(Asn1Src, [abs,{outdir,CaseDir}]), + AbsFile = filename:join(CaseDir, Asn1Spec++".abs"), + {ok,Terms} = file:consult(AbsFile), + Cs = [begin + 'INTEGER' = element(3, Type), %Assertion. + Constraints = element(4, Type), + Name1 = atom_to_list(Name0), + {Name,_} = lists:splitwith(fun(C) -> C =/= $X end, Name1), + {Name,Constraints} + end || {typedef,_,_,Name0,Type} <- Terms], + R = sofs:relation(Cs, [{name,constraint}]), + F0 = sofs:relation_to_family(R), + F = sofs:to_external(F0), + Diff = [E || {_,L}=E <- F, length(L) > 1], + case Diff of + [] -> + ok; + [_|_] -> + io:put_chars("Not equivalent:\n"), + [io:format("~s: ~p\n", [N,D]) || {N,D} <- Diff], + test_server:fail(length(Diff)) + end. + parse(Config) -> [asn1_test_lib:compile(M, Config, [abs]) || M <- test_modules()]. @@ -1063,6 +1083,7 @@ testExtensionAdditionGroup(Config, Rule, Opts) -> [debug_info]), extensionAdditionGroup:run([Rule|Opts]), extensionAdditionGroup:run2([Rule|Opts]), + extensionAdditionGroup:run3(), asn1_test_lib:compile("EUTRA-RRC-Definitions", Config, [Rule, {record_name_prefix, "RRC-"}|Opts]), extensionAdditionGroup:run3([Rule|Opts]). diff --git a/lib/asn1/test/asn1_SUITE_data/ConstraintEquivalence.asn1 b/lib/asn1/test/asn1_SUITE_data/ConstraintEquivalence.asn1 new file mode 100644 index 0000000000..6a97c1b38e --- /dev/null +++ b/lib/asn1/test/asn1_SUITE_data/ConstraintEquivalence.asn1 @@ -0,0 +1,42 @@ +ConstraintEquivalence DEFINITIONS AUTOMATIC TAGS ::= +BEGIN + SingleValueX42 ::= INTEGER (42) + SingleValueX1 ::= INTEGER ((42) ^ (42)) + SingleValueX2 ::= INTEGER ((42) INTERSECTION (42)) + SingleValueX3 ::= INTEGER ((42) | (42)) + SingleValueX4 ::= INTEGER ((42) UNION (42)) + SingleValueX5 ::= INTEGER ((42) INTERSECTION (MIN..MAX)) + SingleValueX6 ::= INTEGER ((42) INTERSECTION (40..49)) + SingleValueX7 ::= INTEGER (42..42) + + UnconstrainedX0 ::= INTEGER + UnconstrainedX1 ::= INTEGER (MIN..MAX) + UnconstrainedX2 ::= INTEGER (1|(MIN..MAX)) + UnconstrainedX3 ::= INTEGER (1..10|(MIN..MAX)) + UnconstrainedX4 ::= INTEGER ((MIN..MAX)|9|10) + UnconstrainedX5 ::= INTEGER ((MIN..MAX)|10..20) + UnconstrainedX6 ::= INTEGER ((MIN..MAX) UNION (10..20)) + + RangeX00 ::= INTEGER (5..10) + RangeX01 ::= INTEGER (4<..<11) + RangeX02 ::= INTEGER (5..<11) + RangeX03 ::= INTEGER (4<..10) + RangeX04 ::= INTEGER (5|6|7|8|9|10) + RangeX05 ::= INTEGER (10|9|8|7|6|5) + RangeX06 ::= INTEGER (5|6|7..10) + + RangeX10 ::= INTEGER ((5..6) UNION (7..8) UNION (9|10)) + RangeX11 ::= INTEGER ((5|6) UNION (7..8) UNION (9|10)) + RangeX12 ::= INTEGER ((5|6) UNION (7|8) UNION (9|10)) + RangeX13 ::= INTEGER ((5|6) UNION (7) UNION (8..10)) + RangeX14 ::= INTEGER ((5|6) UNION (7) UNION (8..10)) + RangeX15 ::= INTEGER ((5|6) UNION (7) UNION ((8..8)|(9..9)|(10))) + RangeX16 ::= INTEGER ((5|6) UNION (7) UNION (7<..<11)) + + RangeX20 ::= INTEGER (0..20) (5..10) + RangeX21 ::= INTEGER (0..10) (5..20) + RangeX22 ::= INTEGER (0..10) (5..20) (MIN..MAX) + RangeX23 ::= INTEGER ((0..10) INTERSECTION (5..20) ^ (MIN..MAX)) + RangeX24 ::= INTEGER ((5|6|7|8|9|10) INTERSECTION (5..20) ^ (MIN..MAX)) + +END diff --git a/lib/asn1/test/asn1_SUITE_data/Extension-Addition-Group.asn b/lib/asn1/test/asn1_SUITE_data/Extension-Addition-Group.asn index 55124f9449..b7cc74ab07 100644 --- a/lib/asn1/test/asn1_SUITE_data/Extension-Addition-Group.asn +++ b/lib/asn1/test/asn1_SUITE_data/Extension-Addition-Group.asn @@ -95,6 +95,27 @@ AS-Config ::= SEQUENCE { ]] } +SystemInformationBlockType2 ::= SEQUENCE { + timeAlignmentTimerCommon TimeAlignmentTimer, + ..., + lateNonCriticalExtension OCTET STRING OPTIONAL, + [[ ssac-BarringForMMTEL-Voice-r9 AC-BarringConfig OPTIONAL, + ssac-BarringForMMTEL-Video-r9 AC-BarringConfig OPTIONAL + ]], + [[ ac-BarringForCSFB-r10 AC-BarringConfig OPTIONAL + ]] +} + +TimeAlignmentTimer ::= ENUMERATED { + sf500, sf750, sf1280, sf1920, sf2560, sf5120, + sf10240, infinity} +AC-BarringConfig ::= SEQUENCE { + ac-BarringFactor ENUMERATED { + p00, p05, p10, p15, p20, p25, p30, p40, + p50, p60, p70, p75, p80, p85, p90, p95}, + ac-BarringTime ENUMERATED {s4, s8, s16, s32, s64, s128, s256, s512}, + ac-BarringForSpecialAC BIT STRING (SIZE(5)) +} END diff --git a/lib/asn1/test/asn1_SUITE_data/PrimStrings.asn1 b/lib/asn1/test/asn1_SUITE_data/PrimStrings.asn1 index 7cb47e9792..9b6b34a776 100644 --- a/lib/asn1/test/asn1_SUITE_data/PrimStrings.asn1 +++ b/lib/asn1/test/asn1_SUITE_data/PrimStrings.asn1 @@ -59,6 +59,19 @@ BS1024 ::= BIT STRING (SIZE (1024)) FixedOs65536 ::= OCTET STRING (SIZE (65536)) FixedOs65537 ::= OCTET STRING (SIZE (65537)) + OsFixedStrings ::= SEQUENCE { + b1 BOOLEAN, -- Unalign + s0 OCTET STRING (SIZE (0)), + s1 OCTET STRING (SIZE (1)), + s2 OCTET STRING (SIZE (2)), + s3 OCTET STRING (SIZE (3)), + b2 BOOLEAN, -- Unalign + s255 OCTET STRING (SIZE (255)), + s256 OCTET STRING (SIZE (256)), + s257 OCTET STRING (SIZE (257)), + i INTEGER (0..1024) + } + OsAlignment ::= SEQUENCE { b1 BOOLEAN, s1 Os, diff --git a/lib/asn1/test/asn1_SUITE_data/SeqExtension.asn1 b/lib/asn1/test/asn1_SUITE_data/SeqExtension.asn1 index bb0a7cca3a..5fda19303a 100644 --- a/lib/asn1/test/asn1_SUITE_data/SeqExtension.asn1 +++ b/lib/asn1/test/asn1_SUITE_data/SeqExtension.asn1 @@ -31,7 +31,35 @@ SeqExt4 ::= SEQUENCE int INTEGER } +SeqExt5 ::= SEQUENCE +{ + ..., + [[ name OCTET STRING (SIZE (1..8)), + shoesize INTEGER ]] +} + +SeqExt6 ::= SEQUENCE +{ + -- The spaces between the ellipsis and the comma will prevent them + -- from being removed. + ... , + [[ i1 [100] INTEGER, i2 [101] INTEGER, i3 [102] INTEGER ]], + [[ i4 [104] INTEGER, i5 [105] INTEGER ]], + [[ i6 [106] INTEGER, i7 [107] INTEGER ]] +} + SeqExt1X ::= XSeqExt1 SeqExt2X ::= XSeqExt2 +SuperSeq ::= SEQUENCE +{ + s1 SeqExt1, + s2 SeqExt2, + s3 SeqExt3, + s4 SeqExt4, + s5 SeqExt5, + s6 SeqExt6, + i INTEGER +} + END diff --git a/lib/asn1/test/asn1_SUITE_data/extensionAdditionGroup.erl b/lib/asn1/test/asn1_SUITE_data/extensionAdditionGroup.erl index 5fcec23756..8148381d92 100644 --- a/lib/asn1/test/asn1_SUITE_data/extensionAdditionGroup.erl +++ b/lib/asn1/test/asn1_SUITE_data/extensionAdditionGroup.erl @@ -130,3 +130,26 @@ run3(Erule) -> _ -> exit({expected,Val, got, Val2}) end. +run3() -> + SI = #'SystemInformationBlockType2'{ + timeAlignmentTimerCommon = sf500, + lateNonCriticalExtension = asn1_NOVALUE, + 'ssac-BarringForMMTEL-Voice-r9' = asn1_NOVALUE, + 'ssac-BarringForMMTEL-Video-r9' = asn1_NOVALUE, + 'ac-BarringForCSFB-r10' = asn1_NOVALUE}, + Barring = #'AC-BarringConfig'{ + 'ac-BarringFactor' = p00, + 'ac-BarringTime' = s4, + 'ac-BarringForSpecialAC' = [0,0,0,0,0]}, + roundtrip(SI), + roundtrip(SI#'SystemInformationBlockType2'{ + 'ssac-BarringForMMTEL-Voice-r9'=Barring}), + roundtrip(SI#'SystemInformationBlockType2'{ + 'ssac-BarringForMMTEL-Video-r9'=Barring}), + roundtrip(SI#'SystemInformationBlockType2'{ + 'ac-BarringForCSFB-r10'=Barring}). + +roundtrip(V) -> + Mod = 'Extension-Addition-Group', + {ok,E} = Mod:encode('SystemInformationBlockType2', V), + {ok,V} = Mod:decode('SystemInformationBlockType2', iolist_to_binary(E)). diff --git a/lib/asn1/test/asn1_SUITE_data/testobj.erl b/lib/asn1/test/asn1_SUITE_data/testobj.erl index 80942f7e38..d9f60ca8a3 100644 --- a/lib/asn1/test/asn1_SUITE_data/testobj.erl +++ b/lib/asn1/test/asn1_SUITE_data/testobj.erl @@ -883,7 +883,7 @@ initial_ue_ies() -> cn_domain_indicator() -> - {'CN-DomainIndicator', 'ps-domain'}. + 'ps-domain'. init_lai() -> #'ProtocolIE-Field'{ @@ -1279,11 +1279,11 @@ reset() -> protocolIEs = reset_ies() }. reset_ies() -> - {'Reset_protocolIEs', % this identifier is very unneccesary here - [reset_cause(), - cn_domain_ind(), % Se initial Ue - init_global_rnc_id() % ---- " ---- - ]}. + [reset_cause(), + cn_domain_ind(), % Se initial Ue + init_global_rnc_id() % ---- " ---- + ]. + init_global_rnc_id() -> #'ProtocolIE-Field'{ id = 86, % 86 = id-GlobalRNC-ID @@ -1323,8 +1323,7 @@ reset_ack() -> protocolIEs = reset_ack_ies() }. reset_ack_ies() -> - {'ResetAcknowledge_protocolIEs', % very unneccesary - [cn_domain_ind()]}. % Se initial Ue + [cn_domain_ind()]. % Se initial Ue @@ -1336,13 +1335,12 @@ reset_res(IuSCId) -> }. reset_res_ies(IuSCId) -> - {'ResetResource_protocolIEs', % very unneccesary - [ - cn_domain_ind() % Se initial Ue - ,reset_cause() % Se reset - ,reset_res_list(IuSCId) - ,init_global_rnc_id_reset_res() % ---- " ---- - ]}. + [ + cn_domain_ind() % Se initial Ue + ,reset_cause() % Se reset + ,reset_res_list(IuSCId) + ,init_global_rnc_id_reset_res() % ---- " ---- + ]. init_global_rnc_id_reset_res() -> #'ProtocolIE-Field'{ diff --git a/lib/asn1/test/testChoExtension.erl b/lib/asn1/test/testChoExtension.erl index b75cfb6831..067d4d2bf7 100644 --- a/lib/asn1/test/testChoExtension.erl +++ b/lib/asn1/test/testChoExtension.erl @@ -25,42 +25,27 @@ extension(_Rules) -> - - ?line {ok,Bytes1} = asn1_wrapper:encode('ChoExtension','ChoExt1',{'ChoExt1',{bool,true}}), - ?line {ok,{bool,true}} = - asn1_wrapper:decode('ChoExtension','ChoExt1',lists:flatten(Bytes1)), - - ?line {ok,Bytes2} = asn1_wrapper:encode('ChoExtension','ChoExt1',{'ChoExt1',{int,33}}), - ?line {ok,{int,33}} = - asn1_wrapper:decode('ChoExtension','ChoExt1',lists:flatten(Bytes2)), + roundtrip('ChoExt1', {bool,true}), + roundtrip('ChoExt1', {int,33}), %% A trick to encode with another compatible CHOICE type to test reception %% extension alternative - ?line {ok,Bytes2x} = asn1_wrapper:encode('ChoExtension','ChoExt1x',{str,"abc"}), - ?line {ok,Val2x} = + {ok,Bytes2x} = asn1_wrapper:encode('ChoExtension','ChoExt1x',{str,"abc"}), + {ok,Val2x} = asn1_wrapper:decode('ChoExtension','ChoExt1',lists:flatten(Bytes2x)), io:format("Choice extension alternative = ~p~n",[Val2x]), - ?line {ok,Bytes3} = asn1_wrapper:encode('ChoExtension','ChoExt2',{'ChoExt2',{bool,true}}), - ?line {ok,{bool,true}} = - asn1_wrapper:decode('ChoExtension','ChoExt2',lists:flatten(Bytes3)), - - ?line {ok,Bytes4} = asn1_wrapper:encode('ChoExtension','ChoExt2',{'ChoExt2',{int,33}}), - ?line {ok,{int,33}} = - asn1_wrapper:decode('ChoExtension','ChoExt2',lists:flatten(Bytes4)), + roundtrip('ChoExt2', {bool,true}), + roundtrip('ChoExt2', {int,33}), + roundtrip('ChoExt3', {bool,true}), + roundtrip('ChoExt3', {int,33}), + roundtrip('ChoExt4', {str,"abc"}), - ?line {ok,Bytes5} = asn1_wrapper:encode('ChoExtension','ChoExt3',{'ChoExt3',{bool,true}}), - ?line {ok,{bool,true}} = - asn1_wrapper:decode('ChoExtension','ChoExt3',lists:flatten(Bytes5)), - - ?line {ok,Bytes6} = asn1_wrapper:encode('ChoExtension','ChoExt3',{'ChoExt3',{int,33}}), - ?line {ok,{int,33}} = - asn1_wrapper:decode('ChoExtension','ChoExt3',lists:flatten(Bytes6)), - - Val7 = {str,"abc"}, - ?line {ok,Bytes7} = asn1_wrapper:encode('ChoExtension','ChoExt4',Val7), - ?line {ok,Val7} = asn1_wrapper:decode('ChoExtension','ChoExt4',lists:flatten(Bytes7)), + ok. +roundtrip(Type, Value) -> + {ok,Encoded} = 'ChoExtension':encode(Type, Value), + {ok,Value} = 'ChoExtension':decode(Type, Encoded), ok. diff --git a/lib/asn1/test/testChoExternal.erl b/lib/asn1/test/testChoExternal.erl index b2d171f9c7..5fdee48add 100644 --- a/lib/asn1/test/testChoExternal.erl +++ b/lib/asn1/test/testChoExternal.erl @@ -38,62 +38,27 @@ compile(Config, Rules, Optimize) -> external(_Rules) -> + roundtrip('ChoXCho', {boolCho,true}), + roundtrip('ChoXCho', {intCho,77}), - ?line {ok,Bytes11} = asn1_wrapper:encode('ChoExternal','ChoXCho',{'ChoXCho',{boolCho,true}}), - ?line {ok,{boolCho,true}} = asn1_wrapper:decode('ChoExternal','ChoXCho',lists:flatten(Bytes11)), - - - ?line {ok,Bytes12} = asn1_wrapper:encode('ChoExternal','ChoXCho',{'ChoXCho',{intCho,77}}), - ?line {ok,{intCho,77}} = asn1_wrapper:decode('ChoExternal','ChoXCho',lists:flatten(Bytes12)), - - - - ?line {ok,Bytes21} = asn1_wrapper:encode('ChoExternal','ChoXBool',{'ChoXBool',{xbool,true}}), - ?line {ok,{xbool,true}} = asn1_wrapper:decode('ChoExternal','ChoXBool',lists:flatten(Bytes21)), - - - ?line {ok,Bytes22} = asn1_wrapper:encode('ChoExternal','ChoXBool',{'ChoXBool',{xboolImp,true}}), - ?line {ok,{xboolImp,true}} = asn1_wrapper:decode('ChoExternal','ChoXBool',lists:flatten(Bytes22)), - - - ?line {ok,Bytes23} = asn1_wrapper:encode('ChoExternal','ChoXBool',{'ChoXBool',{xboolExp,true}}), - ?line {ok,{xboolExp,true}} = asn1_wrapper:decode('ChoExternal','ChoXBool',lists:flatten(Bytes23)), - - - - ?line {ok,Bytes31} = asn1_wrapper:encode('ChoExternal','NT',{os,"kalle"}), - ?line {ok,{os,"kalle"}} = asn1_wrapper:decode('ChoExternal','NT',lists:flatten(Bytes31)), - - ?line {ok,Bytes32} = asn1_wrapper:encode('ChoExternal','Exp',{os,"kalle"}), - ?line {ok,{os,"kalle"}} = asn1_wrapper:decode('ChoExternal','Exp',lists:flatten(Bytes32)), - - ?line {ok,Bytes33} = asn1_wrapper:encode('ChoExternal','NTNT',{os,"kalle"}), - ?line {ok,{os,"kalle"}} = asn1_wrapper:decode('ChoExternal','NTNT',lists:flatten(Bytes33)), - - ?line {ok,Bytes34} = asn1_wrapper:encode('ChoExternal','NTExp',{os,"kalle"}), - ?line {ok,{os,"kalle"}} = asn1_wrapper:decode('ChoExternal','NTExp',lists:flatten(Bytes34)), - - ?line {ok,Bytes35} = asn1_wrapper:encode('ChoExternal','ExpNT',{os,"kalle"}), - ?line {ok,{os,"kalle"}} = asn1_wrapper:decode('ChoExternal','ExpNT',lists:flatten(Bytes35)), - - ?line {ok,Bytes36} = asn1_wrapper:encode('ChoExternal','ExpExp',{os,"kalle"}), - ?line {ok,{os,"kalle"}} = asn1_wrapper:decode('ChoExternal','ExpExp',lists:flatten(Bytes36)), - - - - - - ?line {ok,Bytes41} = asn1_wrapper:encode('ChoExternal','XNTNT',{os,"kalle"}), - ?line {ok,{os,"kalle"}} = asn1_wrapper:decode('ChoExternal','XNTNT',lists:flatten(Bytes41)), - - ?line {ok,Bytes42} = asn1_wrapper:encode('ChoExternal','XNTExp',{os,"kalle"}), - ?line {ok,{os,"kalle"}} = asn1_wrapper:decode('ChoExternal','XNTExp',lists:flatten(Bytes42)), - - ?line {ok,Bytes43} = asn1_wrapper:encode('ChoExternal','XExpNT',{os,"kalle"}), - ?line {ok,{os,"kalle"}} = asn1_wrapper:decode('ChoExternal','XExpNT',lists:flatten(Bytes43)), - - ?line {ok,Bytes44} = asn1_wrapper:encode('ChoExternal','XExpExp',{os,"kalle"}), - ?line {ok,{os,"kalle"}} = asn1_wrapper:decode('ChoExternal','XExpExp',lists:flatten(Bytes44)), + roundtrip('ChoXBool', {xbool,true}), + roundtrip('ChoXBool', {xboolImp,true}), + roundtrip('ChoXBool', {xboolExp,true}), + + roundtrip('NT', {os,"kalle"}), + roundtrip('Exp', {os,"kalle"}), + roundtrip('NTNT', {os,"kalle"}), + roundtrip('NTExp', {os,"kalle"}), + roundtrip('ExpNT', {os,"kalle"}), + roundtrip('ExpExp', {os,"kalle"}), + roundtrip('XNTNT', {os,"kalle"}), + roundtrip('XNTExp', {os,"kalle"}), + roundtrip('XExpNT', {os,"kalle"}), + roundtrip('XExpExp', {os,"kalle"}), ok. +roundtrip(Type, Value) -> + {ok,Encoded} = 'ChoExternal':encode(Type, Value), + {ok,Value} = 'ChoExternal':decode(Type, Encoded), + ok. diff --git a/lib/asn1/test/testChoRecursive.erl b/lib/asn1/test/testChoRecursive.erl index 22be26cbce..ee26d124a9 100644 --- a/lib/asn1/test/testChoRecursive.erl +++ b/lib/asn1/test/testChoRecursive.erl @@ -28,38 +28,21 @@ -record('ChoRec2_something',{a, b, c}). recursive(_Rules) -> - - ?line {ok,Bytes11} = asn1_wrapper:encode('ChoRecursive','ChoRec',{'ChoRec',{something, - #'ChoRec_something'{a = 77, - b = "some octets here", - c = {'ChoRec',{nothing,'NULL'}}}}}), - ?line {ok,{something,{'ChoRec_something',77,"some octets here",{nothing,'NULL'}}}} = - asn1_wrapper:decode('ChoRecursive','ChoRec',lists:flatten(Bytes11)), - - - ?line {ok,Bytes12} = asn1_wrapper:encode('ChoRecursive','ChoRec',{'ChoRec',{nothing,'NULL'}}), - ?line {ok,{nothing,'NULL'}} = - asn1_wrapper:decode('ChoRecursive','ChoRec',lists:flatten(Bytes12)), - - - - ?line {ok,Bytes21} = - asn1_wrapper:encode('ChoRecursive','ChoRec2',{'ChoRec2', - {something, - #'ChoRec2_something'{a = 77, - b = "some octets here", - c = {'ChoRec2', - {nothing,'NULL'}}}}}), - ?line {ok,{something,{'ChoRec2_something',77,"some octets here",{nothing,'NULL'}}}} = - asn1_wrapper:decode('ChoRecursive','ChoRec2',lists:flatten(Bytes21)), - - - ?line {ok,Bytes22} = - asn1_wrapper:encode('ChoRecursive','ChoRec2',{'ChoRec2',{nothing,'NULL'}}), - ?line {ok,{nothing,'NULL'}} = - asn1_wrapper:decode('ChoRecursive','ChoRec2',lists:flatten(Bytes22)), - - - - + roundtrip('ChoRec', + {something, + #'ChoRec_something'{a = 77, + b = "some octets here", + c = {nothing,'NULL'}}}), + roundtrip('ChoRec', {nothing,'NULL'}), + roundtrip('ChoRec2', + {something, + #'ChoRec2_something'{a = 77, + b = "some octets here", + c = {nothing,'NULL'}}}), + roundtrip('ChoRec2', {nothing,'NULL'}), + ok. + +roundtrip(Type, Value) -> + {ok,Encoded} = 'ChoRecursive':encode(Type, Value), + {ok,Value} = 'ChoRecursive':decode(Type, Encoded), ok. diff --git a/lib/asn1/test/testCompactBitString.erl b/lib/asn1/test/testCompactBitString.erl index db102a3bda..96d9f0fdcb 100644 --- a/lib/asn1/test/testCompactBitString.erl +++ b/lib/asn1/test/testCompactBitString.erl @@ -22,240 +22,132 @@ -export([compact_bit_string/1, bit_string_unnamed/1,otp_4869/1, ticket_7734/1]). --include_lib("test_server/include/test_server.hrl"). - compact_bit_string(Rules) -> %%========================================================== %% Bs1 ::= BIT STRING %%========================================================== - ?line {ok,Bytes1} = asn1_wrapper:encode('PrimStrings','Bs1',0), - ?line {ok,{0,<<>>}} = - asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes1)), - - ?line {ok,Bytes2} = asn1_wrapper:encode('PrimStrings','Bs1',4), - ?line {ok,{5,<<32>>}} = - asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes2)), - - ?line {ok,Bytes3} = asn1_wrapper:encode('PrimStrings','Bs1',15), - ?line {ok,{4,<<240>>}} = - asn1_wrapper:decode('PrimStrings','Bs1', - lists:flatten(Bytes3)), - - ?line {ok,Bytes4} = asn1_wrapper:encode('PrimStrings','Bs1',255), - ?line {ok,{0,<<255>>}} = - asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes4)), - - ?line {ok,Bytes5} = asn1_wrapper:encode('PrimStrings','Bs1',256), - ?line {ok,{7,<<0,128>>}} = - asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes5)), - - ?line {ok,Bytes6} = asn1_wrapper:encode('PrimStrings','Bs1',257), - ?line {ok,{7,<<128,128>>}} = - asn1_wrapper:decode('PrimStrings','Bs1', - lists:flatten(Bytes6)), - - ?line {ok,Bytes7} = asn1_wrapper:encode('PrimStrings','Bs1',444), - ?line {ok,{7,<<61,128>>}} = - asn1_wrapper:decode('PrimStrings','Bs1', - lists:flatten(Bytes7)), - - ?line {ok,Bytes8} = asn1_wrapper:encode('PrimStrings','Bs1', - 12345678901234567890), - ?line {ok,_} = asn1_wrapper:decode('PrimStrings','Bs1', - lists:flatten(Bytes8)), - -%% Removed due to beam cannot handle this big integers -%% Bs1_1 = 123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890, -%% ?line {ok,Bytes9} = asn1_wrapper:encode('PrimStrings','Bs1',Bs1_1), -%% ?line {ok,_} = asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes9)), - -%% Bs1_2 = 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890, -%% ?line {ok,Bytes10} = asn1_wrapper:encode('PrimStrings','Bs1',Bs1_2), -%% ?line {ok,_} = asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes10)), - - ?line {ok,Bytes11} = asn1_wrapper:encode('PrimStrings','Bs1', - [1,1,1,1,1,1,1,1]), - ?line {ok,{0,<<255>>}} = asn1_wrapper:decode('PrimStrings','Bs1', - lists:flatten(Bytes11)), - - ?line {ok,Bytes12} = asn1_wrapper:encode('PrimStrings', - 'Bs1', - [0,1,0,0,1,0]), - ?line {ok,{2,<<72>>}} = - asn1_wrapper:decode('PrimStrings','Bs1', - lists:flatten(Bytes12)), - - ?line {ok,Bytes13} = - asn1_wrapper:encode('PrimStrings', 'Bs1', - [1,0,0,0,0,0,0,0,0]), - ?line {ok,{7,<<128,0>>}} = - asn1_wrapper:decode('PrimStrings','Bs1', - lists:flatten(Bytes13)), - - - ?line {ok,Bytes14} = - asn1_wrapper:encode('PrimStrings','Bs1', - [0,1,0,0,1,0,1,1,1,1,1,0,0,0,1,0,0,1,1]), - ?line {ok,{5,<<75,226,96>>}} = - asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes14)), - - - ?line case asn1_wrapper:erule(Rules) of - ber -> - ?line Bytes15 = [35,8,3,2,0,73,3,2,4,32], - ?line {ok,{4,<<73,32>>}} = - asn1_wrapper:decode('PrimStrings','Bs1', - lists:flatten(Bytes15)), - - ?line Bytes16 = [35,9,3,2,0,234,3,3,7,156,0], - ?line {ok,{7,<<234,156,0>>}} = - asn1_wrapper:decode('PrimStrings','Bs1', - lists:flatten(Bytes16)), - - ?line Bytes17 = [35,128,3,2,0,73,3,2,4,32,0,0], - ?line {ok,{4,<<73,32>>}} = - asn1_wrapper:decode('PrimStrings','Bs1', - lists:flatten(Bytes17)), - - ?line Bytes18 = [35,128,3,2,0,234,3,3,7,156,0,0,0], - ?line {ok,{7,<<234,156,0>>}} = - asn1_wrapper:decode('PrimStrings','Bs1', - lists:flatten(Bytes18)), - ok; - - per -> - ok - end, + roundtrip('Bs1', 0, {0,<<>>}), + roundtrip('Bs1', 4, {5,<<2#00100000>>}), + roundtrip('Bs1', 15, {4,<<2#11110000>>}), + roundtrip('Bs1', 255, {0,<<2#11111111>>}), + roundtrip('Bs1', 256, {7,<<16#00,16#80>>}), + roundtrip('Bs1', 257, {7,<<16#80,16#80>>}), + roundtrip('Bs1', 444, {7,<<16#3D,16#80>>}), + roundtrip('Bs1', 12345678901234567890, + {0,<<75,80,248,215,49,149,42,213>>}), + + roundtrip('Bs1', [1,1,1,1,1,1,1,1], {0,<<255>>}), + roundtrip('Bs1', [0,1,0,0,1,0], {2,<<16#48>>}), + roundtrip('Bs1', [1,0,0,0,0,0,0,0,0], {7,<<16#80,0>>}), + roundtrip('Bs1', [0,1,0,0,1,0,1,1,1,1,1,0,0,0,1,0,0,1,1], + {5,<<75,226,96>>}), - %% The following case to test OTP-4200 - ?line {ok,Bytes19} = - asn1_wrapper:encode('PrimStrings','Bs1',{0,<<0,0,1,1>>}), - ?line {ok,{0,<<0,0,1,1>>}} = - asn1_wrapper:decode('PrimStrings','Bs1',lists:flatten(Bytes19)), + case Rules of + ber -> + {ok,{4,<<73,32>>}} = + 'PrimStrings':decode('Bs1', <<35,8,3,2,0,73,3,2,4,32>>), + {ok,{7,<<234,156,0>>}} = + 'PrimStrings':decode('Bs1', <<35,9,3,2,0,234,3,3,7,156,0>>), + {ok,{4,<<73,32>>}} = + 'PrimStrings':decode('Bs1', <<35,128,3,2,0,73,3,2,4,32,0,0>>), + {ok,{7,<<234,156,0>>}} = + 'PrimStrings':decode('Bs1', + <<35,128,3,2,0,234,3,3,7,156,0,0,0>>); + _ -> + ok + end, + + %% Test OTP-4200 + roundtrip('Bs1', {0,<<0,0,1,1>>}), %%========================================================== %% Bs2 ::= BIT STRING {su(0), mo(1), tu(2), we(3), th(4), fr(5), sa(6) } (SIZE (7)) %%========================================================== - - ?line {ok,Bytes21} = asn1_wrapper:encode('PrimStrings','Bs2',[mo,tu,fr]), - ?line {ok,[mo,tu,fr]} = asn1_wrapper:decode('PrimStrings','Bs2',lists:flatten(Bytes21)), - - ?line {ok,Bytes22} = asn1_wrapper:encode('PrimStrings','Bs2',[0,1,1,0,0,1,0]), - ?line {ok,[mo,tu,fr]} = asn1_wrapper:decode('PrimStrings','Bs2',lists:flatten(Bytes22)), - - % ?line case asn1_wrapper:erule(Rules) of -% ber -> -% ?line {ok,[mo,tu,fr,su,mo,th]} = -% asn1_wrapper:decode('PrimStrings','Bs2',[35,8,3,2,1,100,3,2,2,200]), - -% ?line {ok,[mo,tu,fr,su,mo,th]} = -% asn1_wrapper:decode('PrimStrings','Bs2',[35,128,3,2,1,100,3,2,2,200,0,0]), -% ok; - -% per -> -% ok -% end, - - + + roundtrip('Bs2', [mo,tu,fr]), + roundtrip('Bs2', [0,1,1,0,0,1,0], [mo,tu,fr]), %%========================================================== %% Bs3 ::= BIT STRING {su(0), mo(1), tu(2), we(3), th(4), fr(5), sa(6) } (SIZE (1..7)) %%========================================================== - ?line {ok,Bytes31} = asn1_wrapper:encode('PrimStrings','Bs3',[mo,tu,fr]), - ?line {ok,[mo,tu,fr]} = asn1_wrapper:decode('PrimStrings','Bs3',lists:flatten(Bytes31)), - - ?line {ok,Bytes32} = asn1_wrapper:encode('PrimStrings','Bs3',[0,1,1,0,0,1,0]), - ?line {ok,[mo,tu,fr]} = asn1_wrapper:decode('PrimStrings','Bs3',lists:flatten(Bytes32)), - - + roundtrip('Bs3', [mo,tu,fr]), + roundtrip('Bs3', [0,1,1,0,0,1,0], [mo,tu,fr]), %%========================================================== %% BsPri ::= [PRIVATE 61] BIT STRING %%========================================================== - - ?line {ok,Bytes41} = asn1_wrapper:encode('PrimStrings','BsPri',45), - ?line {ok,{2,<<180>>}} = - asn1_wrapper:decode('PrimStrings','BsPri',lists:flatten(Bytes41)), - - ?line {ok,Bytes42} = asn1_wrapper:encode('PrimStrings','BsPri',211), - ?line {ok,{0,<<203>>}} = - asn1_wrapper:decode('PrimStrings','BsPri',lists:flatten(Bytes42)), - - ?line case asn1_wrapper:erule(Rules) of - ber -> - ?line {ok,{5,<<75,226,96>>}} = - asn1_wrapper:decode('PrimStrings','BsPri', - [223,61,4,5,75,226,96]), - - ?line {ok,{5,<<75,226,96>>}} = - asn1_wrapper:decode('PrimStrings','BsPri', - [255,61,128,3,4,5,75,226,96,0,0]), - - ?line {ok,{5,<<75,226,96>>}} = - asn1_wrapper:decode('PrimStrings','BsPri', - [255,61,9,3,2,0,75,3,3,5,226,96]), - - ?line {ok,{5,<<75,226,96>>}} = - asn1_wrapper:decode('PrimStrings','BsPri', - [255,61,128,3,2,0,75,3,3,5,226,96,0,0]), - ok; - - per -> - ok - end, - + + roundtrip('BsPri', 45, {2,<<180>>}), + roundtrip('BsPri', 211, {0,<<203>>}), + + case Rules of + ber -> + {ok,{5,<<75,226,96>>}} = + 'PrimStrings':decode('BsPri', + <<223,61,4,5,75,226,96>>), + + {ok,{5,<<75,226,96>>}} = + 'PrimStrings':decode('BsPri', + <<255,61,128,3,4,5,75,226,96,0,0>>), + + {ok,{5,<<75,226,96>>}} = + 'PrimStrings':decode('BsPri', + <<255,61,9,3,2,0,75,3,3,5,226,96>>), + + {ok,{5,<<75,226,96>>}} = + 'PrimStrings':decode('BsPri', + <<255,61,128,3,2,0,75,3,3,5,226,96,0,0>>), + ok; + _ -> + ok + end, %%========================================================== %% BsExpPri ::= [PRIVATE 61] EXPLICIT BIT STRING %%========================================================== - - ?line {ok,Bytes51} = asn1_wrapper:encode('PrimStrings','BsExpPri',45), - ?line {ok,{2,<<180>>}} = - asn1_wrapper:decode('PrimStrings','BsExpPri',lists:flatten(Bytes51)), - - ?line {ok,Bytes52} = asn1_wrapper:encode('PrimStrings','BsExpPri',211), - ?line {ok,{0,<<203>>}} = - asn1_wrapper:decode('PrimStrings','BsExpPri',lists:flatten(Bytes52)), - - ?line case asn1_wrapper:erule(Rules) of - ber -> - ?line {ok,{5,<<75,226,96>>}} = - asn1_wrapper:decode('PrimStrings','BsExpPri',[255,61,6,3,4,5,75,226,96]), - ok; - - per -> - ok - end, - - ok. -ticket_7734(per) -> - ?line BS = {0,list_to_binary(lists:duplicate(128,0))}, - ?line {ok,BSEnc} = asn1_wrapper:encode('PrimStrings','BS1024',BS), - ?line {ok,BS} = asn1_wrapper:decode('PrimStrings','BS1024',BSEnc). + roundtrip('BsExpPri', 45, {2,<<180>>}), + roundtrip('BsExpPri', 211, {0,<<203>>}), -bit_string_unnamed(Rules) -> - case asn1_wrapper:erule(Rules) of + case Rules of ber -> - ok; - per -> - ?line {ok,Bytes1} = - asn1_wrapper:encode('PrimStrings','TransportLayerAddress', - [0,1,1,0]), - ?line {ok,{4,<<96>>}} = - asn1_wrapper:decode('PrimStrings','TransportLayerAddress', - lists:flatten(Bytes1)) - end. + {ok,{5,<<75,226,96>>}} = + 'PrimStrings':decode('BsExpPri', <<255,61,6,3,4,5,75,226,96>>); + _ -> + ok + end, -otp_4869(per) -> - ?line Val1={'IP',[0],{0,<<62,235,90,50,0,0,0,0,0,0,0,0,0,0,0,0>>},asn1_NOVALUE}, - ?line Val2 = {'IP',[0],[0,0,1,1,1,1,1,0,1,1,1,0,1,0,1,1,0,1,0,1,1,0,1,0,0,0,1,1,0,0,1,0] ++ lists:duplicate(128 - 32,0),asn1_NOVALUE}, + ok. + +ticket_7734(_) -> + BS = {0,list_to_binary(lists:duplicate(128, 0))}, + roundtrip('BS1024', BS). - ?line {ok,Bytes1} = asn1_wrapper:encode('Constraints','IP',Val1), - ?line {ok,Bytes1} = asn1_wrapper:encode('Constraints','IP',Val2); +bit_string_unnamed(_Rules) -> + roundtrip('TransportLayerAddress', [0,1,1,0], {4,<<96>>}). + +otp_4869(per) -> + Val1 = {'IP',[0],{0,<<62,235,90,50,0,0,0,0,0,0,0,0,0,0,0,0>>},asn1_NOVALUE}, + Val2 = {'IP',[0],[0,0,1,1,1,1,1,0,1,1,1,0,1,0,1,1,0,1,0,1,1,0, + 1,0,0,0,1,1,0,0,1,0] ++ + lists:duplicate(128 - 32, 0),asn1_NOVALUE}, + {ok,Encoded} = 'Constraints':encode('IP', Val1), + {ok,Encoded} = 'Constraints':encode('IP', Val2), + ok; otp_4869(_) -> ok. + +roundtrip(Type, Val) -> + roundtrip_1('PrimStrings', Type, Val, Val). + +roundtrip(Type, Val1, Val2) -> + roundtrip_1('PrimStrings', Type, Val1, Val2). + +roundtrip_1(Mod, Type, In, Out) -> + {ok,Encoded} = Mod:encode(Type, In), + {ok,Out} = Mod:decode(Type, Encoded), + ok. diff --git a/lib/asn1/test/testConstraints.erl b/lib/asn1/test/testConstraints.erl index 543c106e8a..c8d9008641 100644 --- a/lib/asn1/test/testConstraints.erl +++ b/lib/asn1/test/testConstraints.erl @@ -30,59 +30,20 @@ int_constraints(Rules) -> %% SingleValue ::= INTEGER (1) %%========================================================== - ?line {ok,Bytes1} = asn1_wrapper:encode('Constraints','SingleValue',1), - ?line {ok,1} = asn1_wrapper:decode('Constraints','SingleValue', - lists:flatten(Bytes1)), - - ?line case asn1_wrapper:erule(Rules) of - ber -> - ?line {ok,Bytes2} = - asn1_wrapper:encode('Constraints','SingleValue',0), - ?line {error,{asn1,{integer_range,_,0}}} = - asn1_wrapper:decode('Constraints','SingleValue', - lists:flatten(Bytes2)), - ?line {ok,Bytes3} = - asn1_wrapper:encode('Constraints','SingleValue',1000), - ?line {error,{asn1,{integer_range,_,1000}}} = - asn1_wrapper:decode('Constraints','SingleValue', - lists:flatten(Bytes3)); - per -> - ?line {error,_Reason1} = - asn1_wrapper:encode('Constraints','SingleValue',0), - ?line {error,_Reason2} = - asn1_wrapper:encode('Constraints','SingleValue',1000) - end, + range_error(Rules, 'SingleValue', 0), + roundtrip('SingleValue', 1), + range_error(Rules, 'SingleValue', 2), + range_error(Rules, 'SingleValue', 1000), %%========================================================== %% SingleValue2 ::= INTEGER (1..20) %%========================================================== - ?line {ok,Bytes4} = asn1_wrapper:encode('Constraints','SingleValue2',1), - ?line {ok,1} = asn1_wrapper:decode('Constraints','SingleValue2', - lists:flatten(Bytes4)), - - ?line {ok,Bytes5} = asn1_wrapper:encode('Constraints','SingleValue2',20), - ?line {ok,20} = asn1_wrapper:decode('Constraints','SingleValue2', - lists:flatten(Bytes5)), - - ?line case asn1_wrapper:erule(Rules) of - ber -> - ?line {ok,Bytes6} = - asn1_wrapper:encode('Constraints','SingleValue2',0), - ?line {error,{asn1,{integer_range,{1,20},0}}} = - asn1_wrapper:decode('Constraints','SingleValue2', - lists:flatten(Bytes6)), - ?line {ok,Bytes7} = - asn1_wrapper:encode('Constraints','SingleValue2',21), - ?line {error,{asn1,{integer_range,{1,20},21}}} = - asn1_wrapper:decode('Constraints','SingleValue2', - lists:flatten(Bytes7)); - per -> - ?line {error,_Reason3} = - asn1_wrapper:encode('Constraints','SingleValue',0), - ?line {error,_Reason4} = - asn1_wrapper:encode('Constraints','SingleValue',1000) - end, + range_error(Rules, 'SingleValue2', 0), + roundtrip('SingleValue2', 1), + roundtrip('SingleValue2', 20), + range_error(Rules, 'SingleValue2', 21), + range_error(Rules, 'SingleValue2', 1000), %%========================================================== %% SingleValue3 ::= INTEGER (Predefined | 5 | 10) @@ -90,136 +51,106 @@ int_constraints(Rules) -> %% where one value is predefined. %%========================================================== - ?line {ok,BytesSV3} = asn1_wrapper:encode('Constraints','SingleValue3',1), - ?line {ok,1} = asn1_wrapper:decode('Constraints','SingleValue3', - lists:flatten(BytesSV3)), - ?line {ok,BytesSV3_2} = asn1_wrapper:encode('Constraints','SingleValue3',5), - ?line {ok,5} = asn1_wrapper:decode('Constraints','SingleValue3', - lists:flatten(BytesSV3_2)), - ?line {ok,BytesSV3_3} = asn1_wrapper:encode('Constraints','SingleValue3',10), - ?line {ok,10} = asn1_wrapper:decode('Constraints','SingleValue3', - lists:flatten(BytesSV3_3)), + roundtrip('SingleValue3', 1), + roundtrip('SingleValue3', 5), + roundtrip('SingleValue3', 10), %%========================================================== %% Range2to19 ::= INTEGER (1<..<20) %%========================================================== - ?line {ok,Bytes8} = asn1_wrapper:encode('Constraints','Range2to19',2), - ?line {ok,2} = asn1_wrapper:decode('Constraints','Range2to19',lists:flatten(Bytes8)), - - ?line {ok,Bytes9} = asn1_wrapper:encode('Constraints','Range2to19',19), - ?line {ok,19} = asn1_wrapper:decode('Constraints','Range2to19',lists:flatten(Bytes9)), - - ?line case asn1_wrapper:erule(Rules) of - ber -> - ?line {ok,Bytes10} = - asn1_wrapper:encode('Constraints','Range2to19',1), - ?line {error,{asn1,{integer_range,{2,19},1}}} = - asn1_wrapper:decode('Constraints','Range2to19', - lists:flatten(Bytes10)), - ?line {ok,Bytes11} = - asn1_wrapper:encode('Constraints','Range2to19',20), - ?line {error,{asn1,{integer_range,{2,19},20}}} = - asn1_wrapper:decode('Constraints','Range2to19', - lists:flatten(Bytes11)); - per -> - ?line {error,_Reason5} = - asn1_wrapper:encode('Constraints','Range2to19',1), - ?line {error,_Reason6} = - asn1_wrapper:encode('Constraints','Range2to19',20) - end, + range_error(Rules, 'Range2to19', 1), + roundtrip('Range2to19', 2), + roundtrip('Range2to19', 19), + range_error(Rules, 'Range2to19', 20), %%========================================================== %% Tests for Range above 16^4 up to maximum supported by asn1 assuming the %% octet length field is encoded on max 8 bits %%========================================================== LastNumWithoutLengthEncoding = 65536, - ?line {ok,BytesFoo} = asn1_wrapper:encode('Constraints','Range256to65536', - LastNumWithoutLengthEncoding), - ?line {ok,LastNumWithoutLengthEncoding} = - asn1_wrapper:decode('Constraints','Range256to65536',lists:flatten(BytesFoo)), + roundtrip('Range256to65536', LastNumWithoutLengthEncoding), FirstNumWithLengthEncoding = 65537, - ?line {ok,BytesBar} = asn1_wrapper:encode('LargeConstraints','RangeMax', - FirstNumWithLengthEncoding), - ?line {ok,FirstNumWithLengthEncoding} = - asn1_wrapper:decode('LargeConstraints','RangeMax',lists:flatten(BytesBar)), + roundtrip('LargeConstraints', 'RangeMax', FirstNumWithLengthEncoding), FirstNumOver16_6 = 16777217, - ?line {ok, BytesBaz} = - asn1_wrapper:encode('LargeConstraints','RangeMax', FirstNumOver16_6), - ?line {ok, FirstNumOver16_6} = - asn1_wrapper:decode('LargeConstraints','RangeMax',lists:flatten(BytesBaz)), + roundtrip('LargeConstraints', 'RangeMax', FirstNumOver16_6), FirstNumOver16_8 = 4294967297, - ?line {ok, BytesQux} = - asn1_wrapper:encode('LargeConstraints','RangeMax', FirstNumOver16_8), - ?line {ok, FirstNumOver16_8} = - asn1_wrapper:decode('LargeConstraints','RangeMax',lists:flatten(BytesQux)), + roundtrip('LargeConstraints', 'RangeMax', FirstNumOver16_8), FirstNumOver16_10 = 1099511627776, - ?line {ok, BytesBur} = - asn1_wrapper:encode('LargeConstraints','RangeMax', FirstNumOver16_10), - ?line {ok, FirstNumOver16_10} = - asn1_wrapper:decode('LargeConstraints','RangeMax',lists:flatten(BytesBur)), + roundtrip('LargeConstraints', 'RangeMax', FirstNumOver16_10), FirstNumOver16_10 = 1099511627776, - ?line {ok, BytesBur} = - asn1_wrapper:encode('LargeConstraints','RangeMax', FirstNumOver16_10), - ?line {ok, FirstNumOver16_10} = - asn1_wrapper:decode('LargeConstraints','RangeMax',lists:flatten(BytesBur)), + roundtrip('LargeConstraints', 'RangeMax', FirstNumOver16_10), HalfMax = 1 bsl (128*8), - ?line {ok, BytesHalfMax} = - asn1_wrapper:encode('LargeConstraints','RangeMax', HalfMax), - ?line {ok, HalfMax} = - asn1_wrapper:decode('LargeConstraints','RangeMax',lists:flatten(BytesHalfMax)), + roundtrip('LargeConstraints', 'RangeMax', HalfMax), Max = 1 bsl (255*8), - ?line {ok, BytesMax} = - asn1_wrapper:encode('LargeConstraints','RangeMax', Max), - ?line {ok, Max} = - asn1_wrapper:decode('LargeConstraints','RangeMax',lists:flatten(BytesMax)), + roundtrip('LargeConstraints', 'RangeMax', Max), %% Random number within longlong range LongLong = 12672809400538808320, - ?line {ok, BytesLongLong} = - asn1_wrapper:encode('Constraints','LongLong', LongLong), - ?line {ok, LongLong} = - asn1_wrapper:decode('Constraints','LongLong',lists:flatten(BytesLongLong)), + roundtrip('LongLong', LongLong), %%========================================================== %% Constraint Combinations (Duboisson p. 285) %% I ::= INTEGER (0|15..269) %%========================================================== - ?line {ok,Bytes12} = asn1_wrapper:encode('Constraints','I',0), - ?line {ok,0} = asn1_wrapper:decode('Constraints','I',Bytes12), - ?line {ok,Bytes13} = asn1_wrapper:encode('Constraints','I',20), - ?line {ok,20} = asn1_wrapper:decode('Constraints','I',Bytes13), + range_error(Rules, 'I', -1), + roundtrip('I', 0), + roundtrip('I', 15), + roundtrip('I', 20), + roundtrip('I', 269), + range_error(Rules, 'I', 270), %%========================================================== %% Constraint Combinations (Duboisson p. 285) %% X1 ::= INTEGER (1..4|8|10|20) %%========================================================== - ?line {ok,Bytes14} = asn1_wrapper:encode('Constraints','X1',1), - ?line {ok,1} = asn1_wrapper:decode('Constraints','X1',Bytes14), - ?line {ok,Bytes15} = asn1_wrapper:encode('Constraints','X1',20), - ?line {ok,20} = asn1_wrapper:decode('Constraints','X1',Bytes15), + range_error(Rules, 'X1', 0), + roundtrip('X1', 1), + roundtrip('X1', 4), + roundtrip('X1', 8), + roundtrip('X1', 10), + roundtrip('X1', 20), + range_error(Rules, 'X1', 21), + %%========================================================== %% SIZE Constraint (Duboisson p. 268) %% T ::= IA5String (SIZE (1|2, ..., SIZE (1|2|3))) %% T2 ::= IA5String (SIZE (1|2, ..., 3)) %%========================================================== - ?line {ok,Bytes16} = asn1_wrapper:encode('Constraints','T',"IA"), - ?line {ok,"IA"} = asn1_wrapper:decode('Constraints','T',Bytes16), - ?line {ok,Bytes17} = asn1_wrapper:encode('Constraints','T2',"IA"), - ?line {ok,"IA"} = asn1_wrapper:decode('Constraints','T2',Bytes17). - + roundtrip('T', "IA"), + roundtrip('T2', "IA"). refed_NNL_name(_Erule) -> ?line {ok,_} = asn1_wrapper:encode('Constraints','AnotherThing',fred), ?line {error,_Reason} = asn1_wrapper:encode('Constraints','AnotherThing',fred3). + +roundtrip(Type, Value) -> + roundtrip('Constraints', Type, Value). + +roundtrip(Module, Type, Value) -> + {ok,Encoded} = Module:encode(Type, Value), + {ok,Value} = Module:decode(Type, Encoded), + ok. + +range_error(ber, Type, Value) -> + %% BER: Values outside the effective range should be rejected + %% on decode. + {ok,Encoded} = 'Constraints':encode(Type, Value), + {error,{asn1,{integer_range,_,_}}} = 'Constraints':decode(Type, Encoded), + ok; +range_error(Per, Type, Value) when Per =:= per; Per =:= uper -> + %% (U)PER: Values outside the effective range should be rejected + %% on encode. + {error,_} = 'Constraints':encode(Type, Value), + ok. diff --git a/lib/asn1/test/testDeepTConstr.erl b/lib/asn1/test/testDeepTConstr.erl index aa3afbb58f..3df7bcbaa0 100644 --- a/lib/asn1/test/testDeepTConstr.erl +++ b/lib/asn1/test/testDeepTConstr.erl @@ -26,21 +26,19 @@ -include_lib("test_server/include/test_server.hrl"). main(_Erule) -> - Val1 = {'FilterItem', - {substrings, - {'FilterItem_substrings', - {2,6}, - [{initial,"SE"}, - {any,"DK"}, - {final,"N"}]}}}, + Val1 = {substrings, + {'FilterItem_substrings', + {2,6}, + [{initial,"SE"}, + {any,"DK"}, + {final,"N"}]}}, - Val2 = {'FilterItem', - {substrings, - {'FilterItem_substrings', - {2,6}, - [{initial,"SE"}, - {any,"DK"}, - {final,"NO"}]}}}, + Val2 = {substrings, + {'FilterItem_substrings', + {2,6}, + [{initial,"SE"}, + {any,"DK"}, + {final,"NO"}]}}, ?line {ok,Bytes1} = asn1_wrapper:encode('TConstrChoice','FilterItem',Val1), diff --git a/lib/asn1/test/testEnumExt.erl b/lib/asn1/test/testEnumExt.erl index bb975a1d13..0811f20571 100644 --- a/lib/asn1/test/testEnumExt.erl +++ b/lib/asn1/test/testEnumExt.erl @@ -25,58 +25,41 @@ main(Rule) when Rule =:= per; Rule =:= uper -> io:format("main(~p)~n",[Rule]), - B32=[32],B64=[64], + %% ENUMERATED with extensionmark (value is in root set) - ?line {ok,B32} = asn1_wrapper:encode('EnumExt','Ext',red), - ?line {ok,red} = asn1_wrapper:decode('EnumExt','Ext',B32), + B32 = <<32>>, + B32 = roundtrip('Ext', red), %% ENUMERATED with extensionmark (value is an extensionvalue) - ?line {ok,Or} = asn1_wrapper:encode('EnumExt','Ext1',orange), - ?line {ok,orange} = asn1_wrapper:decode('EnumExt','Ext1',Or), + Or = roundtrip('Ext1', orange), %% unknown extensionvalue - ?line {ok,{asn1_enum,0}} = asn1_wrapper:decode('EnumExt','Ext',Or), - + {ok,{asn1_enum,0}} = asn1_wrapper:decode('EnumExt','Ext',Or), %% ENUMERATED no extensionmark - ?line {ok,B64} = asn1_wrapper:encode('EnumExt','Noext',red), - ?line {ok,red} = asn1_wrapper:decode('EnumExt','Noext',B64), + B64 = <<64>>, + B64 = roundtrip('Noext', red), ok; main(ber) -> io:format("main(ber)~n",[]), %% ENUMERATED with extensionmark (value is in root set) - ?line {ok,Bytes1} = asn1_wrapper:encode('EnumExt','Ext',red), - ?line {ok,red} = asn1_wrapper:decode('EnumExt','Ext',lists:flatten(Bytes1)), + roundtrip('Ext', red), %% value is an extensionvalue - ?line {ok,Bytes1_1} = asn1_wrapper:encode('EnumExt','Ext1',orange), - ?line {ok,{asn1_enum,7}} = asn1_wrapper:decode('EnumExt','Ext',lists:flatten(Bytes1_1)), -%% ?line {ok,Bytes1_1} = asn1_wrapper:encode('EnumExt','Ext',{asn1_enum,7}), + {ok,Bytes1_1} = asn1_wrapper:encode('EnumExt','Ext1',orange), + {ok,{asn1_enum,7}} = asn1_wrapper:decode('EnumExt','Ext',lists:flatten(Bytes1_1)), - %% ENUMERATED no extensionmark - ?line {ok,Bytes2} = asn1_wrapper:encode('EnumExt','Noext',red), - ?line {ok,red} = asn1_wrapper:decode('EnumExt','Noext',lists:flatten(Bytes2)), + %% ENUMERATED no extensionmark + roundtrip('Noext', red), ?line {error,{asn1,_}} = (catch asn1_wrapper:encode('EnumExt','Noext',orange)), -%% ?line {error,{asn1,_}} = (catch asn1_wrapper:encode('EnumExt','Noext',{asn1_enum,7})), - ok, %% ENUMERATED with atom 'com' - ?line {ok,Bytes3} = asn1_wrapper:encode('EnumExt','Globalstate',{'Globalstate',preop}), - ?line {ok,preop} = asn1_wrapper:decode('EnumExt','Globalstate', - lists:flatten(Bytes3)), - ?line {ok,Bytes4} = asn1_wrapper:encode('EnumExt','Globalstate',{'Globalstate',com}), - ?line {ok,com} = asn1_wrapper:decode('EnumExt','Globalstate', - lists:flatten(Bytes4)). - - - - - - - - - - - + roundtrip('Globalstate', preop), + roundtrip('Globalstate', com), + ok. +roundtrip(Type, Value) -> + {ok,Encoded} = 'EnumExt':encode(Type, Value), + {ok,Value} = 'EnumExt':decode(Type, Encoded), + Encoded. diff --git a/lib/asn1/test/testMergeCompile.erl b/lib/asn1/test/testMergeCompile.erl index d63df28c31..8ef7ba3458 100644 --- a/lib/asn1/test/testMergeCompile.erl +++ b/lib/asn1/test/testMergeCompile.erl @@ -37,7 +37,7 @@ main(Erule) -> %% test of RANAP.set.asn1 ?line _PIEVal = [{'ProtocolIE-Field',4,ignore,{'Cause',{radioNetwork,{'CauseRadioNetwork','rab-pre-empted'}}}}], - ?line PIEVal2 = [{'ProtocolIE-Field',4,ignore,{'Cause',{radioNetwork,'rab-pre-empted'}}}], + PIEVal2 = [{'ProtocolIE-Field',4,ignore,{radioNetwork,'rab-pre-empted'}}], ?line _PEVal = [{'ProtocolExtensionField',[0]}], %% ?line EncVal = asn1rt_per_v1:encode_integer([],100), ?line EncVal = diff --git a/lib/asn1/test/testParameterizedInfObj.erl b/lib/asn1/test/testParameterizedInfObj.erl index 6f53595132..17108e285b 100644 --- a/lib/asn1/test/testParameterizedInfObj.erl +++ b/lib/asn1/test/testParameterizedInfObj.erl @@ -86,7 +86,7 @@ main(Erule) -> ranap(_Erule) -> - ?line PIEVal2 = [{'ProtocolIE-Field',4,ignore,{'Cause',{radioNetwork,'rab-pre-empted'}}}], + PIEVal2 = [{'ProtocolIE-Field',4,ignore,{radioNetwork,'rab-pre-empted'}}], ?line Val2 = #'InitiatingMessage'{procedureCode=1, criticality=ignore, diff --git a/lib/asn1/test/testPrimStrings.erl b/lib/asn1/test/testPrimStrings.erl index 9a640a2cb1..263d9e5ed2 100644 --- a/lib/asn1/test/testPrimStrings.erl +++ b/lib/asn1/test/testPrimStrings.erl @@ -372,6 +372,11 @@ octet_string(Rules) -> end, fragmented_octet_string(Rules), + + S255 = lists:seq(1, 255), + FixedStrings = {'OsFixedStrings',true,"","1","12","345",true, + S255,[$a|S255],[$a,$b|S255],397}, + roundtrip('OsFixedStrings', FixedStrings), ok. fragmented_octet_string(Erules) -> diff --git a/lib/asn1/test/testSeqExtension.erl b/lib/asn1/test/testSeqExtension.erl index 7c77ab87e9..1128d9a7c3 100644 --- a/lib/asn1/test/testSeqExtension.erl +++ b/lib/asn1/test/testSeqExtension.erl @@ -20,7 +20,7 @@ -module(testSeqExtension). -include("External.hrl"). --export([main/1]). +-export([main/2]). -include_lib("test_server/include/test_server.hrl"). @@ -28,70 +28,73 @@ -record('SeqExt2',{bool, int}). -record('SeqExt3',{bool, int}). -record('SeqExt4',{bool, int}). - - -main(_Rules) -> - - ?line {ok,Bytes11} = - asn1_wrapper:encode('SeqExtension','SeqExt1',#'SeqExt1'{}), - ?line {ok,{'SeqExt1'}} = - asn1_wrapper:decode('SeqExtension','SeqExt1',lists:flatten(Bytes11)), - - ?line {ok,Bytes21} = - asn1_wrapper:encode('SeqExtension','SeqExt2',#'SeqExt2'{bool = true,int = 99}), - ?line {ok,{'SeqExt2',true,99}} = - asn1_wrapper:decode('SeqExtension','SeqExt2',lists:flatten(Bytes21)), - - ?line {ok,Bytes22} = - asn1_wrapper:encode('SeqExtension','SeqExt2',#'SeqExt2'{int = 99,bool = true}), - ?line {ok,{'SeqExt2',true,99}} = - asn1_wrapper:decode('SeqExtension','SeqExt2',lists:flatten(Bytes22)), - - ?line {ok,Bytes31} = - asn1_wrapper:encode('SeqExtension','SeqExt3',#'SeqExt3'{bool = true,int = 99}), - ?line {ok,{'SeqExt3',true,99}} = - asn1_wrapper:decode('SeqExtension','SeqExt3',lists:flatten(Bytes31)), - - ?line {ok,Bytes32} = - asn1_wrapper:encode('SeqExtension','SeqExt3',#'SeqExt3'{int = 99,bool = true}), - ?line {ok,{'SeqExt3',true,99}} = - asn1_wrapper:decode('SeqExtension','SeqExt3',lists:flatten(Bytes32)), - - ?line {ok,Bytes41} = - asn1_wrapper:encode('SeqExtension','SeqExt4',#'SeqExt4'{bool = true,int = 99}), - ?line {ok,{'SeqExt4',true,99}} = - asn1_wrapper:decode('SeqExtension','SeqExt4',lists:flatten(Bytes41)), - - ?line {ok,Bytes42} = - asn1_wrapper:encode('SeqExtension','SeqExt4',#'SeqExt4'{int = 99,bool = true}), - ?line {ok,{'SeqExt4',true,99}} = - asn1_wrapper:decode('SeqExtension','SeqExt4',lists:flatten(Bytes42)), - - - % test of extension , not ready - - ?line {ok,BytesX11} = - asn1_wrapper:encode('SeqExtension','SeqExt1',#'SeqExt1'{}), - ?line {ok,{'SeqExt1'}} = - asn1_wrapper:decode('SeqExtension','SeqExt1',lists:flatten(BytesX11)), - - ?line {ok,BytesX21} = - asn1_wrapper:encode('SeqExtension','SeqExt2',#'SeqExt2'{bool = true,int = 99}), - ?line {ok,{'SeqExt2',true,99}} = - asn1_wrapper:decode('SeqExtension','SeqExt2',lists:flatten(BytesX21)), - - ?line {ok,BytesX22} = - asn1_wrapper:encode('SeqExtension','SeqExt2',#'SeqExt2'{int = 99,bool = true}), - ?line {ok,{'SeqExt2',true,99}} = - asn1_wrapper:decode('SeqExtension','SeqExt2',lists:flatten(BytesX22)), - - - - - +-record('SeqExt5',{name, shoesize}). +-record('SeqExt6',{i1,i2,i3,i4,i5,i6,i7}). +-record('SuperSeq',{s1,s2,s3,s4,s5,s6,i}). + +main(DataDir, Opts) -> + roundtrip('SeqExt1', #'SeqExt1'{}), + + roundtrip('SeqExt2', #'SeqExt2'{bool=true,int=99}), + roundtrip('SeqExt2', #'SeqExt2'{bool=false,int=42}), + + roundtrip('SeqExt3', #'SeqExt3'{bool=true,int=-77777}), + roundtrip('SeqExt3', #'SeqExt3'{bool=false,int=-42000}), + + roundtrip('SeqExt4', #'SeqExt4'{bool=true,int=12345}), + roundtrip('SeqExt4', #'SeqExt4'{bool=false,int=123456}), + + roundtrip('SeqExt5', #'SeqExt5'{name="Arne",shoesize=47}), + + %% Encode a value with this version of the specification. + BigInt = 128638468966, + SuperSeq = #'SuperSeq'{s1=#'SeqExt1'{}, + s2=#'SeqExt2'{bool=true,int=2345}, + s3=#'SeqExt3'{bool=false,int=17}, + s4=#'SeqExt4'{bool=true,int=38739739}, + s5=#'SeqExt5'{name="Arne",shoesize=47}, + s6=#'SeqExt6'{i1=531,i2=601,i3=999, + i4=777,i5=11953, + i6=13553,i7=77777}, + i=BigInt + }, + {ok,SuperSeqEnc} = 'SeqExtension':encode('SuperSeq', SuperSeq), + {ok,SuperSeq} = 'SeqExtension':decode('SuperSeq', SuperSeqEnc), + + %% Remove all extensions from the ASN.1 specification and compile it. + CaseDir = filename:dirname(code:which('SeqExtension')), + Asn1SrcBase = "SeqExtension.asn1", + Asn1SrcFile0 = filename:join(DataDir, Asn1SrcBase), + {ok,Src0} = file:read_file(Asn1SrcFile0), + %% Remove all declarations following "...," up to the end + %% of the SEQUENCE. + Src1 = re:replace(Src0, "[.][.][.],[^}]*", "...\n", + [global,{return,binary}]), + %% Remove the last double bracket group in the SEQUENCE. + Src = re:replace(Src1, ",\\s*\\[\\[.*?\\]\\]\\s*\\}", "\n}", + [global,{return,binary}]), + io:format("~s\n\n", [Src]), + Asn1SrcFile = filename:join(CaseDir, Asn1SrcBase), + ok = file:write_file(Asn1SrcFile, Src), + ok = asn1ct:compile(Asn1SrcFile, + [{i,DataDir},{outdir,CaseDir}|Opts]), + + %% Decode the encoded sequence with the version of the spec + %% with no extensions following the extension marks + %% (except in SeqExt6). The integer 'i' at the end + %% of the sequence must still be the correct integer (otherwise + %% some extension has not been skipped correctly). + {ok,DecodedSuperSeq} = 'SeqExtension':decode('SuperSeq', SuperSeqEnc), + #'SuperSeq'{s1={'SeqExt1'}, + s2=#'SeqExt2'{bool=true,int=2345}, + s3={'SeqExt3'}, + s4={'SeqExt4',true}, + s5={'SeqExt5'}, + s6={'SeqExt6',531,601,999,777,11953}, + i=BigInt} = DecodedSuperSeq, ok. - - - - +roundtrip(Type, Value) -> + {ok,Encoded} = 'SeqExtension':encode(Type, Value), + {ok,Value} = 'SeqExtension':decode(Type, Encoded), + ok. diff --git a/lib/asn1/test/testSetOptional.erl b/lib/asn1/test/testSetOptional.erl index cef90bc843..bb43ff0a96 100644 --- a/lib/asn1/test/testSetOptional.erl +++ b/lib/asn1/test/testSetOptional.erl @@ -21,8 +21,7 @@ -include("External.hrl"). -export([main/1]). --export([ticket_7533/1,decoder/4]). --include_lib("test_server/include/test_server.hrl"). +-export([ticket_7533/1]). -record('SetOpt1',{bool1 = asn1_NOVALUE, int1, set1 = asn1_NOVALUE}). -record('SetOpt1Imp',{bool1 = asn1_NOVALUE, int1, set1 = asn1_NOVALUE}). @@ -36,171 +35,64 @@ -record('SetIn',{boolIn, intIn}). main(_Rules) -> + roundtrip('SetOpt1', + #'SetOpt1'{bool1=true,int1=15, + set1=#'SetIn'{boolIn=true,intIn=66}}), + roundtrip('SetOpt1', #'SetOpt1'{int1=15}), + + roundtrip('SetOpt2', #'SetOpt2'{bool2=true,int2=15, + set2=#'SetIn'{boolIn=true,intIn=66}}), + roundtrip('SetOpt2', #'SetOpt2'{int2=15,bool2=true}), + + roundtrip('SetOpt3', #'SetOpt3'{bool3=true,int3=15, + set3=#'SetIn'{boolIn=true,intIn=66}}), + roundtrip('SetOpt3', #'SetOpt3'{int3=15}), + + roundtrip('SetOpt1Imp', + #'SetOpt1Imp'{bool1=true,int1 = 15, + set1=#'SetIn'{boolIn = true,intIn = 66}}), + roundtrip('SetOpt1Imp', #'SetOpt1Imp'{int1=15}), - ?line {ok,Bytes11} = - asn1_wrapper:encode('SetOptional','SetOpt1',#'SetOpt1'{bool1 = true, - int1 = 15, - set1 = #'SetIn'{boolIn = true, - intIn = 66}}), - ?line {ok,{'SetOpt1',true,15,{'SetIn',true,66}}} = - asn1_wrapper:decode('SetOptional','SetOpt1',lists:flatten(Bytes11)), - - - ?line {ok,Bytes12} = asn1_wrapper:encode('SetOptional','SetOpt1',#'SetOpt1'{int1 = 15}), - ?line {ok,{'SetOpt1',asn1_NOVALUE,15,asn1_NOVALUE}} = - asn1_wrapper:decode('SetOptional','SetOpt1',lists:flatten(Bytes12)), - - - ?line {ok,Bytes21} = - asn1_wrapper:encode('SetOptional','SetOpt2',#'SetOpt2'{bool2 = true, - int2 = 15, - set2 = #'SetIn'{boolIn = true, - intIn = 66}}), - ?line {ok,{'SetOpt2',{'SetIn',true,66},true,15}} = - asn1_wrapper:decode('SetOptional','SetOpt2',lists:flatten(Bytes21)), - - - ?line {ok,Bytes22} = asn1_wrapper:encode('SetOptional','SetOpt2',#'SetOpt2'{int2 = 15, - bool2 = true}), - ?line {ok,{'SetOpt2',asn1_NOVALUE,true,15}} = - asn1_wrapper:decode('SetOptional','SetOpt2',lists:flatten(Bytes22)), - - - - ?line {ok,Bytes31} = - asn1_wrapper:encode('SetOptional','SetOpt3',#'SetOpt3'{bool3 = true, - int3 = 15, - set3 = #'SetIn'{boolIn = true, - intIn = 66}}), - ?line {ok,{'SetOpt3',true,{'SetIn',true,66},15}} = - asn1_wrapper:decode('SetOptional','SetOpt3',lists:flatten(Bytes31)), - - - ?line {ok,Bytes32} = asn1_wrapper:encode('SetOptional','SetOpt3',#'SetOpt3'{int3 = 15}), - ?line {ok,{'SetOpt3',asn1_NOVALUE,asn1_NOVALUE,15}} = - asn1_wrapper:decode('SetOptional','SetOpt3',lists:flatten(Bytes32)), - - - - - - ?line {ok,Bytes41} = - asn1_wrapper:encode('SetOptional','SetOpt1Imp',#'SetOpt1Imp'{bool1 = true, - int1 = 15, - set1 = #'SetIn'{boolIn = true, - intIn = 66}}), - ?line {ok,{'SetOpt1Imp',true,15,{'SetIn',true,66}}} = - asn1_wrapper:decode('SetOptional','SetOpt1Imp',lists:flatten(Bytes41)), - - - ?line {ok,Bytes42} = asn1_wrapper:encode('SetOptional','SetOpt1Imp',#'SetOpt1Imp'{int1 = 15}), - ?line {ok,{'SetOpt1Imp',asn1_NOVALUE,15,asn1_NOVALUE}} = - asn1_wrapper:decode('SetOptional','SetOpt1Imp',lists:flatten(Bytes42)), - - - ?line {ok,Bytes51} = - asn1_wrapper:encode('SetOptional','SetOpt2Imp',#'SetOpt2Imp'{bool2 = true, - int2 = 15, - set2 = #'SetIn'{boolIn = true, - intIn = 66}}), - ?line {ok,{'SetOpt2Imp',{'SetIn',true,66},true,15}} = - asn1_wrapper:decode('SetOptional','SetOpt2Imp',lists:flatten(Bytes51)), - - - ?line {ok,Bytes52} = asn1_wrapper:encode('SetOptional','SetOpt2Imp',#'SetOpt2Imp'{int2 = 15, - bool2 = true}), - ?line {ok,{'SetOpt2Imp',asn1_NOVALUE,true,15}} = - asn1_wrapper:decode('SetOptional','SetOpt2Imp',lists:flatten(Bytes52)), - - - - ?line {ok,Bytes61} = - asn1_wrapper:encode('SetOptional','SetOpt3Imp',#'SetOpt3Imp'{bool3 = true, - int3 = 15, - set3 = #'SetIn'{boolIn = true, - intIn = 66}}), - ?line {ok,{'SetOpt3Imp',true,{'SetIn',true,66},15}} = - asn1_wrapper:decode('SetOptional','SetOpt3Imp',lists:flatten(Bytes61)), - - - ?line {ok,Bytes62} = asn1_wrapper:encode('SetOptional','SetOpt3Imp',#'SetOpt3Imp'{int3 = 15}), - ?line {ok,{'SetOpt3Imp',asn1_NOVALUE,asn1_NOVALUE,15}} = - asn1_wrapper:decode('SetOptional','SetOpt3Imp',lists:flatten(Bytes62)), - - - - - - - ?line {ok,Bytes71} = - asn1_wrapper:encode('SetOptional','SetOpt1Exp',#'SetOpt1Exp'{bool1 = true, - int1 = 15, - set1 = #'SetIn'{boolIn = true, - intIn = 66}}), - ?line {ok,{'SetOpt1Exp',true,15,{'SetIn',true,66}}} = - asn1_wrapper:decode('SetOptional','SetOpt1Exp',lists:flatten(Bytes71)), - - - ?line {ok,Bytes72} = asn1_wrapper:encode('SetOptional','SetOpt1Exp',#'SetOpt1Exp'{int1 = 15}), - ?line {ok,{'SetOpt1Exp',asn1_NOVALUE,15,asn1_NOVALUE}} = - asn1_wrapper:decode('SetOptional','SetOpt1Exp',lists:flatten(Bytes72)), - - - ?line {ok,Bytes81} = - asn1_wrapper:encode('SetOptional','SetOpt2Exp',#'SetOpt2Exp'{bool2 = true, - int2 = 15, - set2 = #'SetIn'{boolIn = true, - intIn = 66}}), - ?line {ok,{'SetOpt2Exp',{'SetIn',true,66},true,15}} = - asn1_wrapper:decode('SetOptional','SetOpt2Exp',lists:flatten(Bytes81)), - - - ?line {ok,Bytes82} = asn1_wrapper:encode('SetOptional','SetOpt2Exp',#'SetOpt2Exp'{int2 = 15, - bool2 = true}), - ?line {ok,{'SetOpt2Exp',asn1_NOVALUE,true,15}} = - asn1_wrapper:decode('SetOptional','SetOpt2Exp',lists:flatten(Bytes82)), - - - - ?line {ok,Bytes91} = - asn1_wrapper:encode('SetOptional','SetOpt3Exp',#'SetOpt3Exp'{bool3 = true, - int3 = 15, - set3 = #'SetIn'{boolIn = true, - intIn = 66}}), - ?line {ok,{'SetOpt3Exp',true,{'SetIn',true,66},15}} = - asn1_wrapper:decode('SetOptional','SetOpt3Exp',lists:flatten(Bytes91)), - - - ?line {ok,Bytes92} = asn1_wrapper:encode('SetOptional','SetOpt3Exp',#'SetOpt3Exp'{int3 = 15}), - ?line {ok,{'SetOpt3Exp',asn1_NOVALUE,asn1_NOVALUE,15}} = - asn1_wrapper:decode('SetOptional','SetOpt3Exp',lists:flatten(Bytes92)), - + + roundtrip('SetOpt2Imp', + #'SetOpt2Imp'{bool2=true,int2=15, + set2=#'SetIn'{boolIn=true,intIn=66}}), + roundtrip('SetOpt2Imp',#'SetOpt2Imp'{int2=15,bool2=true}), + + roundtrip('SetOpt3Imp', + #'SetOpt3Imp'{bool3=true,int3=15, + set3=#'SetIn'{boolIn=true,intIn=66}}), + roundtrip('SetOpt3Imp', #'SetOpt3Imp'{int3=15}), + + roundtrip('SetOpt1Exp', + #'SetOpt1Exp'{bool1=true,int1=15, + set1=#'SetIn'{boolIn=true,intIn=66}}), + roundtrip('SetOpt1Exp', #'SetOpt1Exp'{int1=15}), + + roundtrip('SetOpt2Exp', + #'SetOpt2Exp'{bool2=true,int2=15, + set2=#'SetIn'{boolIn=true,intIn=66}}), + roundtrip('SetOpt2Exp', #'SetOpt2Exp'{int2=15,bool2=true}), + roundtrip('SetOpt3Exp', + #'SetOpt3Exp'{bool3=true,int3=15, + set3=#'SetIn'{boolIn=true,intIn=66}}), + roundtrip('SetOpt3Exp', #'SetOpt3Exp'{int3=15}), ok. ticket_7533(Ber) when Ber == ber -> - Val = #'SetOpt1'{bool1 = true,int1=12,set1=#'SetIn'{boolIn=false,intIn=13}}, - ?line {ok,B} = asn1_wrapper:encode('SetOptional','SetOpt1',Val), - ?line {ok,Val} = asn1_wrapper:decode('SetOptional','SetOpt1',B), - - CorruptVal = [49,14,1,1,255,2,1,12] ++ lists:duplicate(8,0), - Pid = spawn(?MODULE,decoder,[self(),'SetOptional','SetOpt1',CorruptVal]), - receive - {ok,Pid,Result} -> - io:format("Decode result: ~p~n",[Result]), - ok - after 10000 -> - io:format("Decode timeout~n",[]), - exit(Pid,normal) - end; + Val = #'SetOpt1'{bool1=true,int1=12,set1=#'SetIn'{boolIn=false,intIn=13}}, + roundtrip('SetOpt1', Val), + CorruptVal = <<49,14,1,1,255,2,1,12,0:8/unit:8>>, + {error,_} = 'SetOptional':decode('SetOpt1', CorruptVal), + ok; ticket_7533(_) -> ok. -decoder(Parent,Module,Type,Val) -> - io:format("Decoding~n",[]), - ?line {ok,Res} = asn1_wrapper:decode(Module,Type,Val), - io:format("Decode res: ~p~n",[Res]), - Parent ! {ok,self(),Res}. +roundtrip(Type, Value) -> + {ok,Encoded} = 'SetOptional':encode(Type, Value), + {ok,Value} = 'SetOptional':decode(Type, Encoded), + ok. diff --git a/lib/asn1/test/test_partial_incomplete_decode.erl b/lib/asn1/test/test_partial_incomplete_decode.erl index df56c27115..8ede06938d 100644 --- a/lib/asn1/test/test_partial_incomplete_decode.erl +++ b/lib/asn1/test/test_partial_incomplete_decode.erl @@ -188,7 +188,7 @@ decode_parts('S1_2',PartDecMsg) -> msg('F') -> - {'F',{fb,{'E',35,[{'D',3,true},{'D',4,false},{'D',5,true},{'D',6,true},{'D',7,false},{'D',8,true},{'D',9,true},{'D',10,false},{'D',11,true},{'D',12,true},{'D',13,false},{'D',14,true}],false,{da,[{'A',16,{'D',17,true}}]}}}}; + {fb,{'E',35,[{'D',3,true},{'D',4,false},{'D',5,true},{'D',6,true},{'D',7,false},{'D',8,true},{'D',9,true},{'D',10,false},{'D',11,true},{'D',12,true},{'D',13,false},{'D',14,true}],false,{da,[{'A',16,{'D',17,true}}]}}}; msg('F3') -> {fb,{'E',10,[{'D',11,true},{'D',12,false}],false,{dc,{'E_d_dc',13,true,{'E_d_dc_dcc',14,15}}}}}; diff --git a/lib/asn1/test/test_selective_decode.erl b/lib/asn1/test/test_selective_decode.erl index bb348611da..ebe1296cf3 100644 --- a/lib/asn1/test/test_selective_decode.erl +++ b/lib/asn1/test/test_selective_decode.erl @@ -53,7 +53,7 @@ test() -> msg('F') -> - {'F',{fb,{'E',35,[{'D',3,true},{'D',4,false},{'D',5,true},{'D',6,true},{'D',7,false},{'D',8,true},{'D',9,true},{'D',10,false},{'D',11,true},{'D',12,true},{'D',13,false},{'D',14,true}],false,{da,[{'A',16,{'D',17,true}}]}}}}; + {fb,{'E',35,[{'D',3,true},{'D',4,false},{'D',5,true},{'D',6,true},{'D',7,false},{'D',8,true},{'D',9,true},{'D',10,false},{'D',11,true},{'D',12,true},{'D',13,false},{'D',14,true}],false,{da,[{'A',16,{'D',17,true}}]}}}; msg('E') -> {'E',10,[{'D',11,true},{'D',12,false}],false,{dc,{'E_d_dc',13,true,{'E_d_dc_dcc',14,15}}}}; diff --git a/lib/asn1/test/test_special_decode_performance.erl b/lib/asn1/test/test_special_decode_performance.erl index dd56d29b28..7dfab1f25a 100644 --- a/lib/asn1/test/test_special_decode_performance.erl +++ b/lib/asn1/test/test_special_decode_performance.erl @@ -31,8 +31,8 @@ go(all) -> {Time_S_c,Time_MGC_c}). go(N,Mod) -> - ?line Val = val(Mod), - ?line {ok,B} = Mod:encode(element(1,Val),Val), + {Type,Val} = val(Mod), + {ok,B} = Mod:encode(Type, Val), ?line go(Mod,B,N). go(Mod,Bin,N) -> @@ -92,7 +92,7 @@ val('PartialDecSeq') -> {'F',{fb,{'E',12,[{'D',13,true},{'D',14,false},{'D',15,true},{'D',16,false},{'D',13,true},{'D',14,false},{'D',15,true},{'D',16,false},{'D',13,true},{'D',14,false},{'D',15,true},{'D',16,false}],true,{da,[{'A',17,{'D',18,false}},{'A',19,{'D',20,true}},{'A',21,{'D',22,false}},{'A',17,{'D',18,false}},{'A',19,{'D',20,true}},{'A',21,{'D',22,false}},{'A',17,{'D',18,false}},{'A',19,{'D',20,true}},{'A',21,{'D',22,false}},{'A',17,{'D',18,false}},{'A',19,{'D',20,true}},{'A',21,{'D',22,false}},{'A',17,{'D',18,false}},{'A',19,{'D',20,true}},{'A',21,{'D',22,false}},{'A',17,{'D',18,false}},{'A',19,{'D',20,true}},{'A',21,{'D',22,false}}]}}}}; val('MEDIA-GATEWAY-CONTROL') -> - {'MegacoMessage',asn1_NOVALUE,{'Message',1,{ip4Address,{'IP4Address',[125,125,125,111],55555}},{transactions,[{transactionReply,{'TransactionReply',50007,asn1_NOVALUE,{actionReplies,[{'ActionReply',0,asn1_NOVALUE,asn1_NOVALUE,[{auditValueReply,{auditResult,{'AuditResult',{'TerminationID',[],[255,255,255]},[{mediaDescriptor,{'MediaDescriptor',asn1_NOVALUE,{multiStream,[{'StreamDescriptor',1,{'StreamParms',{'LocalControlDescriptor',sendRecv,asn1_NOVALUE,asn1_NOVALUE,[{'PropertyParm',[0,11,0,7],[[52,48]],asn1_NOVALUE}]},{'LocalRemoteDescriptor',[[{'PropertyParm',[0,0,176,1],[[48]],asn1_NOVALUE},{'PropertyParm',[0,0,176,8],[[73,78,32,73,80,52,32,49,50,53,46,49,50,53,46,49,50,53,46,49,49,49]],asn1_NOVALUE},{'PropertyParm',[0,0,176,15],[[97,117,100,105,111,32,49,49,49,49,32,82,84,80,47,65,86,80,32,32,52]],asn1_NOVALUE},{'PropertyParm',[0,0,176,12],[[112,116,105,109,101,58,51,48]],asn1_NOVALUE}]]},{'LocalRemoteDescriptor',[[{'PropertyParm',[0,0,176,1],[[48]],asn1_NOVALUE},{'PropertyParm',[0,0,176,8],[[73,78,32,73,80,52,32,49,50,52,46,49,50,52,46,49,50,52,46,50,50,50]],asn1_NOVALUE},{'PropertyParm',[0,0,176,15],[[97,117,100,105,111,32,50,50,50,50,32,82,84,80,47,65,86,80,32,32,52]],asn1_NOVALUE},{'PropertyParm',[0,0,176,12],[[112,116,105,109,101,58,51,48]],asn1_NOVALUE}]]}}}]}}},{packagesDescriptor,[{'PackagesItem',[0,11],1},{'PackagesItem',[0,11],1}]},{statisticsDescriptor,[{'StatisticsParameter',[0,12,0,4],[[49,50,48,48]]},{'StatisticsParameter',[0,11,0,2],[[54,50,51,48,48]]},{'StatisticsParameter',[0,12,0,5],[[55,48,48]]},{'StatisticsParameter',[0,11,0,3],[[52,53,49,48,48]]},{'StatisticsParameter',[0,12,0,6],[[48,46,50]]},{'StatisticsParameter',[0,12,0,7],[[50,48]]},{'StatisticsParameter',[0,12,0,8],[[52,48]]}]}]}}}]}]}}}]}}}. + {'MegacoMessage',{'MegacoMessage',asn1_NOVALUE,{'Message',1,{ip4Address,{'IP4Address',[125,125,125,111],55555}},{transactions,[{transactionReply,{'TransactionReply',50007,asn1_NOVALUE,{actionReplies,[{'ActionReply',0,asn1_NOVALUE,asn1_NOVALUE,[{auditValueReply,{auditResult,{'AuditResult',{'TerminationID',[],[255,255,255]},[{mediaDescriptor,{'MediaDescriptor',asn1_NOVALUE,{multiStream,[{'StreamDescriptor',1,{'StreamParms',{'LocalControlDescriptor',sendRecv,asn1_NOVALUE,asn1_NOVALUE,[{'PropertyParm',[0,11,0,7],[[52,48]],asn1_NOVALUE}]},{'LocalRemoteDescriptor',[[{'PropertyParm',[0,0,176,1],[[48]],asn1_NOVALUE},{'PropertyParm',[0,0,176,8],[[73,78,32,73,80,52,32,49,50,53,46,49,50,53,46,49,50,53,46,49,49,49]],asn1_NOVALUE},{'PropertyParm',[0,0,176,15],[[97,117,100,105,111,32,49,49,49,49,32,82,84,80,47,65,86,80,32,32,52]],asn1_NOVALUE},{'PropertyParm',[0,0,176,12],[[112,116,105,109,101,58,51,48]],asn1_NOVALUE}]]},{'LocalRemoteDescriptor',[[{'PropertyParm',[0,0,176,1],[[48]],asn1_NOVALUE},{'PropertyParm',[0,0,176,8],[[73,78,32,73,80,52,32,49,50,52,46,49,50,52,46,49,50,52,46,50,50,50]],asn1_NOVALUE},{'PropertyParm',[0,0,176,15],[[97,117,100,105,111,32,50,50,50,50,32,82,84,80,47,65,86,80,32,32,52]],asn1_NOVALUE},{'PropertyParm',[0,0,176,12],[[112,116,105,109,101,58,51,48]],asn1_NOVALUE}]]}}}]}}},{packagesDescriptor,[{'PackagesItem',[0,11],1},{'PackagesItem',[0,11],1}]},{statisticsDescriptor,[{'StatisticsParameter',[0,12,0,4],[[49,50,48,48]]},{'StatisticsParameter',[0,11,0,2],[[54,50,51,48,48]]},{'StatisticsParameter',[0,12,0,5],[[55,48,48]]},{'StatisticsParameter',[0,11,0,3],[[52,53,49,48,48]]},{'StatisticsParameter',[0,12,0,6],[[48,46,50]]},{'StatisticsParameter',[0,12,0,7],[[50,48]]},{'StatisticsParameter',[0,12,0,8],[[52,48]]}]}]}}}]}]}}}]}}}}. %% val('PartialDecSeq') -> %% {'F',{fb,{'E',35,[{'D',3,true},{'D',4,false},{'D',5,true},{'D',6,true},{'D',7,false},{'D',8,true},{'D',9,true},{'D',10,false},{'D',11,true},{'D',12,true},{'D',13,false},{'D',14,true}],false,{dc,{'E_d_dc',15,true,{'E_d_dc_dcc',17,4711}}}}}}. diff --git a/lib/common_test/doc/src/cover_chapter.xml b/lib/common_test/doc/src/cover_chapter.xml index b2e64bfff0..4fa92d5583 100644 --- a/lib/common_test/doc/src/cover_chapter.xml +++ b/lib/common_test/doc/src/cover_chapter.xml @@ -108,8 +108,8 @@ specifications</seealso>).</p> </section> + <marker id="cover_stop"></marker> <section> - <marker id="cover_stop"></marker> <title>Stopping the cover tool when tests are completed</title> <p>By default the Cover tool is automatically stopped when the tests are completed. This causes the original (non cover @@ -175,6 +175,11 @@ %% Specific modules to exclude in cover. {excl_mods, Mods}. + + %% Cross cover compilation + %% Tag = atom(), an identifier for a test run + %% Mod = [atom()], modules to compile for accumulated analysis + {cross,[{Tag,Mods}]}. </pre> <p>The <c>incl_dirs_r</c> and <c>excl_dirs_r</c> terms tell Common @@ -190,6 +195,81 @@ specification file for Common Test).</p> </section> + <marker id="cross_cover"/> + <section> + <title>Cross cover analysis</title> + <p>The cross cover mechanism allows cover analysis of modules + across multiple tests. It is useful if some code, e.g. a library + module, is used by many different tests and the accumulated cover + result is desirable.</p> + + <p>This can of course also be achieved in a more customized way by + using the <c>export</c> parameter in the cover specification and + analysing the result off line, but the cross cover mechanism is a + build in solution which also provides the logging.</p> + + <p>The mechanism is easiest explained via an example:</p> + + <p>Let's say that there are two systems, <c>s1</c> and <c>s2</c>, + which are tested in separate test runs. System <c>s1</c> contains + a library module <c>m1</c> which is tested by the <c>s1</c> test + run and is included in <c>s1</c>'s cover specification:</p> + +<code type="none"> +s1.cover: + {incl_mods,[m1]}.</code> + + <p>When analysing code coverage, the result for <c>m1</c> can be + seen in the cover log in the <c>s1</c> test result.</p> + + <p>Now, let's imagine that since <c>m1</c> is a library module, it + is also used quite a bit by system <c>s2</c>. The <c>s2</c> test + run does not specifically test <c>m1</c>, but it might still be + interesting to see which parts of <c>m1</c> is actually covered by + the <c>s2</c> tests. To do this, <c>m1</c> could be included also + in <c>s2</c>'s cover specification:</p> + +<code type="none"> +s2.cover: + {incl_mods,[m1]}.</code> + + <p>This would give an entry for <c>m1</c> also in the cover log + for the <c>s2</c> test run. The problem is that this would only + reflect the coverage by <c>s2</c> tests, not the accumulated + result over <c>s1</c> and <c>s2</c>. And this is where the cross + cover mechanism comes in handy.</p> + + <p>If instead the cover specification for <c>s2</c> was like + this:</p> + +<code type="none"> +s2.cover: + {cross,[{s1,[m1]}]}.</code> + + <p>then <c>m1</c> would be cover compiled in the <c>s2</c> test + run, but not shown in the coverage log. Instead, if + <c>ct_cover:cross_cover_analyse/2</c> is called after both + <c>s1</c> and <c>s2</c> test runs are completed, the accumulated + result for <c>m1</c> would be available in the cross cover log for + the <c>s1</c> test run.</p> + + <p>The call to the analyse function must be like this:</p> + +<code type="none"> +ct_cover:cross_cover_analyse(Level, [{s1,S1LogDir},{s2,S2LogDir}]).</code> + + <p>where <c>S1LogDir</c> and <c>S2LogDir</c> are the directories + named <c><TestName>.logs</c> for each test respectively.</p> + + <p>Note the tags <c>s1</c> and <c>s2</c> which are used in the + cover specification file and in the call to + <c>ct_cover:cross_cover_analyse/2</c>. The point of these are only + to map the modules specified in the cover specification to the log + directory specified in the call to the analyse function. The name + of the tag has no meaning beyond this.</p> + + </section> + <section> <title>Logging</title> <p>To view the result of a code coverage test, follow the @@ -197,6 +277,11 @@ takes you to the code coverage overview page. If you have successfully performed a detailed coverage analysis, you find links to each individual module coverage page here.</p> + + <p>If cross cover analysis has been performed, and there are + accumulated coverage results for the current test, then the - + "Coverdata collected over all tests" link will take you to these + results.</p> </section> </chapter> diff --git a/lib/common_test/src/ct_cover.erl b/lib/common_test/src/ct_cover.erl index d39f50ba00..ae671c750a 100644 --- a/lib/common_test/src/ct_cover.erl +++ b/lib/common_test/src/ct_cover.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2009. All Rights Reserved. +%% Copyright Ericsson AB 2006-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -24,7 +24,7 @@ -module(ct_cover). --export([get_spec/1, add_nodes/1, remove_nodes/1]). +-export([get_spec/1, add_nodes/1, remove_nodes/1, cross_cover_analyse/2]). -include("ct_util.hrl"). @@ -100,6 +100,22 @@ remove_nodes(Nodes) -> %%%----------------------------------------------------------------- +%%% @spec cross_cover_analyse(Level,Tests) -> ok +%%% Level = overview | details +%%% Tests = [{Tag,Dir}] +%%% Tag = atom() +%%% Dir = string() +%%% +%%% @doc Accumulate cover results over multiple tests. +%%% See the chapter about <seealso +%%% marker="cover_chapter#cross_cover">cross cover +%%% analysis</seealso> in the users's guide. +%%% +cross_cover_analyse(Level,Tests) -> + test_server_ctrl:cross_cover_analyse(Level,Tests). + + +%%%----------------------------------------------------------------- %%% @hidden %% Read cover specification file and return the parsed info. @@ -249,9 +265,11 @@ get_app_info(App=#cover{app=Name}, [{excl_mods,Name,Mods1}|Terms]) -> Mods = App#cover.excl_mods, get_app_info(App#cover{excl_mods=Mods++Mods1},Terms); -get_app_info(App=#cover{app=Name}, [{cross_apps,Name,AppMods1}|Terms]) -> - AppMods = App#cover.cross, - get_app_info(App#cover{cross=AppMods++AppMods1},Terms); +get_app_info(App=#cover{app=none}, [{cross,Cross}|Terms]) -> + get_app_info(App, [{cross,none,Cross}|Terms]); +get_app_info(App=#cover{app=Name}, [{cross,Name,Cross1}|Terms]) -> + Cross = App#cover.cross, + get_app_info(App#cover{cross=Cross++Cross1},Terms); get_app_info(App=#cover{app=none}, [{src_dirs,Dirs}|Terms]) -> get_app_info(App, [{src_dirs,none,Dirs}|Terms]); @@ -354,10 +372,10 @@ remove_excludes_and_dups(CoverData=#cover{excl_mods=Excl,incl_mods=Incl}) -> files2mods(Info=#cover{excl_mods=ExclFs, incl_mods=InclFs, - cross=CrossFs}) -> + cross=Cross}) -> Info#cover{excl_mods=files2mods1(ExclFs), incl_mods=files2mods1(InclFs), - cross=files2mods1(CrossFs)}. + cross=[{Tag,files2mods1(Fs)} || {Tag,Fs} <- Cross]}. files2mods1([M|Fs]) when is_atom(M) -> [M|files2mods1(Fs)]; diff --git a/lib/common_test/test/common_test.cover b/lib/common_test/test/common_test.cover index 66697854ea..3aa49623e7 100644 --- a/lib/common_test/test/common_test.cover +++ b/lib/common_test/test/common_test.cover @@ -1,10 +1,10 @@ %% -*- erlang -*- {incl_app,common_test,details}. -{cross_apps,common_test,[erl2html2, - test_server, - test_server_ctrl, - test_server_gl, - test_server_h, - test_server_io, - test_server_node, - test_server_sup]}. +{cross,common_test,[{test_server,[erl2html2, + test_server, + test_server_ctrl, + test_server_gl, + test_server_h, + test_server_io, + test_server_node, + test_server_sup]}]}. diff --git a/lib/common_test/test/ct_cover_SUITE.erl b/lib/common_test/test/ct_cover_SUITE.erl index bebfce70d0..cb49dc423f 100644 --- a/lib/common_test/test/ct_cover_SUITE.erl +++ b/lib/common_test/test/ct_cover_SUITE.erl @@ -77,7 +77,8 @@ all() -> slave_start_slave, cover_node_option, ct_cover_add_remove_nodes, - otp_9956 + otp_9956, + cross ]. %%-------------------------------------------------------------------- @@ -161,6 +162,43 @@ otp_9956(Config) -> check_calls(Events,{?suite,otp_9956,1},1), ok. +%% Test cross cover mechanism +cross(Config) -> + {ok,Events1} = run_test(cross1,Config), + check_calls(Events1,1), + + CoverFile2 = create_cover_file(cross1,[{cross,[{cross1,[?mod]}]}],Config), + {ok,Events2} = run_test(cross2,[{cover,CoverFile2}],Config), + check_calls(Events2,1), + + %% Get the log dirs for each test and run cross cover analyse + [D11,D12] = lists:sort(get_run_dirs(Events1)), + [D21,D22] = lists:sort(get_run_dirs(Events2)), + + ct_cover:cross_cover_analyse(details,[{cross1,D11},{cross2,D21}]), + ct_cover:cross_cover_analyse(details,[{cross1,D12},{cross2,D22}]), + + %% Get the cross cover logs and read for each test + [C11,C12,C21,C22] = + [filename:join(D,"cross_cover.html") || D <- [D11,D12,D21,D22]], + + {ok,CrossData} = file:read_file(C11), + {ok,CrossData} = file:read_file(C12), + + {ok,Def} = file:read_file(C21), + {ok,Def} = file:read_file(C22), + + %% A simple test: just check that the test module exists in the + %% log from cross1 test, and that it does not exist in the log + %% from cross2 test. + TestMod = list_to_binary(atom_to_list(?mod)), + {_,_} = binary:match(CrossData,TestMod), + nomatch = binary:match(Def,TestMod), + {_,_} = binary:match(Def, + <<"No cross cover modules exist for this application">>), + + ok. + %%%----------------------------------------------------------------- %%% HELP FUNCTIONS @@ -229,15 +267,18 @@ check_cover(Node) when is_atom(Node) -> false end. +%% Get the log dir "run.<timestamp>" for all (both!) tests +get_run_dirs(Events) -> + [filename:dirname(TCLog) || + {ct_test_support_eh, + {event,tc_logfile,_Node, + {{?suite,init_per_suite},TCLog}}} <- Events]. + %% Check that each coverlog includes N calls to ?mod:foo/0 check_calls(Events,N) -> check_calls(Events,{?mod,foo,0},N). check_calls(Events,MFA,N) -> - CoverLogs = - [filename:join(filename:dirname(TCLog),"all.coverdata") || - {ct_test_support_eh, - {event,tc_logfile,ct@falco, - {{?suite,init_per_suite},TCLog}}} <- Events], + CoverLogs = [filename:join(D,"all.coverdata") || D <- get_run_dirs(Events)], do_check_logs(CoverLogs,MFA,N). do_check_logs([CoverLog|CoverLogs],{Mod,_,_} = MFA,N) -> diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl index a3120eb917..10e7f5e9ce 100644 --- a/lib/compiler/src/compile.erl +++ b/lib/compiler/src/compile.erl @@ -1342,16 +1342,12 @@ save_binary(#compile{code=none}=St) -> {ok,St}; save_binary(#compile{module=Mod,ofile=Outfile, options=Opts}=St) -> %% Test that the module name and output file name match. - %% We must take care to not completely break a packaged module - %% (even though packages still is as an experimental, unsupported - %% feature) - so we will extract the last part of a packaged - %% module name and compare only that. case member(no_error_module_mismatch, Opts) of true -> save_binary_1(St); false -> Base = filename:rootname(filename:basename(Outfile)), - case lists:last(packages:split(Mod)) of + case atom_to_list(Mod) of Base -> save_binary_1(St); _ -> diff --git a/lib/compiler/src/sys_pre_expand.erl b/lib/compiler/src/sys_pre_expand.erl index e55fb2a037..a8c69c3cb1 100644 --- a/lib/compiler/src/sys_pre_expand.erl +++ b/lib/compiler/src/sys_pre_expand.erl @@ -35,10 +35,8 @@ -record(expand, {module=[], %Module name parameters=undefined, %Module parameters - package="", %Module package exports=[], %Exports imports=[], %Imports - mod_imports, %Module Imports compile=[], %Compile flags attributes=[], %Attributes callbacks=[], %Callbacks @@ -67,12 +65,8 @@ module(Fs0, Opts0) -> %% Set pre-defined exported functions. PreExp = [{module_info,0},{module_info,1}], - %% Set pre-defined module imports. - PreModImp = [{erlang,erlang},{packages,packages}], - %% Build initial expand record. St0 = #expand{exports=PreExp, - mod_imports=dict:from_list(PreModImp), compile=Opts, defined=PreExp, bitdefault = erl_bits:system_bitdefault(), @@ -242,14 +236,12 @@ forms([], St) -> {[],St}. %% Process an attribute, this just affects the state. attribute(module, {Module, As}, _L, St) -> - M = package_to_string(Module), - St#expand{module=list_to_atom(M), - package=packages:strip_last(M), + true = is_atom(Module), + St#expand{module=Module, parameters=As}; attribute(module, Module, _L, St) -> - M = package_to_string(Module), - St#expand{module=list_to_atom(M), - package=packages:strip_last(M)}; + true = is_atom(Module), + St#expand{module=Module}; attribute(export, Es, _L, St) -> St#expand{exports=union(from_list(Es), St#expand.exports)}; attribute(import, Is, _L, St) -> @@ -312,8 +304,6 @@ pattern({tuple,Line,Ps}, St0) -> %%pattern({struct,Line,Tag,Ps}, St0) -> %% {TPs,TPsvs,St1} = pattern_list(Ps, St0), %% {{tuple,Line,[{atom,Line,Tag}|TPs]},TPsvs,St1}; -pattern({record_field,_,_,_}=M, St) -> - {expand_package(M, St),St}; % must be a package name pattern({bin,Line,Es0}, St0) -> {Es1,St1} = pattern_bin(Es0, St0), {{bin,Line,Es1},St1}; @@ -404,8 +394,6 @@ expr({tuple,Line,Es0}, St0) -> %%expr({struct,Line,Tag,Es0}, Vs, St0) -> %% {Es1,Esvs,Esus,St1} = expr_list(Es0, Vs, St0), %% {{tuple,Line,[{atom,Line,Tag}|Es1]},Esvs,Esus,St1}; -expr({record_field,_,_,_}=M, St) -> - {expand_package(M, St),St}; % must be a package name expr({bin,Line,Es0}, St0) -> {Es1,St1} = expr_bin(Es0, St0), {{bin,Line,Es1},St1}; @@ -448,12 +436,9 @@ expr({call,Line,{atom,La,N}=Atom,As0}, St0) -> end end end; -expr({call,Line,{record_field,_,_,_}=M,As0}, St0) -> - expr({call,Line,expand_package(M, St0),As0}, St0); -expr({call,Line,{remote,Lr,M,F},As0}, St0) -> - M1 = expand_package(M, St0), - {[M2,F1|As1],St1} = expr_list([M1,F|As0], St0), - {{call,Line,{remote,Lr,M2,F1},As1},St1}; +expr({call,Line,{remote,Lr,M0,F},As0}, St0) -> + {[M1,F1|As1],St1} = expr_list([M0,F|As0], St0), + {{call,Line,{remote,Lr,M1,F1},As1},St1}; expr({call,Line,F,As0}, St0) -> {[Fun1|As1],St1} = expr_list([F|As0], St0), {{call,Line,Fun1,As1},St1}; @@ -666,32 +651,6 @@ string_to_conses(Line, Cs, Tail) -> foldr(fun (C, T) -> {cons,Line,{char,Line,C},T} end, Tail, Cs). -%% In syntax trees, module/package names are atoms or lists of atoms. - -package_to_string(A) when is_atom(A) -> atom_to_list(A); -package_to_string(L) when is_list(L) -> packages:concat(L). - -expand_package({atom,L,A} = M, St) -> - case dict:find(A, St#expand.mod_imports) of - {ok, A1} -> - {atom,L,A1}; - error -> - case packages:is_segmented(A) of - true -> - M; - false -> - M1 = packages:concat(St#expand.package, A), - {atom,L,list_to_atom(M1)} - end - end; -expand_package(M, _St) -> - case erl_parse:package_segments(M) of - error -> - M; - M1 -> - {atom,element(2,M),list_to_atom(package_to_string(M1))} - end. - %% import(Line, Imports, State) -> %% State' %% imported(Name, Arity, State) -> @@ -699,15 +658,10 @@ expand_package(M, _St) -> %% Handle import declarations and test for imported functions. No need to %% check when building imports as code is correct. -import({Mod0,Fs}, St) -> - Mod = list_to_atom(package_to_string(Mod0)), +import({Mod,Fs}, St) -> + true = is_atom(Mod), Mfs = from_list(Fs), - St#expand{imports=add_imports(Mod, Mfs, St#expand.imports)}; -import(Mod0, St) -> - Mod = package_to_string(Mod0), - Key = list_to_atom(packages:last(Mod)), - St#expand{mod_imports=dict:store(Key, list_to_atom(Mod), - St#expand.mod_imports)}. + St#expand{imports=add_imports(Mod, Mfs, St#expand.imports)}. add_imports(Mod, [F|Fs], Is) -> add_imports(Mod, Fs, orddict:store(F, Mod, Is)); diff --git a/lib/compiler/test/compilation_SUITE.erl b/lib/compiler/test/compilation_SUITE.erl index bec97b0199..f8f74e6f7a 100644 --- a/lib/compiler/test/compilation_SUITE.erl +++ b/lib/compiler/test/compilation_SUITE.erl @@ -44,7 +44,7 @@ groups() -> {group,vsn},otp_2380,otp_2141,otp_2173,otp_4790, const_list_256,bin_syntax_1,bin_syntax_2, bin_syntax_3,bin_syntax_4,bin_syntax_5,bin_syntax_6, - live_var,convopts,bad_functional_value, + live_var,convopts, catch_in_catch,redundant_case,long_string,otp_5076, complex_guard,otp_5092,otp_5151,otp_5235,otp_5244, trycatch_4,opt_crash,otp_5404,otp_5436,otp_5481, @@ -143,7 +143,6 @@ split({int, N}, <<N:16,B:N/binary,T/binary>>) -> ?comp(live_var). ?comp(trycatch_4). -?comp(bad_functional_value). ?comp(catch_in_catch). diff --git a/lib/compiler/test/compilation_SUITE_data/bad_functional_value.erl b/lib/compiler/test/compilation_SUITE_data/bad_functional_value.erl deleted file mode 100644 index 126a573e83..0000000000 --- a/lib/compiler/test/compilation_SUITE_data/bad_functional_value.erl +++ /dev/null @@ -1,28 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2003-2009. All Rights Reserved. -%% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%% -%% %CopyrightEnd% -%% --module(bad_functional_value). - --export([?MODULE/0,a/0]). - -?MODULE() -> - ok. - -a() -> - .list_to_atom("ok"). - diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl index 2cd75944f4..229e5a98a1 100644 --- a/lib/compiler/test/compile_SUITE.erl +++ b/lib/compiler/test/compile_SUITE.erl @@ -27,7 +27,7 @@ app_test/1, file_1/1, forms_2/1, module_mismatch/1, big_file/1, outdir/1, binary/1, makedep/1, cond_and_ifdef/1, listings/1, listings_big/1, - other_output/1, package_forms/1, encrypted_abstr/1, + other_output/1, encrypted_abstr/1, bad_record_use1/1, bad_record_use2/1, strict_record/1, missing_testheap/1, cover/1, env/1, core/1, asm/1, sys_pre_attributes/1]). @@ -44,7 +44,7 @@ all() -> test_lib:recompile(?MODULE), [app_test, file_1, forms_2, module_mismatch, big_file, outdir, binary, makedep, cond_and_ifdef, listings, listings_big, - other_output, package_forms, encrypted_abstr, + other_output, encrypted_abstr, {group, bad_record_use}, strict_record, missing_testheap, cover, env, core, asm, sys_pre_attributes]. @@ -410,32 +410,6 @@ other_output(Config) when is_list(Config) -> ?line test_server:timetrap_cancel(Dog), ok. -package_forms(Config) when is_list(Config) -> - Fs = [{attribute,1,file,{"./p.erl",1}}, - {attribute,1,module,[p,p]}, - {attribute,3,compile,export_all}, - {attribute,1,file, - {"/clearcase/otp/erts/lib/stdlib/include/qlc.hrl",1}}, - {attribute,6,file,{"./p.erl",6}}, - {function,7,q,0, - [{clause,7,[],[], - [{call,8, - {remote,8,{atom,8,qlc},{atom,8,q}}, - [{tuple,-8, - [{atom,-8,qlc_lc}, - {'fun',-8, - {clauses, - [{clause,-8,[],[], - [{tuple,-8, - [{atom,-8,simple_v1}, - {atom,-8,'X'}, - {'fun',-8,{clauses,[{clause,-8,[],[],[{nil,8}]}]}}, - {integer,-8,8}]}]}]}}, - {atom,-8,undefined}]}]}]}]}, - {eof,9}], - {ok,'p.p',_} = compile:forms(Fs, ['S',report]), - ok. - encrypted_abstr(Config) when is_list(Config) -> ?line Dog = test_server:timetrap(test_server:minutes(10)), ?line {Simple,Target} = files(Config, "encrypted_abstr"), diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index 72c9e5b8e8..e77e5fb8f0 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -44,6 +44,7 @@ #include <openssl/md5.h> #include <openssl/md4.h> #include <openssl/sha.h> +#include <openssl/ripemd.h> #include <openssl/bn.h> #include <openssl/objects.h> #include <openssl/rc4.h> @@ -139,6 +140,10 @@ static ERL_NIF_TERM md5(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM md5_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM md5_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM md5_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM ripemd160(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM ripemd160_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM ripemd160_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM ripemd160_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM sha(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM sha_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM sha_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); @@ -246,6 +251,10 @@ static ErlNifFunc nif_funcs[] = { {"md5_init", 0, md5_init}, {"md5_update", 2, md5_update}, {"md5_final", 1, md5_final}, + {"ripemd160", 1, ripemd160}, + {"ripemd160_init", 0, ripemd160_init}, + {"ripemd160_update", 2, ripemd160_update}, + {"ripemd160_final", 1, ripemd160_final}, {"sha", 1, sha}, {"sha_init", 0, sha_init}, {"sha_update", 2, sha_update}, @@ -326,6 +335,8 @@ ERL_NIF_INIT(crypto,nif_funcs,load,NULL,upgrade,unload) #define MD5_LEN_96 12 #define MD4_CTX_LEN (sizeof(MD4_CTX)) #define MD4_LEN 16 +#define RIPEMD160_CTX_LEN (sizeof(RIPEMD160_CTX)) +#define RIPEMD160_LEN 20 #define SHA_CTX_LEN (sizeof(SHA_CTX)) #define SHA_LEN 20 #define SHA_LEN_96 12 @@ -600,6 +611,53 @@ static ERL_NIF_TERM md5_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ return ret; } +static ERL_NIF_TERM ripemd160(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{/* (Data) */ + ErlNifBinary ibin; + ERL_NIF_TERM ret; + + if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) { + return enif_make_badarg(env); + } + RIPEMD160((unsigned char *) ibin.data, ibin.size, + enif_make_new_binary(env,RIPEMD160_LEN, &ret)); + return ret; +} +static ERL_NIF_TERM ripemd160_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{/* () */ + ERL_NIF_TERM ret; + RIPEMD160_Init((RIPEMD160_CTX *) enif_make_new_binary(env, RIPEMD160_CTX_LEN, &ret)); + return ret; +} +static ERL_NIF_TERM ripemd160_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{/* (Context, Data) */ + RIPEMD160_CTX* new_ctx; + ErlNifBinary ctx_bin, data_bin; + ERL_NIF_TERM ret; + if (!enif_inspect_binary(env, argv[0], &ctx_bin) + || ctx_bin.size != RIPEMD160_CTX_LEN + || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { + return enif_make_badarg(env); + } + new_ctx = (RIPEMD160_CTX*) enif_make_new_binary(env,RIPEMD160_CTX_LEN, &ret); + memcpy(new_ctx, ctx_bin.data, RIPEMD160_CTX_LEN); + RIPEMD160_Update(new_ctx, data_bin.data, data_bin.size); + return ret; +} +static ERL_NIF_TERM ripemd160_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{/* (Context) */ + ErlNifBinary ctx_bin; + RIPEMD160_CTX ctx_clone; + ERL_NIF_TERM ret; + if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != RIPEMD160_CTX_LEN) { + return enif_make_badarg(env); + } + memcpy(&ctx_clone, ctx_bin.data, RIPEMD160_CTX_LEN); /* writable */ + RIPEMD160_Final(enif_make_new_binary(env, RIPEMD160_LEN, &ret), &ctx_clone); + return ret; +} + + static ERL_NIF_TERM sha(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Data) */ ErlNifBinary ibin; diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml index 3e533158c8..14c77c873f 100644..100755 --- a/lib/crypto/doc/src/crypto.xml +++ b/lib/crypto/doc/src/crypto.xml @@ -265,7 +265,7 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]> <name>hash(Type, Data) -> Digest</name> <fsummary></fsummary> <type> - <v>Type = md4 | md5 | sha | sha224 | sha256 | sha384 | sha512</v> + <v>Type = md4 | md5 | ripemd160 | sha | sha224 | sha256 | sha384 | sha512</v> <v>Data = iodata()</v> <v>Digest = binary()</v> </type> @@ -279,7 +279,7 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]> <name>hash_init(Type) -> Context</name> <fsummary></fsummary> <type> - <v>Type = md4 | md5 | sha | sha224 | sha256 | sha384 | sha512</v> + <v>Type = md4 | md5 | ripemd160 | sha | sha224 | sha256 | sha384 | sha512</v> </type> <desc> <p>Initializes the context for streaming hash operations. <c>Type</c> determines @@ -343,10 +343,27 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]> </desc> </func> <func> + <name>hmac(Type, Key, Data) -> Mac</name> + <name>hmac(Type, Key, Data, MacLength) -> Mac</name> + <fsummary></fsummary> + <type> + <v>Type = md5 | sha | sha224 | sha256 | sha384 | sha512</v> + <v>Key = iodata()</v> + <v>Data = iodata()</v> + <v>MacLength = integer()</v> + <v>Mac = binary()</v> + </type> + <desc> + <p>Computes a HMAC of type <c>Type</c> from <c>Data</c> using + <c>Key</c> as the authentication key.</p> <c>MacLength</c> + will limit the size of the resultant <c>Mac</c>. + </desc> + </func> + <func> <name>hmac_init(Type, Key) -> Context</name> <fsummary></fsummary> <type> - <v>Type = sha | md5 | ripemd160</v> + <v>Type = md5 | ripemd160 | sha | sha224 | sha256 | sha384 | sha512</v> <v>Key = iolist() | binary()</v> <v>Context = binary()</v> </type> diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index 461558a79e..aa89f6cc61 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -35,7 +35,7 @@ -export([sha256_mac/2, sha256_mac/3]). -export([sha384_mac/2, sha384_mac/3]). -export([sha512_mac/2, sha512_mac/3]). --export([hmac_init/2, hmac_update/2, hmac_final/1, hmac_final_n/2]). +-export([hmac/3, hmac/4, hmac_init/2, hmac_update/2, hmac_final/1, hmac_final_n/2]). -export([des_cbc_encrypt/3, des_cbc_decrypt/3, des_cbc_ivec/1]). -export([des_ecb_encrypt/2, des_ecb_decrypt/2]). -export([des_cfb_encrypt/3, des_cfb_decrypt/3, des_cfb_ivec/2]). @@ -107,7 +107,7 @@ blowfish_ecb_encrypt, blowfish_ecb_decrypt, blowfish_ofb64_encrypt, des_cbc_ivec, des_cfb_ivec, erlint, mpint, hash, hash_init, hash_update, hash_final, - hmac_init, hmac_update, hmac_final, hmac_final_n, info, + hmac, hmac_init, hmac_update, hmac_final, hmac_final_n, info, rc2_cbc_encrypt, rc2_cbc_decrypt, info_lib]). @@ -197,43 +197,48 @@ version() -> ?CRYPTO_VSN. %% -spec hash(_, iodata()) -> binary(). -hash(md5, Data) -> md5(Data); -hash(md4, Data) -> md4(Data); -hash(sha, Data) -> sha(Data); -hash(sha224, Data) -> sha224(Data); -hash(sha256, Data) -> sha256(Data); -hash(sha384, Data) -> sha384(Data); -hash(sha512, Data) -> sha512(Data). - --spec hash_init('md5'|'md4'|'sha'|'sha224'|'sha256'|'sha384'|'sha512') -> any(). - -hash_init(md5) -> {md5, md5_init()}; -hash_init(md4) -> {md4, md4_init()}; -hash_init(sha) -> {sha, sha_init()}; -hash_init(sha224) -> {sha224, sha224_init()}; -hash_init(sha256) -> {sha256, sha256_init()}; -hash_init(sha384) -> {sha384, sha384_init()}; -hash_init(sha512) -> {sha512, sha512_init()}. +hash(md5, Data) -> md5(Data); +hash(md4, Data) -> md4(Data); +hash(sha, Data) -> sha(Data); +hash(ripemd160, Data) -> ripemd160(Data); +hash(sha224, Data) -> sha224(Data); +hash(sha256, Data) -> sha256(Data); +hash(sha384, Data) -> sha384(Data); +hash(sha512, Data) -> sha512(Data). + +-spec hash_init('md5'|'md4'|'ripemd160'| + 'sha'|'sha224'|'sha256'|'sha384'|'sha512') -> any(). + +hash_init(md5) -> {md5, md5_init()}; +hash_init(md4) -> {md4, md4_init()}; +hash_init(sha) -> {sha, sha_init()}; +hash_init(ripemd160) -> {ripemd160, ripemd160_init()}; +hash_init(sha224) -> {sha224, sha224_init()}; +hash_init(sha256) -> {sha256, sha256_init()}; +hash_init(sha384) -> {sha384, sha384_init()}; +hash_init(sha512) -> {sha512, sha512_init()}. -spec hash_update(_, iodata()) -> any(). -hash_update({md5,Context}, Data) -> {md5, md5_update(Context,Data)}; -hash_update({md4,Context}, Data) -> {md4, md4_update(Context,Data)}; -hash_update({sha,Context}, Data) -> {sha, sha_update(Context,Data)}; -hash_update({sha224,Context}, Data) -> {sha224, sha224_update(Context,Data)}; -hash_update({sha256,Context}, Data) -> {sha256, sha256_update(Context,Data)}; -hash_update({sha384,Context}, Data) -> {sha384, sha384_update(Context,Data)}; -hash_update({sha512,Context}, Data) -> {sha512, sha512_update(Context,Data)}. +hash_update({md5,Context}, Data) -> {md5, md5_update(Context,Data)}; +hash_update({md4,Context}, Data) -> {md4, md4_update(Context,Data)}; +hash_update({sha,Context}, Data) -> {sha, sha_update(Context,Data)}; +hash_update({ripemd160,Context}, Data) -> {ripemd160, ripemd160_update(Context,Data)}; +hash_update({sha224,Context}, Data) -> {sha224, sha224_update(Context,Data)}; +hash_update({sha256,Context}, Data) -> {sha256, sha256_update(Context,Data)}; +hash_update({sha384,Context}, Data) -> {sha384, sha384_update(Context,Data)}; +hash_update({sha512,Context}, Data) -> {sha512, sha512_update(Context,Data)}. -spec hash_final(_) -> binary(). -hash_final({md5,Context}) -> md5_final(Context); -hash_final({md4,Context}) -> md4_final(Context); -hash_final({sha,Context}) -> sha_final(Context); -hash_final({sha224,Context}) -> sha224_final(Context); -hash_final({sha256,Context}) -> sha256_final(Context); -hash_final({sha384,Context}) -> sha384_final(Context); -hash_final({sha512,Context}) -> sha512_final(Context). +hash_final({md5,Context}) -> md5_final(Context); +hash_final({md4,Context}) -> md4_final(Context); +hash_final({sha,Context}) -> sha_final(Context); +hash_final({ripemd160,Context}) -> ripemd160_final(Context); +hash_final({sha224,Context}) -> sha224_final(Context); +hash_final({sha256,Context}) -> sha256_final(Context); +hash_final({sha384,Context}) -> sha384_final(Context); +hash_final({sha512,Context}) -> sha512_final(Context). %% %% MD5 @@ -263,6 +268,20 @@ md4_update(_Context, _Data) -> ?nif_stub. md4_final(_Context) -> ?nif_stub. %% +%% RIPEMD160 +%% + +-spec ripemd160(iodata()) -> binary(). +-spec ripemd160_init() -> binary(). +-spec ripemd160_update(binary(), iodata()) -> binary(). +-spec ripemd160_final(binary()) -> binary(). + +ripemd160(_Data) -> ?nif_stub. +ripemd160_init() -> ?nif_stub. +ripemd160_update(_Context, _Data) -> ?nif_stub. +ripemd160_final(_Context) -> ?nif_stub. + +%% %% SHA %% -spec sha(iodata()) -> binary(). @@ -418,11 +437,28 @@ sha512_final_nif(_Context) -> ?nif_stub. %% %% HMAC (multiple hash options) %% + +-spec hmac(_, iodata(), iodata()) -> binary(). +-spec hmac(_, iodata(), iodata(), integer()) -> binary(). -spec hmac_init(atom(), iodata()) -> binary(). -spec hmac_update(binary(), iodata()) -> binary(). -spec hmac_final(binary()) -> binary(). -spec hmac_final_n(binary(), integer()) -> binary(). +hmac(md5, Key, Data) -> md5_mac(Key, Data); +hmac(sha, Key, Data) -> sha_mac(Key, Data); +hmac(sha224, Key, Data) -> sha224_mac(Key, Data); +hmac(sha256, Key, Data) -> sha256_mac(Key, Data); +hmac(sha384, Key, Data) -> sha384_mac(Key, Data); +hmac(sha512, Key, Data) -> sha512_mac(Key, Data). + +hmac(md5, Key, Data, Size) -> md5_mac_n(Key, Data, Size); +hmac(sha, Key, Data, Size) -> sha_mac(Key, Data, Size); +hmac(sha224, Key, Data, Size) -> sha224_mac(Key, Data, Size); +hmac(sha256, Key, Data, Size) -> sha256_mac(Key, Data, Size); +hmac(sha384, Key, Data, Size) -> sha384_mac(Key, Data, Size); +hmac(sha512, Key, Data, Size) -> sha512_mac(Key, Data, Size). + hmac_init(_Type, _Key) -> ?nif_stub. hmac_update(_Context, _Data) -> ? nif_stub. hmac_final(_Context) -> ? nif_stub. diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl index 8965ab6b94..142f06677a 100644 --- a/lib/crypto/test/crypto_SUITE.erl +++ b/lib/crypto/test/crypto_SUITE.erl @@ -38,7 +38,10 @@ hmac_update_md5/1, hmac_update_md5_io/1, hmac_update_md5_n/1, + hmac_rfc2202/1, hmac_rfc4231/1, + ripemd160/1, + ripemd160_update/1, sha256/1, sha256_update/1, sha512/1, @@ -86,11 +89,11 @@ groups() -> [{info, [sequence],[info, {group, rest}]}, {rest, [], [md5, md5_update, md4, md4_update, md5_mac, - md5_mac_io, sha, sha_update, + md5_mac_io, ripemd160, ripemd160_update, sha, sha_update, sha256, sha256_update, sha512, sha512_update, hmac_update_sha, hmac_update_sha_n, hmac_update_sha256, hmac_update_sha512, hmac_update_md5_n, hmac_update_md5_io, hmac_update_md5, - hmac_rfc4231, + hmac_rfc2202, hmac_rfc4231, des_cbc, aes_cfb, aes_cbc, des_cfb, des_cfb_iter, des3_cbc, des3_cfb, rc2_cbc, aes_cbc_iter, aes_ctr, aes_ctr_stream, des_cbc_iter, des_ecb, @@ -418,8 +421,169 @@ hmac_update_md5(Config) when is_list(Config) -> ?line Exp2 = crypto:md5_mac(Key2, lists:flatten([Long1, Long2, Long3])), ?line m(Exp2, Mac2). +hmac_rfc2202(doc) -> + ["Generate an HMAC using hmac, md5_mac, and sha_mac." + "Test vectors are taken from RFC-2202."]; +hmac_rfc2202(suite) -> + []; +hmac_rfc2202(Config) when is_list(Config) -> + hmac_rfc2202_md5(), + hmac_rfc2202_sha(). + +hmac_rfc2202_md5() -> + %% Test case 1 + Case1Key = binary:copy(<<16#0b>>, 16), + Case1Data = <<"Hi There">>, + Case1Exp = hexstr2bin("9294727a3638bb1c13f48ef8158bfc9d"), + + ?line Case1Mac_1 = crypto:md5_mac(Case1Key, Case1Data), + ?line Case1Mac_2 = crypto:hmac(md5, Case1Key, Case1Data), + ?line m(Case1Exp, Case1Mac_1), + ?line m(Case1Exp, Case1Mac_2), + + %% Test case 2 + Case2Key = <<"Jefe">>, + Case2Data = <<"what do ya want for nothing?">>, + Case2Exp = hexstr2bin("750c783e6ab0b503eaa86e310a5db738"), + + ?line Case2Mac_1 = crypto:md5_mac(Case2Key, Case2Data), + ?line Case2Mac_2 = crypto:hmac(md5, Case2Key, Case2Data), + ?line m(Case2Exp, Case2Mac_1), + ?line m(Case2Exp, Case2Mac_2), + + %% Test case 3 + Case3Key = binary:copy(<<16#aa>>, 16), + Case3Data = binary:copy(<<16#dd>>, 50), + Case3Exp = hexstr2bin("56be34521d144c88dbb8c733f0e8b3f6"), + + ?line Case3Mac_1 = crypto:md5_mac(Case3Key, Case3Data), + ?line Case3Mac_2 = crypto:hmac(md5, Case3Key, Case3Data), + ?line m(Case3Exp, Case3Mac_1), + ?line m(Case3Exp, Case3Mac_2), + + %% Test case 4 + Case4Key = list_to_binary(lists:seq(1, 16#19)), + Case4Data = binary:copy(<<16#cd>>, 50), + Case4Exp = hexstr2bin("697eaf0aca3a3aea3a75164746ffaa79"), + + ?line Case4Mac_1 = crypto:md5_mac(Case4Key, Case4Data), + ?line Case4Mac_2 = crypto:hmac(md5, Case4Key, Case4Data), + ?line m(Case4Exp, Case4Mac_1), + ?line m(Case4Exp, Case4Mac_2), + + %% Test case 5 + Case5Key = binary:copy(<<16#0c>>, 16), + Case5Data = "Test With Truncation", + Case5Exp = hexstr2bin("56461ef2342edc00f9bab995690efd4c"), + Case5Exp96 = hexstr2bin("56461ef2342edc00f9bab995"), + + ?line Case5Mac_1 = crypto:md5_mac(Case5Key, Case5Data), + ?line Case5Mac_2 = crypto:hmac(md5, Case5Key, Case5Data), + ?line Case5Mac96_1 = crypto:md5_mac_96(Case5Key, Case5Data), + ?line Case5Mac96_2 = crypto:hmac(md5, Case5Key, Case5Data, 12), + ?line m(Case5Exp, Case5Mac_1), + ?line m(Case5Exp, Case5Mac_2), + ?line m(Case5Exp96, Case5Mac96_1), + ?line m(Case5Exp96, Case5Mac96_2), + + %% Test case 6 + Case6Key = binary:copy(<<16#aa>>, 80), + Case6Data = <<"Test Using Larger Than Block-Size Key - Hash Key First">>, + Case6Exp = hexstr2bin("6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd"), + + ?line Case6Mac_1 = crypto:md5_mac(Case6Key, Case6Data), + ?line Case6Mac_2 = crypto:hmac(md5, Case6Key, Case6Data), + ?line m(Case6Exp, Case6Mac_1), + ?line m(Case6Exp, Case6Mac_2), + + %% Test case 7 + Case7Key = binary:copy(<<16#aa>>, 80), + Case7Data = <<"Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data">>, + Case7Exp = hexstr2bin("6f630fad67cda0ee1fb1f562db3aa53e"), + + ?line Case7Mac_1 = crypto:md5_mac(Case7Key, Case7Data), + ?line Case7Mac_2 = crypto:hmac(md5, Case7Key, Case7Data), + ?line m(Case7Exp, Case7Mac_1), + ?line m(Case7Exp, Case7Mac_2). + +hmac_rfc2202_sha() -> + %% Test case 1 + Case1Key = binary:copy(<<16#0b>>, 20), + Case1Data = <<"Hi There">>, + Case1Exp = hexstr2bin("b617318655057264e28bc0b6fb378c8ef146be00"), + + ?line Case1Mac_1 = crypto:sha_mac(Case1Key, Case1Data), + ?line Case1Mac_2 = crypto:hmac(sha, Case1Key, Case1Data), + ?line m(Case1Exp, Case1Mac_1), + ?line m(Case1Exp, Case1Mac_2), + + %% Test case 2 + Case2Key = <<"Jefe">>, + Case2Data = <<"what do ya want for nothing?">>, + Case2Exp = hexstr2bin("effcdf6ae5eb2fa2d27416d5f184df9c259a7c79"), + + ?line Case2Mac_1 = crypto:sha_mac(Case2Key, Case2Data), + ?line Case2Mac_2 = crypto:hmac(sha, Case2Key, Case2Data), + ?line m(Case2Exp, Case2Mac_1), + ?line m(Case2Exp, Case2Mac_2), + + %% Test case 3 + Case3Key = binary:copy(<<16#aa>>, 20), + Case3Data = binary:copy(<<16#dd>>, 50), + Case3Exp = hexstr2bin("125d7342b9ac11cd91a39af48aa17b4f63f175d3"), + + ?line Case3Mac_1 = crypto:sha_mac(Case3Key, Case3Data), + ?line Case3Mac_2 = crypto:hmac(sha, Case3Key, Case3Data), + ?line m(Case3Exp, Case3Mac_1), + ?line m(Case3Exp, Case3Mac_2), + + %% Test case 4 + Case4Key = list_to_binary(lists:seq(1, 16#19)), + Case4Data = binary:copy(<<16#cd>>, 50), + Case4Exp = hexstr2bin("4c9007f4026250c6bc8414f9bf50c86c2d7235da"), + + ?line Case4Mac_1 = crypto:sha_mac(Case4Key, Case4Data), + ?line Case4Mac_2 = crypto:hmac(sha, Case4Key, Case4Data), + ?line m(Case4Exp, Case4Mac_1), + ?line m(Case4Exp, Case4Mac_2), + + %% Test case 5 + Case5Key = binary:copy(<<16#0c>>, 20), + Case5Data = "Test With Truncation", + Case5Exp = hexstr2bin("4c1a03424b55e07fe7f27be1d58bb9324a9a5a04"), + Case5Exp96 = hexstr2bin("4c1a03424b55e07fe7f27be1"), + + ?line Case5Mac_1 = crypto:sha_mac(Case5Key, Case5Data), + ?line Case5Mac_2 = crypto:hmac(sha, Case5Key, Case5Data), + ?line Case5Mac96_1 = crypto:sha_mac_96(Case5Key, Case5Data), + ?line Case5Mac96_2 = crypto:hmac(sha, Case5Key, Case5Data, 12), + ?line m(Case5Exp, Case5Mac_1), + ?line m(Case5Exp, Case5Mac_2), + ?line m(Case5Exp96, Case5Mac96_1), + ?line m(Case5Exp96, Case5Mac96_2), + + %% Test case 6 + Case6Key = binary:copy(<<16#aa>>, 80), + Case6Data = <<"Test Using Larger Than Block-Size Key - Hash Key First">>, + Case6Exp = hexstr2bin("aa4ae5e15272d00e95705637ce8a3b55ed402112"), + + ?line Case6Mac_1 = crypto:sha_mac(Case6Key, Case6Data), + ?line Case6Mac_2 = crypto:hmac(sha, Case6Key, Case6Data), + ?line m(Case6Exp, Case6Mac_1), + ?line m(Case6Exp, Case6Mac_2), + + %% Test case 7 + Case7Key = binary:copy(<<16#aa>>, 80), + Case7Data = <<"Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data">>, + Case7Exp = hexstr2bin("e8e99d0f45237d786d6bbaa7965c7808bbff1a91"), + + ?line Case7Mac_1 = crypto:sha_mac(Case7Key, Case7Data), + ?line Case7Mac_2 = crypto:hmac(sha, Case7Key, Case7Data), + ?line m(Case7Exp, Case7Mac_1), + ?line m(Case7Exp, Case7Mac_2). + hmac_rfc4231(doc) -> - ["Generate an HMAC using crypto:shaXXX_mac and hmac_init, hmac_update, and hmac_final. " + ["Generate an HMAC using crypto:shaXXX_mac, hmac, and hmac_init, hmac_update, and hmac_final. " "Testvectors are take from RFC4231." ]; hmac_rfc4231(suite) -> []; @@ -446,29 +610,37 @@ hmac_rfc4231_do() -> ?line Case1Ctx224_2 = crypto:hmac_update(Case1Ctx224, Case1Data), ?line Case1Mac224_1 = crypto:hmac_final(Case1Ctx224_2), ?line Case1Mac224_2 = crypto:sha224_mac(Case1Key, Case1Data), + ?line Case1Mac224_3 = crypto:hmac(sha224, Case1Key, Case1Data), ?line m(Case1Exp224, Case1Mac224_1), ?line m(Case1Exp224, Case1Mac224_2), + ?line m(Case1Exp224, Case1Mac224_3), ?line Case1Ctx256 = crypto:hmac_init(sha256, Case1Key), ?line Case1Ctx256_2 = crypto:hmac_update(Case1Ctx256, Case1Data), ?line Case1Mac256_1 = crypto:hmac_final(Case1Ctx256_2), ?line Case1Mac256_2 = crypto:sha256_mac(Case1Key, Case1Data), + ?line Case1Mac256_3 = crypto:hmac(sha256, Case1Key, Case1Data), ?line m(Case1Exp256, Case1Mac256_1), ?line m(Case1Exp256, Case1Mac256_2), + ?line m(Case1Exp256, Case1Mac256_3), ?line Case1Ctx384 = crypto:hmac_init(sha384, Case1Key), ?line Case1Ctx384_2 = crypto:hmac_update(Case1Ctx384, Case1Data), ?line Case1Mac384_1 = crypto:hmac_final(Case1Ctx384_2), ?line Case1Mac384_2 = crypto:sha384_mac(Case1Key, Case1Data), + ?line Case1Mac384_3 = crypto:hmac(sha384, Case1Key, Case1Data), ?line m(Case1Exp384, Case1Mac384_1), ?line m(Case1Exp384, Case1Mac384_2), + ?line m(Case1Exp384, Case1Mac384_3), ?line Case1Ctx512 = crypto:hmac_init(sha512, Case1Key), ?line Case1Ctx512_2 = crypto:hmac_update(Case1Ctx512, Case1Data), ?line Case1Mac512_1 = crypto:hmac_final(Case1Ctx512_2), ?line Case1Mac512_2 = crypto:sha512_mac(Case1Key, Case1Data), + ?line Case1Mac512_3 = crypto:hmac(sha512, Case1Key, Case1Data), ?line m(Case1Exp512, Case1Mac512_1), ?line m(Case1Exp512, Case1Mac512_2), + ?line m(Case1Exp512, Case1Mac512_3), %% Test Case 2 Case2Key = <<"Jefe">>, @@ -489,29 +661,37 @@ hmac_rfc4231_do() -> ?line Case2Ctx224_2 = crypto:hmac_update(Case2Ctx224, Case2Data), ?line Case2Mac224_1 = crypto:hmac_final(Case2Ctx224_2), ?line Case2Mac224_2 = crypto:sha224_mac(Case2Key, Case2Data), + ?line Case2Mac224_3 = crypto:hmac(sha224, Case2Key, Case2Data), ?line m(Case2Exp224, Case2Mac224_1), ?line m(Case2Exp224, Case2Mac224_2), + ?line m(Case2Exp224, Case2Mac224_3), ?line Case2Ctx256 = crypto:hmac_init(sha256, Case2Key), ?line Case2Ctx256_2 = crypto:hmac_update(Case2Ctx256, Case2Data), ?line Case2Mac256_1 = crypto:hmac_final(Case2Ctx256_2), ?line Case2Mac256_2 = crypto:sha256_mac(Case2Key, Case2Data), + ?line Case2Mac256_3 = crypto:hmac(sha256, Case2Key, Case2Data), ?line m(Case2Exp256, Case2Mac256_1), ?line m(Case2Exp256, Case2Mac256_2), + ?line m(Case2Exp256, Case2Mac256_3), ?line Case2Ctx384 = crypto:hmac_init(sha384, Case2Key), ?line Case2Ctx384_2 = crypto:hmac_update(Case2Ctx384, Case2Data), ?line Case2Mac384_1 = crypto:hmac_final(Case2Ctx384_2), ?line Case2Mac384_2 = crypto:sha384_mac(Case2Key, Case2Data), + ?line Case2Mac384_3 = crypto:hmac(sha384, Case2Key, Case2Data), ?line m(Case2Exp384, Case2Mac384_1), ?line m(Case2Exp384, Case2Mac384_2), + ?line m(Case2Exp384, Case2Mac384_3), ?line Case2Ctx512 = crypto:hmac_init(sha512, Case2Key), ?line Case2Ctx512_2 = crypto:hmac_update(Case2Ctx512, Case2Data), ?line Case2Mac512_1 = crypto:hmac_final(Case2Ctx512_2), ?line Case2Mac512_2 = crypto:sha512_mac(Case2Key, Case2Data), + ?line Case2Mac512_3 = crypto:hmac(sha512, Case2Key, Case2Data), ?line m(Case2Exp512, Case2Mac512_1), ?line m(Case2Exp512, Case2Mac512_2), + ?line m(Case2Exp512, Case2Mac512_3), %% Test Case 3 Case3Key = binary:copy(<<16#aa>>, 20), @@ -532,29 +712,37 @@ hmac_rfc4231_do() -> ?line Case3Ctx224_2 = crypto:hmac_update(Case3Ctx224, Case3Data), ?line Case3Mac224_1 = crypto:hmac_final(Case3Ctx224_2), ?line Case3Mac224_2 = crypto:sha224_mac(Case3Key, Case3Data), + ?line Case3Mac224_3 = crypto:hmac(sha224, Case3Key, Case3Data), ?line m(Case3Exp224, Case3Mac224_1), ?line m(Case3Exp224, Case3Mac224_2), + ?line m(Case3Exp224, Case3Mac224_3), ?line Case3Ctx256 = crypto:hmac_init(sha256, Case3Key), ?line Case3Ctx256_2 = crypto:hmac_update(Case3Ctx256, Case3Data), ?line Case3Mac256_1 = crypto:hmac_final(Case3Ctx256_2), ?line Case3Mac256_2 = crypto:sha256_mac(Case3Key, Case3Data), + ?line Case3Mac256_3 = crypto:hmac(sha256, Case3Key, Case3Data), ?line m(Case3Exp256, Case3Mac256_1), ?line m(Case3Exp256, Case3Mac256_2), + ?line m(Case3Exp256, Case3Mac256_3), ?line Case3Ctx384 = crypto:hmac_init(sha384, Case3Key), ?line Case3Ctx384_2 = crypto:hmac_update(Case3Ctx384, Case3Data), ?line Case3Mac384_1 = crypto:hmac_final(Case3Ctx384_2), ?line Case3Mac384_2 = crypto:sha384_mac(Case3Key, Case3Data), + ?line Case3Mac384_3 = crypto:hmac(sha384, Case3Key, Case3Data), ?line m(Case3Exp384, Case3Mac384_1), ?line m(Case3Exp384, Case3Mac384_2), + ?line m(Case3Exp384, Case3Mac384_3), ?line Case3Ctx512 = crypto:hmac_init(sha512, Case3Key), ?line Case3Ctx512_2 = crypto:hmac_update(Case3Ctx512, Case3Data), ?line Case3Mac512_1 = crypto:hmac_final(Case3Ctx512_2), ?line Case3Mac512_2 = crypto:sha512_mac(Case3Key, Case3Data), + ?line Case3Mac512_3 = crypto:hmac(sha512, Case3Key, Case3Data), ?line m(Case3Exp512, Case3Mac512_1), ?line m(Case3Exp512, Case3Mac512_2), + ?line m(Case3Exp512, Case3Mac512_3), %% Test Case 4 Case4Key = list_to_binary(lists:seq(1, 16#19)), @@ -575,29 +763,81 @@ hmac_rfc4231_do() -> ?line Case4Ctx224_2 = crypto:hmac_update(Case4Ctx224, Case4Data), ?line Case4Mac224_1 = crypto:hmac_final(Case4Ctx224_2), ?line Case4Mac224_2 = crypto:sha224_mac(Case4Key, Case4Data), + ?line Case4Mac224_3 = crypto:hmac(sha224, Case4Key, Case4Data), ?line m(Case4Exp224, Case4Mac224_1), ?line m(Case4Exp224, Case4Mac224_2), + ?line m(Case4Exp224, Case4Mac224_3), ?line Case4Ctx256 = crypto:hmac_init(sha256, Case4Key), ?line Case4Ctx256_2 = crypto:hmac_update(Case4Ctx256, Case4Data), ?line Case4Mac256_1 = crypto:hmac_final(Case4Ctx256_2), ?line Case4Mac256_2 = crypto:sha256_mac(Case4Key, Case4Data), + ?line Case4Mac256_3 = crypto:hmac(sha256, Case4Key, Case4Data), ?line m(Case4Exp256, Case4Mac256_1), ?line m(Case4Exp256, Case4Mac256_2), + ?line m(Case4Exp256, Case4Mac256_3), ?line Case4Ctx384 = crypto:hmac_init(sha384, Case4Key), ?line Case4Ctx384_2 = crypto:hmac_update(Case4Ctx384, Case4Data), ?line Case4Mac384_1 = crypto:hmac_final(Case4Ctx384_2), ?line Case4Mac384_2 = crypto:sha384_mac(Case4Key, Case4Data), + ?line Case4Mac384_3 = crypto:hmac(sha384, Case4Key, Case4Data), ?line m(Case4Exp384, Case4Mac384_1), ?line m(Case4Exp384, Case4Mac384_2), + ?line m(Case4Exp384, Case4Mac384_3), ?line Case4Ctx512 = crypto:hmac_init(sha512, Case4Key), ?line Case4Ctx512_2 = crypto:hmac_update(Case4Ctx512, Case4Data), ?line Case4Mac512_1 = crypto:hmac_final(Case4Ctx512_2), ?line Case4Mac512_2 = crypto:sha512_mac(Case4Key, Case4Data), + ?line Case4Mac512_3 = crypto:hmac(sha512, Case4Key, Case4Data), ?line m(Case4Exp512, Case4Mac512_1), ?line m(Case4Exp512, Case4Mac512_2), + ?line m(Case4Exp512, Case4Mac512_3), + + %% Test Case 5 + Case5Key = binary:copy(<<16#0c>>, 20), + Case5Data = <<"Test With Truncation">>, + Case5Exp224 = hexstr2bin("0e2aea68a90c8d37c988bcdb9fca6fa8"), + Case5Exp256 = hexstr2bin("a3b6167473100ee06e0c796c2955552b"), + Case5Exp384 = hexstr2bin("3abf34c3503b2a23a46efc619baef897"), + Case5Exp512 = hexstr2bin("415fad6271580a531d4179bc891d87a6"), + + ?line Case5Ctx224 = crypto:hmac_init(sha224, Case5Key), + ?line Case5Ctx224_2 = crypto:hmac_update(Case5Ctx224, Case5Data), + ?line Case5Mac224_1 = crypto:hmac_final_n(Case5Ctx224_2, 16), + ?line Case5Mac224_2 = crypto:sha224_mac(Case5Key, Case5Data, 16), + ?line Case5Mac224_3 = crypto:hmac(sha224, Case5Key, Case5Data, 16), + ?line m(Case5Exp224, Case5Mac224_1), + ?line m(Case5Exp224, Case5Mac224_2), + ?line m(Case5Exp224, Case5Mac224_3), + + ?line Case5Ctx256 = crypto:hmac_init(sha256, Case5Key), + ?line Case5Ctx256_2 = crypto:hmac_update(Case5Ctx256, Case5Data), + ?line Case5Mac256_1 = crypto:hmac_final_n(Case5Ctx256_2, 16), + ?line Case5Mac256_2 = crypto:sha256_mac(Case5Key, Case5Data, 16), + ?line Case5Mac256_3 = crypto:hmac(sha256, Case5Key, Case5Data, 16), + ?line m(Case5Exp256, Case5Mac256_1), + ?line m(Case5Exp256, Case5Mac256_2), + ?line m(Case5Exp256, Case5Mac256_3), + + ?line Case5Ctx384 = crypto:hmac_init(sha384, Case5Key), + ?line Case5Ctx384_2 = crypto:hmac_update(Case5Ctx384, Case5Data), + ?line Case5Mac384_1 = crypto:hmac_final_n(Case5Ctx384_2, 16), + ?line Case5Mac384_2 = crypto:sha384_mac(Case5Key, Case5Data, 16), + ?line Case5Mac384_3 = crypto:hmac(sha384, Case5Key, Case5Data, 16), + ?line m(Case5Exp384, Case5Mac384_1), + ?line m(Case5Exp384, Case5Mac384_2), + ?line m(Case5Exp384, Case5Mac384_3), + + ?line Case5Ctx512 = crypto:hmac_init(sha512, Case5Key), + ?line Case5Ctx512_2 = crypto:hmac_update(Case5Ctx512, Case5Data), + ?line Case5Mac512_1 = crypto:hmac_final_n(Case5Ctx512_2, 16), + ?line Case5Mac512_2 = crypto:sha512_mac(Case5Key, Case5Data, 16), + ?line Case5Mac512_3 = crypto:hmac(sha512, Case5Key, Case5Data, 16), + ?line m(Case5Exp512, Case5Mac512_1), + ?line m(Case5Exp512, Case5Mac512_2), + ?line m(Case5Exp512, Case5Mac512_3), %% Test Case 6 Case6Key = binary:copy(<<16#aa>>, 131), @@ -618,29 +858,37 @@ hmac_rfc4231_do() -> ?line Case6Ctx224_2 = crypto:hmac_update(Case6Ctx224, Case6Data), ?line Case6Mac224_1 = crypto:hmac_final(Case6Ctx224_2), ?line Case6Mac224_2 = crypto:sha224_mac(Case6Key, Case6Data), + ?line Case6Mac224_3 = crypto:hmac(sha224, Case6Key, Case6Data), ?line m(Case6Exp224, Case6Mac224_1), ?line m(Case6Exp224, Case6Mac224_2), + ?line m(Case6Exp224, Case6Mac224_3), ?line Case6Ctx256 = crypto:hmac_init(sha256, Case6Key), ?line Case6Ctx256_2 = crypto:hmac_update(Case6Ctx256, Case6Data), ?line Case6Mac256_1 = crypto:hmac_final(Case6Ctx256_2), ?line Case6Mac256_2 = crypto:sha256_mac(Case6Key, Case6Data), + ?line Case6Mac256_3 = crypto:hmac(sha256, Case6Key, Case6Data), ?line m(Case6Exp256, Case6Mac256_1), ?line m(Case6Exp256, Case6Mac256_2), + ?line m(Case6Exp256, Case6Mac256_3), ?line Case6Ctx384 = crypto:hmac_init(sha384, Case6Key), ?line Case6Ctx384_2 = crypto:hmac_update(Case6Ctx384, Case6Data), ?line Case6Mac384_1 = crypto:hmac_final(Case6Ctx384_2), ?line Case6Mac384_2 = crypto:sha384_mac(Case6Key, Case6Data), + ?line Case6Mac384_3 = crypto:hmac(sha384, Case6Key, Case6Data), ?line m(Case6Exp384, Case6Mac384_1), ?line m(Case6Exp384, Case6Mac384_2), + ?line m(Case6Exp384, Case6Mac384_3), ?line Case6Ctx512 = crypto:hmac_init(sha512, Case6Key), ?line Case6Ctx512_2 = crypto:hmac_update(Case6Ctx512, Case6Data), ?line Case6Mac512_1 = crypto:hmac_final(Case6Ctx512_2), ?line Case6Mac512_2 = crypto:sha512_mac(Case6Key, Case6Data), + ?line Case6Mac512_3 = crypto:hmac(sha512, Case6Key, Case6Data), ?line m(Case6Exp512, Case6Mac512_1), ?line m(Case6Exp512, Case6Mac512_2), + ?line m(Case6Exp512, Case6Mac512_3), %% Test Case 7 Case7Key = binary:copy(<<16#aa>>, 131), @@ -663,29 +911,37 @@ hmac_rfc4231_do() -> ?line Case7Ctx224_2 = crypto:hmac_update(Case7Ctx224, Case7Data), ?line Case7Mac224_1 = crypto:hmac_final(Case7Ctx224_2), ?line Case7Mac224_2 = crypto:sha224_mac(Case7Key, Case7Data), + ?line Case7Mac224_3 = crypto:hmac(sha224, Case7Key, Case7Data), ?line m(Case7Exp224, Case7Mac224_1), ?line m(Case7Exp224, Case7Mac224_2), + ?line m(Case7Exp224, Case7Mac224_3), ?line Case7Ctx256 = crypto:hmac_init(sha256, Case7Key), ?line Case7Ctx256_2 = crypto:hmac_update(Case7Ctx256, Case7Data), ?line Case7Mac256_1 = crypto:hmac_final(Case7Ctx256_2), ?line Case7Mac256_2 = crypto:sha256_mac(Case7Key, Case7Data), + ?line Case7Mac256_3 = crypto:hmac(sha256, Case7Key, Case7Data), ?line m(Case7Exp256, Case7Mac256_1), ?line m(Case7Exp256, Case7Mac256_2), + ?line m(Case7Exp256, Case7Mac256_3), ?line Case7Ctx384 = crypto:hmac_init(sha384, Case7Key), ?line Case7Ctx384_2 = crypto:hmac_update(Case7Ctx384, Case7Data), ?line Case7Mac384_1 = crypto:hmac_final(Case7Ctx384_2), ?line Case7Mac384_2 = crypto:sha384_mac(Case7Key, Case7Data), + ?line Case7Mac384_3 = crypto:hmac(sha384, Case7Key, Case7Data), ?line m(Case7Exp384, Case7Mac384_1), ?line m(Case7Exp384, Case7Mac384_2), + ?line m(Case7Exp384, Case7Mac384_3), ?line Case7Ctx512 = crypto:hmac_init(sha512, Case7Key), ?line Case7Ctx512_2 = crypto:hmac_update(Case7Ctx512, Case7Data), ?line Case7Mac512_1 = crypto:hmac_final(Case7Ctx512_2), ?line Case7Mac512_2 = crypto:sha512_mac(Case7Key, Case7Data), + ?line Case7Mac512_3 = crypto:hmac(sha512, Case7Key, Case7Data), ?line m(Case7Exp512, Case7Mac512_1), - ?line m(Case7Exp512, Case7Mac512_2). + ?line m(Case7Exp512, Case7Mac512_2), + ?line m(Case7Exp512, Case7Mac512_3). hmac_update_md5_io(doc) -> ["Generate an MD5 HMAC using hmac_init, hmac_update, and hmac_final. " @@ -719,7 +975,33 @@ hmac_update_md5_n(Config) when is_list(Config) -> ?line Mac = crypto:hmac_final_n(Ctx3, 12), ?line Exp = crypto:md5_mac_96(Key, lists:flatten([Data, Data2])), ?line m(Exp, Mac). - +%% +%% +ripemd160(doc) -> + ["Generate RIPEMD160 message digests and check the result."]; +ripemd160(suite) -> + []; +ripemd160(Config) when is_list(Config) -> + ?line m(crypto:hash(ripemd160,"abc"), + hexstr2bin("8EB208F7E05D987A9B044A8E98C6B087F15A0BFC")), + ?line m(crypto:hash(ripemd160,"abcdbcdecdefdefgefghfghighijhijkijkljklmklm" + "nlmnomnopnopq"), + hexstr2bin("12A053384A9C0C88E405A06C27DCF49ADA62EB2B")). + + +%% +%% +ripemd160_update(doc) -> + ["Generate RIPEMD160 message digests by using ripemd160_init," + "ripemd160_update, and ripemd160_final and check the result."]; +ripemd160_update(suite) -> + []; +ripemd160_update(Config) when is_list(Config) -> + ?line Ctx = crypto:hash_init(ripemd160), + ?line Ctx1 = crypto:hash_update(Ctx, "abcdbcdecdefdefgefghfghighi"), + ?line Ctx2 = crypto:hash_update(Ctx1, "jhijkijkljklmklmnlmnomnopnopq"), + ?line m(crypto:hash_final(Ctx2), + hexstr2bin("12A053384A9C0C88E405A06C27DCF49ADA62EB2B")). %% %% @@ -1838,7 +2120,7 @@ worker_loop(N, Config) -> aes_cfb, aes_cbc, des_cbc_iter, rand_uniform_test, strong_rand_test, rsa_verify_test, exor_test, rc4_test, rc4_stream_test, mod_exp_test, hmac_update_md5, hmac_update_sha, hmac_update_sha256, hmac_update_sha512, - hmac_rfc4231, + hmac_rfc2202, hmac_rfc4231, aes_ctr_stream }, F = element(random:uniform(size(Funcs)),Funcs), diff --git a/lib/debugger/src/int.erl b/lib/debugger/src/int.erl index b3a8a07f03..1c9f2eddd1 100644 --- a/lib/debugger/src/int.erl +++ b/lib/debugger/src/int.erl @@ -626,18 +626,18 @@ find_src(Beam) -> find_beam(Mod, Src) -> SrcDir = filename:dirname(Src), - BeamFile = packages:last(Mod) ++ code:objfile_extension(), + BeamFile = atom_to_list(Mod) ++ code:objfile_extension(), File = filename:join(SrcDir, BeamFile), case is_file(File) of true -> File; - false -> find_beam_1(Mod, SrcDir) + false -> find_beam_1(Mod, BeamFile, SrcDir) end. -find_beam_1(Mod, SrcDir) -> - RootDir = find_root_dir(SrcDir, packages:first(Mod)), +find_beam_1(Mod, BeamFile, SrcDir) -> + RootDir = filename:dirname(SrcDir), EbinDir = filename:join(RootDir, "ebin"), CodePath = [EbinDir | code:get_path()], - BeamFile = to_path(Mod) ++ code:objfile_extension(), + BeamFile = atom_to_list(Mod) ++ code:objfile_extension(), lists:foldl(fun(_, Beam) when is_list(Beam) -> Beam; (Dir, error) -> File = filename:join(Dir, BeamFile), @@ -649,14 +649,6 @@ find_beam_1(Mod, SrcDir) -> error, CodePath). -to_path(X) -> - filename:join(packages:split(X)). - -find_root_dir(Dir, [_|Ss]) -> - find_root_dir(filename:dirname(Dir), Ss); -find_root_dir(Dir, []) -> - filename:dirname(Dir). - check_beam(BeamBin) when is_binary(BeamBin) -> case beam_lib:chunks(BeamBin, [abstract_code,exports]) of {ok,{_Mod,[{abstract_code,no_abstract_code}|_]}} -> @@ -711,14 +703,11 @@ scan_module_name_2(_, _) -> scan_module_name_3(Ts) -> case erl_parse:parse_form(Ts) of - {ok, {attribute,_,module,{M,_}}} -> module_atom(M); - {ok, {attribute,_,module,M}} -> module_atom(M); + {ok, {attribute,_,module,{M,_}}} -> M; + {ok, {attribute,_,module,M}} -> M; _ -> error end. -module_atom(A) when is_atom(A) -> A; -module_atom(L) when is_list(L) -> list_to_atom(packages:concat(L)). - %%--Stop interpreting modules----------------------------------------- del_mod(AbsMod, Dist) -> diff --git a/lib/dialyzer/test/options1_SUITE_data/src/compiler/sys_pre_expand.erl b/lib/dialyzer/test/options1_SUITE_data/src/compiler/sys_pre_expand.erl index 08bc6cb147..41b7cb248d 100644 --- a/lib/dialyzer/test/options1_SUITE_data/src/compiler/sys_pre_expand.erl +++ b/lib/dialyzer/test/options1_SUITE_data/src/compiler/sys_pre_expand.erl @@ -149,14 +149,12 @@ forms([], St) -> {[],St}. %% Process an attribute, this just affects the state. attribute(module, {Module, As}, St) -> - M = package_to_string(Module), - St#expand{module=list_to_atom(M), - package = packages:strip_last(M), + true = is_atom(Module), + St#expand{module=Module, parameters=As}; attribute(module, Module, St) -> - M = package_to_string(Module), - St#expand{module=list_to_atom(M), - package = packages:strip_last(M)}; + true = is_atom(Module), + St#expand{module=Module}; attribute(export, Es, St) -> St#expand{exports=union(from_list(Es), St#expand.exports)}; attribute(import, Is, St) -> @@ -226,8 +224,6 @@ pattern({tuple,Line,Ps}, St0) -> %%pattern({struct,Line,Tag,Ps}, St0) -> %% {TPs,TPsvs,St1} = pattern_list(Ps, St0), %% {{tuple,Line,[{atom,Line,Tag}|TPs]},TPsvs,St1}; -pattern({record_field,_,_,_}=M, St) -> - {expand_package(M, St), [], [], St}; % must be a package name pattern({record_index,Line,Name,Field}, St) -> {index_expr(Line, Field, Name, record_fields(Name, St)),[],[],St}; pattern({record,Line,Name,Pfs}, St0) -> @@ -401,8 +397,6 @@ expr({tuple,Line,Es0}, Vs, St0) -> %%expr({struct,Line,Tag,Es0}, Vs, St0) -> %% {Es1,Esvs,Esus,St1} = expr_list(Es0, Vs, St0), %% {{tuple,Line,[{atom,Line,Tag}|Es1]},Esvs,Esus,St1}; -expr({record_field,_,_,_}=M, _Vs, St) -> - {expand_package(M, St), [], [], St}; % must be a package name expr({record_index,Line,Name,F}, Vs, St) -> I = index_expr(Line, F, Name, record_fields(Name, St)), expr(I, Vs, St); @@ -483,10 +477,7 @@ expr({call,Line,{atom,La,N},As0}, Vs, St0) -> end end end; -expr({call,Line,{record_field,_,_,_}=M,As0}, Vs, St0) -> - expr({call,Line,expand_package(M, St0),As0}, Vs, St0); -expr({call,Line,{remote,Lr,M,F},As0}, Vs, St0) -> - M1 = expand_package(M, St0), +expr({call,Line,{remote,Lr,M1,F},As0}, Vs, St0) -> {[M2,F1|As1],Asvs,Asus,St1} = expr_list([M1,F|As0], Vs, St0), {{call,Line,{remote,Lr,M2,F1},As1},Asvs,Asus,St1}; expr({call,Line,{tuple,_,[{atom,_,_}=M,{atom,_,_}=F]},As}, Vs, St) -> @@ -922,32 +913,6 @@ string_to_conses(Line, Cs, Tail) -> foldr(fun (C, T) -> {cons,Line,{char,Line,C},T} end, Tail, Cs). -%% In syntax trees, module/package names are atoms or lists of atoms. - -package_to_string(A) when atom(A) -> atom_to_list(A); -package_to_string(L) when list(L) -> packages:concat(L). - -expand_package({atom,L,A} = M, St) -> - case dict:find(A, St#expand.mod_imports) of - {ok, A1} -> - {atom,L,A1}; - error -> - case packages:is_segmented(A) of - true -> - M; - false -> - M1 = packages:concat(St#expand.package, A), - {atom,L,list_to_atom(M1)} - end - end; -expand_package(M, _St) -> - case erl_parse:package_segments(M) of - error -> - M; - M1 -> - {atom,element(2,M),list_to_atom(package_to_string(M1))} - end. - %% Create a case-switch on true/false, generating badarg for all other %% values. @@ -1005,15 +970,10 @@ new_in_all(Before, Region) -> %% Handle import declarations and est for imported functions. No need to %% check when building imports as code is correct. -import({Mod0,Fs}, St) -> - Mod = list_to_atom(package_to_string(Mod0)), +import({Mod,Fs}, St) -> + true = is_atom(Mod), Mfs = from_list(Fs), - St#expand{imports=add_imports(Mod, Mfs, St#expand.imports)}; -import(Mod0, St) -> - Mod = package_to_string(Mod0), - Key = list_to_atom(packages:last(Mod)), - St#expand{mod_imports=dict:store(Key, list_to_atom(Mod), - St#expand.mod_imports)}. + St#expand{imports=add_imports(Mod, Mfs, St#expand.imports)}. add_imports(Mod, [F|Fs], Is) -> add_imports(Mod, Fs, orddict:store(F, Mod, Is)); diff --git a/lib/dialyzer/test/r9c_SUITE_data/results/mnesia b/lib/dialyzer/test/r9c_SUITE_data/results/mnesia index 17f2bd2ea8..1aac46f5b2 100644 --- a/lib/dialyzer/test/r9c_SUITE_data/results/mnesia +++ b/lib/dialyzer/test/r9c_SUITE_data/results/mnesia @@ -6,7 +6,7 @@ mnesia_bup.erl:111: The created fun has no local return mnesia_bup.erl:574: Function fallback_receiver/2 has no local return mnesia_bup.erl:967: Function uninstall_fallback_master/2 has no local return mnesia_checkpoint.erl:1014: The variable Error can never match since previous clauses completely covered the type {'ok',#checkpoint_args{nodes::[any()],retainers::[any(),...]}} -mnesia_checkpoint.erl:894: The call sys:handle_system_msg(Msg::any(),From::any(),'no_parent','mnesia_checkpoint',[],Cp::#checkpoint_args{}) breaks the contract (Msg,From,Parent,Module,Debug,Misc) -> Void when is_subtype(Msg,term()), is_subtype(From,{pid(),Tag::_}), is_subtype(Parent,pid()), is_subtype(Module,module()), is_subtype(Debug,[dbg_opt()]), is_subtype(Misc,term()), is_subtype(Void,term()) +mnesia_checkpoint.erl:894: The call sys:handle_system_msg(Msg::any(),From::any(),'no_parent','mnesia_checkpoint',[],Cp::#checkpoint_args{}) breaks the contract (Msg,From,Parent,Module,Debug,Misc) -> no_return() when is_subtype(Msg,term()), is_subtype(From,{pid(),Tag::_}), is_subtype(Parent,pid()), is_subtype(Module,module()), is_subtype(Debug,[dbg_opt()]), is_subtype(Misc,term()) mnesia_controller.erl:1666: The variable Tab can never match since previous clauses completely covered the type [any()] mnesia_controller.erl:1679: The pattern {'stop', Reason, Reply, State2} can never match the type {'noreply',_} | {'reply',_,_} | {'stop','shutdown',#state{}} mnesia_controller.erl:1685: The pattern {'noreply', State2, _Timeout} can never match the type {'reply',_,_} diff --git a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen.erl b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen.erl index 32d4a22645..5b33be9eff 100644 --- a/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen.erl +++ b/lib/dialyzer/test/r9c_SUITE_data/src/asn1/asn1ct_gen.erl @@ -295,7 +295,7 @@ gen_part_decode_funcs([_H|T],N) -> gen_part_decode_funcs([],N) -> if N > 0 -> - .emit([".",nl]); + emit([".",nl]); true -> ok end. diff --git a/lib/dialyzer/test/small_SUITE_data/results/port_info_test b/lib/dialyzer/test/small_SUITE_data/results/port_info_test index 863a3d61df..53d20a415b 100644 --- a/lib/dialyzer/test/small_SUITE_data/results/port_info_test +++ b/lib/dialyzer/test/small_SUITE_data/results/port_info_test @@ -1,7 +1,7 @@ port_info_test.erl:10: The pattern {'connected', 42} can never match the type 'undefined' | {'connected',pid()} -port_info_test.erl:14: The pattern {'registered_name', "42"} can never match the type 'undefined' | {'registered_name',atom()} +port_info_test.erl:14: The pattern {'registered_name', "42"} can never match the type 'undefined' | [] | {'registered_name',atom()} port_info_test.erl:19: The pattern {'output', 42} can never match the type 'undefined' | {'connected',pid()} port_info_test.erl:24: Guard test 'links' =:= Atom::'connected' can never succeed -port_info_test.erl:28: The pattern {'gazonk', _} can never match the type 'undefined' | {'connected' | 'id' | 'input' | 'links' | 'name' | 'os_pid' | 'output' | 'registered_name',atom() | pid() | [pid() | char()] | integer()} +port_info_test.erl:28: The pattern {'gazonk', _} can never match the type 'undefined' | [] | {'connected' | 'id' | 'input' | 'links' | 'locking' | 'memory' | 'monitors' | 'name' | 'os_pid' | 'output' | 'parallelism' | 'queue_size' | 'registered_name',atom() | pid() | [pid() | char() | {'process',pid()}] | non_neg_integer()} port_info_test.erl:32: The pattern {'os_pid', "42"} can never match the type 'undefined' | {'os_pid','undefined' | non_neg_integer()} diff --git a/lib/edoc/src/edoc.erl b/lib/edoc/src/edoc.erl index 5a599e6e97..599036f380 100644 --- a/lib/edoc/src/edoc.erl +++ b/lib/edoc/src/edoc.erl @@ -456,14 +456,14 @@ expand_sources(Ss, Opts) -> end, expand_sources(Ss1, Suffix, sets:new(), [], []). -expand_sources([{P, F, D} | Fs], Suffix, S, As, Ms) -> - M = list_to_atom(packages:concat(P, filename:rootname(F, Suffix))), +expand_sources([{'', F, D} | Fs], Suffix, S, As, Ms) -> + M = list_to_atom(filename:rootname(F, Suffix)), case sets:is_element(M, S) of true -> expand_sources(Fs, Suffix, S, As, Ms); false -> S1 = sets:add_element(M, S), - expand_sources(Fs, Suffix, S1, [{M, P, F, D} | As], + expand_sources(Fs, Suffix, S1, [{M, '', F, D} | As], [M | Ms]) end; expand_sources([], _Suffix, _S, As, Ms) -> diff --git a/lib/edoc/src/edoc_doclet.erl b/lib/edoc/src/edoc_doclet.erl index d6561e10fc..a0c1ae1c0f 100644 --- a/lib/edoc/src/edoc_doclet.erl +++ b/lib/edoc/src/edoc_doclet.erl @@ -192,7 +192,7 @@ source({M, P, Name, Path}, Dir, Suffix, Env, Set, Private, Hidden, andalso ((not is_hidden(Doc)) orelse Hidden) of true -> Text = edoc:layout(Doc, Options), - Name1 = packages:last(M) ++ Suffix, + Name1 = atom_to_list(M) ++ Suffix, Encoding = [{encoding,encoding(Doc)}], edoc_lib:write_file(Text, Dir, Name1, P, Encoding), {sets:add_element(Module, Set), Error}; @@ -205,9 +205,9 @@ source({M, P, Name, Path}, Dir, Suffix, Env, Set, Private, Hidden, end. check_name(M, M0, P0, File) -> - P = list_to_atom(packages:strip_last(M)), - N = packages:last(M), - N0 = packages:last(M0), + P = '', + N = M, + N0 = M0, case N of [$? | _] -> %% A module name of the form '?...' is assumed to be caused diff --git a/lib/edoc/src/edoc_extract.erl b/lib/edoc/src/edoc_extract.erl index dcab816f54..67a95e80aa 100644 --- a/lib/edoc/src/edoc_extract.erl +++ b/lib/edoc/src/edoc_extract.erl @@ -121,7 +121,7 @@ source1(Tree, File0, Env, Opts, TypeDocs) -> Module = get_module_info(Tree, File), {Header, Footer, Entries} = collect(Forms, Module), Name = Module#module.name, - Package = list_to_atom(packages:strip_last(Name)), + Package = '', Env1 = Env#env{module = Name, package = Package, root = edoc_refs:relative_package_path('', Package)}, diff --git a/lib/edoc/src/edoc_lib.erl b/lib/edoc/src/edoc_lib.erl index 942715b8ee..3d193c4bfa 100644 --- a/lib/edoc/src/edoc_lib.erl +++ b/lib/edoc/src/edoc_lib.erl @@ -269,6 +269,10 @@ is_name_1(_) -> false. to_atom(A) when is_atom(A) -> A; to_atom(S) when is_list(S) -> list_to_atom(S). + +to_list(A) when is_atom(A) -> atom_to_list(A); +to_list(S) when is_list(S) -> S. + %% @private unique([X | Xs]) -> [X | unique(Xs, X)]; @@ -695,8 +699,7 @@ write_file(Text, Dir, Name, Package) -> write_file(Text, Dir, Name, Package, [{encoding,latin1}]). write_file(Text, Dir, Name, Package, Options) -> - Dir1 = filename:join([Dir | packages:split(Package)]), - File = filename:join(Dir1, Name), + File = filename:join([Dir, to_list(Package), Name]), ok = filelib:ensure_dir(File), case file:open(File, [write] ++ Options) of {ok, FD} -> @@ -836,7 +839,7 @@ find_sources(Path, Pkg, Rec, Ext, Opts) -> lists:flatten(find_sources_1(Path, to_atom(Pkg), Rec, Ext, Skip)). find_sources_1([P | Ps], Pkg, Rec, Ext, Skip) -> - Dir = filename:join(P, filename:join(packages:split(Pkg))), + Dir = filename:join(P, atom_to_list(Pkg)), Fs1 = find_sources_1(Ps, Pkg, Rec, Ext, Skip), case filelib:is_dir(Dir) of true -> @@ -862,9 +865,9 @@ find_sources_2(Dir, Pkg, Rec, Ext, Skip) -> [] end. -find_sources_3(Es, Dir, Pkg, Rec, Ext, Skip) -> +find_sources_3(Es, Dir, '', Rec, Ext, Skip) -> [find_sources_2(filename:join(Dir, E), - to_atom(packages:concat(Pkg, E)), Rec, Ext, Skip) + to_atom(E), Rec, Ext, Skip) || E <- Es, is_package_dir(E, Dir)]. is_source_file(Name, Ext) -> @@ -876,16 +879,16 @@ is_package_dir(Name, Dir) -> andalso filelib:is_dir(filename:join(Dir, Name)). %% @private -find_file([P | Ps], Pkg, Name) -> - Dir = filename:join(P, filename:join(packages:split(Pkg))), - File = filename:join(Dir, Name), +find_file([P | Ps], []=Pkg, Name) -> + Pkg = [], + File = filename:join(P, Name), case filelib:is_file(File) of true -> File; false -> find_file(Ps, Pkg, Name) end; -find_file([], _Pkg, _Name) -> +find_file([], [], _Name) -> "". %% @private diff --git a/lib/edoc/src/edoc_parser.yrl b/lib/edoc/src/edoc_parser.yrl index 9351217618..cf1a2d6b11 100644 --- a/lib/edoc/src/edoc_parser.yrl +++ b/lib/edoc/src/edoc_parser.yrl @@ -318,10 +318,7 @@ tok_val(T) -> element(3, T). tok_line(T) -> element(2, T). -qname([A]) -> - A; % avoid unnecessary call to packages:concat/1. -qname(List) -> - list_to_atom(packages:concat(lists:reverse(List))). +qname([A]) -> A. union(Ts) -> case Ts of diff --git a/lib/edoc/src/edoc_refs.erl b/lib/edoc/src/edoc_refs.erl index 1f578a3b83..ea439490ed 100644 --- a/lib/edoc/src/edoc_refs.erl +++ b/lib/edoc/src/edoc_refs.erl @@ -126,7 +126,7 @@ abs_uri({package, P}, Env) -> module_ref(M, Env) -> case (Env#env.modules)(M) of "" -> - File = packages:last(M) ++ Env#env.file_suffix, + File = atom_to_list(M) ++ Env#env.file_suffix, Path = relative_module_path(M, Env#env.package), join_uri(Path, escape_uri(File)); Base -> @@ -134,8 +134,7 @@ module_ref(M, Env) -> end. module_absref(M, Env) -> - join_segments(packages:split(M)) - ++ escape_uri(Env#env.file_suffix). + escape_uri(atom_to_list(M)) ++ escape_uri(Env#env.file_suffix). package_ref(P, Env) -> case (Env#env.packages)(P) of @@ -147,7 +146,7 @@ package_ref(P, Env) -> end. package_absref(P, Env) -> - join_uri(join_segments(packages:split(P)), + join_uri(escape_uri(atom_to_list(P)), escape_uri(Env#env.package_summary)). app_ref(A, Env) -> @@ -179,14 +178,11 @@ join_segments([S | Ss]) -> %% The empty string is returned if the To module has only one segment, %% implying a local reference. -relative_module_path(To, From) -> - case first(packages:split(To)) of - [] -> ""; - P -> relative_path(P, packages:split(From)) - end. +relative_module_path(_To, _From) -> + "". relative_package_path(To, From) -> - relative_path(packages:split(To), packages:split(From)). + relative_path([atom_to_list(To)], [atom_to_list(From)]). %% This takes two lists of path segments (From, To). Note that an empty %% string will be returned if the paths are the same. Empty leading @@ -210,6 +206,3 @@ relative_path_2([], []) -> ""; relative_path_2([], Ts) -> join_segments(Ts). - -first([H | T]) when T /= [] -> [H | first(T)]; -first(_) -> []. diff --git a/lib/eldap/src/eldap.erl b/lib/eldap/src/eldap.erl index b3249d4f56..5753cc4749 100644 --- a/lib/eldap/src/eldap.erl +++ b/lib/eldap/src/eldap.erl @@ -320,7 +320,7 @@ present(Attribute) when is_list(Attribute) -> %%% will match entries containing: 'sn: Tornkvist' %%% substrings(Type, SubStr) when is_list(Type), is_list(SubStr) -> - Ss = {'SubstringFilter_substrings',v_substr(SubStr)}, + Ss = v_substr(SubStr), {substrings,#'SubstringFilter'{type = Type, substrings = Ss}}. diff --git a/lib/erl_interface/aclocal.m4 b/lib/erl_interface/aclocal.m4 index 9578cd35c4..5d555a5123 100644 --- a/lib/erl_interface/aclocal.m4 +++ b/lib/erl_interface/aclocal.m4 @@ -1849,6 +1849,32 @@ case $erl_gethrvtime in esac ])dnl +dnl ---------------------------------------------------------------------- +dnl +dnl LM_TRY_ENABLE_CFLAG +dnl +dnl +dnl Tries a CFLAG and sees if it can be enabled without compiler errors +dnl $1: textual cflag to add +dnl $2: variable to store the modified CFLAG in +dnl Usage example LM_TRY_ENABLE_CFLAG([-Werror=return-type], [CFLAGS]) +dnl +dnl +AC_DEFUN([LM_TRY_ENABLE_CFLAG], [ + AC_MSG_CHECKING([if we can add $1 to CFLAGS]) + saved_CFLAGS=$CFLAGS; + CFLAGS="$1 $CFLAGS"; + AC_TRY_COMPILE([],[return 0;],can_enable_flag=true,can_enable_flag=false) + CFLAGS=$saved_CFLAGS; + if test "X$can_enable_flag" = "Xtrue"; then + AC_MSG_RESULT([yes]) + AS_VAR_SET($2, "$1 $CFLAGS") + else + AC_MSG_RESULT([no]) + AS_VAR_SET($2, "$CFLAGS") + fi +]) + dnl ERL_TRY_LINK_JAVA(CLASSES, FUNCTION-BODY dnl [ACTION_IF_FOUND [, ACTION-IF-NOT-FOUND]]) dnl Freely inspired by AC_TRY_LINK. (Maybe better to create a diff --git a/lib/erl_interface/configure.in b/lib/erl_interface/configure.in index 97f1cff345..d511f2e240 100644 --- a/lib/erl_interface/configure.in +++ b/lib/erl_interface/configure.in @@ -273,6 +273,8 @@ esac AC_SUBST(WFLAGS) if test "x$GCC" = xyes; then + # Treat certain GCC warnings as errors + LM_TRY_ENABLE_CFLAG([-Werror=return-type], [WERRORFLAGS]) WFLAGS="-Wall -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Winline" # check which GCC version GCC_VERSION=`$CC -v 2>&1 | sed -n 's/gcc version //p'` @@ -287,8 +289,10 @@ if test "x$GCC" = xyes; then *) WFLAGS="$WFLAGS -fno-strict-aliasing";; esac + CFLAGS="$WERRORFLAGS $CFLAGS" else WFLAGS="" + WERRORFLAGS="" fi # --------------------------------------------------------------------------- diff --git a/lib/eunit/include/eunit.hrl b/lib/eunit/include/eunit.hrl index 7b460ee5e8..8ebdb6ba16 100644 --- a/lib/eunit/include/eunit.hrl +++ b/lib/eunit/include/eunit.hrl @@ -125,8 +125,8 @@ -ifndef(UNDER_EUNIT). -define(UNDER_EUNIT, (?MATCHES({current_function,{eunit_proc,_,_}}, - .erlang:process_info(.erlang:group_leader(), - current_function)))). + erlang:process_info(erlang:group_leader(), + current_function)))). -endif. %% The plain assert macro should be defined to do nothing if this file @@ -143,14 +143,14 @@ ((fun () -> case (BoolExpr) of true -> ok; - __V -> .erlang:error({assertion_failed, - [{module, ?MODULE}, - {line, ?LINE}, - {expression, (??BoolExpr)}, - {expected, true}, - {value, case __V of false -> __V; - _ -> {not_a_boolean,__V} - end}]}) + __V -> erlang:error({assertion_failed, + [{module, ?MODULE}, + {line, ?LINE}, + {expression, (??BoolExpr)}, + {expected, true}, + {value, case __V of false -> __V; + _ -> {not_a_boolean,__V} + end}]}) end end)())). -endif. @@ -171,12 +171,12 @@ ((fun () -> case (Expr) of Guard -> ok; - __V -> .erlang:error({assertMatch_failed, - [{module, ?MODULE}, - {line, ?LINE}, - {expression, (??Expr)}, - {pattern, (??Guard)}, - {value, __V}]}) + __V -> erlang:error({assertMatch_failed, + [{module, ?MODULE}, + {line, ?LINE}, + {expression, (??Expr)}, + {pattern, (??Guard)}, + {value, __V}]}) end end)())). -endif. @@ -190,12 +190,12 @@ ((fun () -> __V = (Expr), case __V of - Guard -> .erlang:error({assertNotMatch_failed, - [{module, ?MODULE}, - {line, ?LINE}, - {expression, (??Expr)}, - {pattern, (??Guard)}, - {value, __V}]}); + Guard -> erlang:error({assertNotMatch_failed, + [{module, ?MODULE}, + {line, ?LINE}, + {expression, (??Expr)}, + {pattern, (??Guard)}, + {value, __V}]}); _ -> ok end end)())). @@ -211,12 +211,12 @@ ((fun (__X) -> case (Expr) of __X -> ok; - __V -> .erlang:error({assertEqual_failed, - [{module, ?MODULE}, - {line, ?LINE}, - {expression, (??Expr)}, - {expected, __X}, - {value, __V}]}) + __V -> erlang:error({assertEqual_failed, + [{module, ?MODULE}, + {line, ?LINE}, + {expression, (??Expr)}, + {expected, __X}, + {value, __V}]}) end end)(Expect))). -endif. @@ -229,11 +229,11 @@ -define(assertNotEqual(Unexpected, Expr), ((fun (__X) -> case (Expr) of - __X -> .erlang:error({assertNotEqual_failed, - [{module, ?MODULE}, - {line, ?LINE}, - {expression, (??Expr)}, - {value, __X}]}); + __X -> erlang:error({assertNotEqual_failed, + [{module, ?MODULE}, + {line, ?LINE}, + {expression, (??Expr)}, + {value, __X}]}); _ -> ok end end)(Unexpected))). @@ -249,7 +249,7 @@ -define(assertException(Class, Term, Expr), ((fun () -> try (Expr) of - __V -> .erlang:error({assertException_failed, + __V -> erlang:error({assertException_failed, [{module, ?MODULE}, {line, ?LINE}, {expression, (??Expr)}, @@ -260,16 +260,16 @@ catch Class:Term -> ok; __C:__T -> - .erlang:error({assertException_failed, - [{module, ?MODULE}, - {line, ?LINE}, - {expression, (??Expr)}, - {pattern, - "{ "++(??Class)++" , "++(??Term) - ++" , [...] }"}, - {unexpected_exception, - {__C, __T, - .erlang:get_stacktrace()}}]}) + erlang:error({assertException_failed, + [{module, ?MODULE}, + {line, ?LINE}, + {expression, (??Expr)}, + {pattern, + "{ "++(??Class)++" , "++(??Term) + ++" , [...] }"}, + {unexpected_exception, + {__C, __T, + erlang:get_stacktrace()}}]}) end end)())). -endif. @@ -300,17 +300,17 @@ Class -> case __T of Term -> - .erlang:error({assertNotException_failed, - [{module, ?MODULE}, - {line, ?LINE}, - {expression, (??Expr)}, - {pattern, - "{ "++(??Class)++" , " - ++(??Term)++" , [...] }"}, - {unexpected_exception, - {__C, __T, - .erlang:get_stacktrace() - }}]}); + erlang:error({assertNotException_failed, + [{module, ?MODULE}, + {line, ?LINE}, + {expression, (??Expr)}, + {pattern, + "{ "++(??Class)++" , " + ++(??Term)++" , [...] }"}, + {unexpected_exception, + {__C, __T, + erlang:get_stacktrace() + }}]}); _ -> ok end; _ -> ok @@ -325,17 +325,17 @@ %% require EUnit to be present at runtime, or at least eunit_lib.) %% these can be used for simply running commands in a controlled way --define(_cmd_(Cmd), (.eunit_lib:command(Cmd))). +-define(_cmd_(Cmd), (eunit_lib:command(Cmd))). -define(cmdStatus(N, Cmd), ((fun () -> case ?_cmd_(Cmd) of {(N), __Out} -> __Out; - {__N, _} -> .erlang:error({command_failed, - [{module, ?MODULE}, - {line, ?LINE}, - {command, (Cmd)}, - {expected_status,(N)}, - {status,__N}]}) + {__N, _} -> erlang:error({command_failed, + [{module, ?MODULE}, + {line, ?LINE}, + {command, (Cmd)}, + {expected_status,(N)}, + {status,__N}]}) end end)())). -define(_cmdStatus(N, Cmd), ?_test(?cmdStatus(N, Cmd))). @@ -351,12 +351,12 @@ ((fun () -> case ?_cmd_(Cmd) of {(N), _} -> ok; - {__N, _} -> .erlang:error({assertCmd_failed, - [{module, ?MODULE}, - {line, ?LINE}, - {command, (Cmd)}, - {expected_status,(N)}, - {status,__N}]}) + {__N, _} -> erlang:error({assertCmd_failed, + [{module, ?MODULE}, + {line, ?LINE}, + {command, (Cmd)}, + {expected_status,(N)}, + {status,__N}]}) end end)())). -endif. @@ -369,12 +369,12 @@ ((fun () -> case ?_cmd_(Cmd) of {_, (T)} -> ok; - {_, __T} -> .erlang:error({assertCmdOutput_failed, - [{module, ?MODULE}, - {line, ?LINE}, - {command,(Cmd)}, - {expected_output,(T)}, - {output,__T}]}) + {_, __T} -> erlang:error({assertCmdOutput_failed, + [{module, ?MODULE}, + {line, ?LINE}, + {command,(Cmd)}, + {expected_output,(T)}, + {output,__T}]}) end end)())). -endif. @@ -395,12 +395,12 @@ -else. -define(debugMsg(S), (begin - .io:fwrite(user, <<"~s:~w:~w: ~s\n">>, - [?FILE, ?LINE, self(), S]), + io:fwrite(user, <<"~s:~w:~w: ~s\n">>, + [?FILE, ?LINE, self(), S]), ok end)). -define(debugHere, (?debugMsg("<-"))). --define(debugFmt(S, As), (?debugMsg(.io_lib:format((S), (As))))). +-define(debugFmt(S, As), (?debugMsg(io_lib:format((S), (As))))). -define(debugVal(E), ((fun (__V) -> ?debugFmt(<<"~s = ~P">>, [(??E), __V, 15]), diff --git a/lib/eunit/src/eunit_autoexport.erl b/lib/eunit/src/eunit_autoexport.erl index 099bcb222e..36ae3b71d7 100644 --- a/lib/eunit/src/eunit_autoexport.erl +++ b/lib/eunit/src/eunit_autoexport.erl @@ -80,10 +80,9 @@ rewrite([F | Fs], As, Module, Test) -> rewrite(Fs, [F | As], Module, Test); rewrite([], As, Module, Test) -> {if Test -> - EUnit = {record_field,0,{atom,0,''},{atom,0,eunit}}, [{function,0,test,0, [{clause,0,[],[], - [{call,0,{remote,0,EUnit,{atom,0,test}}, + [{call,0,{remote,0,{atom,0,eunit},{atom,0,test}}, [{atom,0,Module}]}]}]} | As]; true -> @@ -92,9 +91,7 @@ rewrite([], As, Module, Test) -> Test}. module_decl(Name, M, Fs, Exports) -> - Module = if is_atom(Name) -> Name; - true -> list_to_atom(packages:concat(Name)) - end, + Module = Name, {Fs1, Test} = rewrite(Fs, [], Module, true), Es = if Test -> [{test,0} | Exports]; true -> Exports diff --git a/lib/kernel/doc/src/Makefile b/lib/kernel/doc/src/Makefile index 5e04bff0c1..de3ca1e176 100644 --- a/lib/kernel/doc/src/Makefile +++ b/lib/kernel/doc/src/Makefile @@ -58,7 +58,6 @@ XML_REF3_FILES = application.xml \ net_adm.xml \ net_kernel.xml \ os.xml \ - packages.xml \ pg2.xml \ rpc.xml \ seq_trace.xml \ diff --git a/lib/kernel/doc/src/file.xml b/lib/kernel/doc/src/file.xml index 536b98b5f5..e30ade1bd2 100644 --- a/lib/kernel/doc/src/file.xml +++ b/lib/kernel/doc/src/file.xml @@ -170,6 +170,18 @@ </desc> </func> <func> + <name name="allocate" arity="3"/> + <fsummary>Allocate file space</fsummary> + <desc> + <p><c>allocate/3</c> can be used to preallocate space for a file.</p> + <p>This function only succeeds in platforms that implement this + feature. When it succeeds, space is preallocated for the file but + the file size might not be updated. This behaviour depends on the + preallocation implementation. To guarantee the file size is updated + one must truncate the file to the new size.</p> + </desc> + </func> + <func> <name name="change_group" arity="2"/> <fsummary>Change group of a file</fsummary> <desc> diff --git a/lib/kernel/src/Makefile b/lib/kernel/src/Makefile index c76ff9e2f0..60291bbce6 100644 --- a/lib/kernel/src/Makefile +++ b/lib/kernel/src/Makefile @@ -107,7 +107,6 @@ MODULES = \ net_adm \ net_kernel \ os \ - packages \ pg2 \ ram_file \ rpc \ diff --git a/lib/kernel/src/code.erl b/lib/kernel/src/code.erl index c808ac7cb7..361f2bdf8a 100644 --- a/lib/kernel/src/code.erl +++ b/lib/kernel/src/code.erl @@ -359,7 +359,6 @@ load_code_server_prerequisites() -> hipe_unified_loader, lists, os, - packages, unicode], [M = M:module_info(module) || M <- Needed], ok. @@ -413,7 +412,7 @@ which(Module) when is_atom(Module) -> end. which2(Module) -> - Base = to_path(Module), + Base = atom_to_list(Module), File = filename:basename(Base) ++ objfile_extension(), Path = get_path(), which(File, filename:dirname(Base), Path). @@ -547,9 +546,6 @@ has_ext(Ext, Extlen, File) -> _ -> false end. -to_path(X) -> - filename:join(packages:split(X)). - -spec load_native_code_for_all_loaded() -> ok. load_native_code_for_all_loaded() -> Architecture = erlang:system_info(hipe_architecture), diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl index 00ad923466..b2d2c19f78 100644 --- a/lib/kernel/src/code_server.erl +++ b/lib/kernel/src/code_server.erl @@ -1229,7 +1229,7 @@ load_abs(File, Mod0, Caller, St) -> end. try_load_module(Mod, Dir, Caller, St) -> - File = filename:append(Dir, to_path(Mod) ++ + File = filename:append(Dir, to_list(Mod) ++ objfile_extension()), case erl_prim_loader:get_file(File) of error -> @@ -1347,7 +1347,7 @@ load_file_1(Mod, Caller, #state{cache=Cache}=St0) -> end. mod_to_bin([Dir|Tail], Mod) -> - File = filename:append(Dir, to_path(Mod) ++ objfile_extension()), + File = filename:append(Dir, to_list(Mod) ++ objfile_extension()), case erl_prim_loader:get_file(File) of error -> mod_to_bin(Tail, Mod); @@ -1356,7 +1356,7 @@ mod_to_bin([Dir|Tail], Mod) -> end; mod_to_bin([], Mod) -> %% At last, try also erl_prim_loader's own method - File = to_path(Mod) ++ objfile_extension(), + File = to_list(Mod) ++ objfile_extension(), case erl_prim_loader:get_file(File) of error -> error; % No more alternatives ! @@ -1570,6 +1570,3 @@ to_list(X) when is_atom(X) -> atom_to_list(X). to_atom(X) when is_atom(X) -> X; to_atom(X) when is_list(X) -> list_to_atom(X). - -to_path(X) -> - filename:join(packages:split(X)). diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl index de3eaad5a1..16f2dde464 100644 --- a/lib/kernel/src/file.erl +++ b/lib/kernel/src/file.erl @@ -38,7 +38,7 @@ %% Specialized -export([ipread_s32bu_p32bu/3]). %% Generic file contents. --export([open/2, close/1, advise/4, +-export([open/2, close/1, advise/4, allocate/3, read/2, write/2, pread/2, pread/3, pwrite/2, pwrite/3, read_line/1, @@ -490,6 +490,18 @@ advise(#file_descriptor{module = Module} = Handle, Offset, Length, Advise) -> advise(_, _, _, _) -> {error, badarg}. +-spec allocate(File, Offset, Length) -> + 'ok' | {'error', posix()} when + File :: io_device(), + Offset :: non_neg_integer(), + Length :: non_neg_integer(). + +allocate(File, Offset, Length) when is_pid(File) -> + R = file_request(File, {allocate, Offset, Length}), + wait_file_reply(File, R); +allocate(#file_descriptor{module = Module} = Handle, Offset, Length) -> + Module:allocate(Handle, Offset, Length). + -spec read(IoDevice, Number) -> {ok, Data} | eof | {error, Reason} when IoDevice :: io_device() | atom(), Number :: non_neg_integer(), diff --git a/lib/kernel/src/file_io_server.erl b/lib/kernel/src/file_io_server.erl index acaffe1e41..fad2ed7fb3 100644 --- a/lib/kernel/src/file_io_server.erl +++ b/lib/kernel/src/file_io_server.erl @@ -211,6 +211,10 @@ file_request({advise,Offset,Length,Advise}, Reply -> {reply,Reply,State} end; +file_request({allocate, Offset, Length}, + #state{handle = Handle} = State) -> + Reply = ?PRIM_FILE:allocate(Handle, Offset, Length), + {reply, Reply, State}; file_request({pread,At,Sz}, #state{handle=Handle,buf=Buf,read_mode=ReadMode}=State) -> case position(Handle, At, Buf) of diff --git a/lib/kernel/src/kernel.app.src b/lib/kernel/src/kernel.app.src index 17ab84c177..9a20baf8d0 100644 --- a/lib/kernel/src/kernel.app.src +++ b/lib/kernel/src/kernel.app.src @@ -28,7 +28,6 @@ application_starter, auth, code, - packages, code_server, dist_util, erl_boot_server, diff --git a/lib/kernel/src/packages.erl b/lib/kernel/src/packages.erl deleted file mode 100644 index e0b1f36b85..0000000000 --- a/lib/kernel/src/packages.erl +++ /dev/null @@ -1,158 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2002-2009. All Rights Reserved. -%% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%% -%% %CopyrightEnd% -%% --module(packages). - --export([to_string/1, concat/1, concat/2, is_valid/1, is_segmented/1, - split/1, last/1, first/1, strip_last/1, find_modules/1, - find_modules/2]). - -%% A package name (or a package-qualified module name) may be an atom or -%% a string (list of nonnegative integers) - not a deep list, and not a -%% list containing atoms. A name may be empty, but may not contain two -%% consecutive period (`.') characters or end with a period character. - --type package_name() :: atom() | string(). - --spec to_string(package_name()) -> string(). -to_string(Name) when is_atom(Name) -> - atom_to_list(Name); -to_string(Name) -> - Name. - -%% `concat' does not insert a leading period if the first segment is -%% empty. However, the result may contain leading, consecutive or -%% dangling period characters, if any of the segments after the first -%% are empty. Use 'is_valid' to check the result if necessary. - --spec concat(package_name(), package_name()) -> string(). -concat(A, B) -> - concat([A, B]). - --spec concat([package_name()]) -> string(). -concat([H | T]) when is_atom(H) -> - concat([atom_to_list(H) | T]); -concat(["" | T]) -> - concat_1(T); -concat(L) -> - concat_1(L). - -concat_1([H | T]) when is_atom(H) -> - concat_1([atom_to_list(H) | T]); -concat_1([H]) -> - H; -concat_1([H | T]) -> - H ++ "." ++ concat_1(T); -concat_1([]) -> - ""; -concat_1(Name) -> - erlang:error({badarg, Name}). - --spec is_valid(package_name()) -> boolean(). -is_valid(Name) when is_atom(Name) -> - is_valid_1(atom_to_list(Name)); -is_valid([$. | _]) -> - false; -is_valid(Name) -> - is_valid_1(Name). - -is_valid_1([$.]) -> false; -is_valid_1([$., $. | _]) -> false; -is_valid_1([H | T]) when is_integer(H), H >= 0 -> - is_valid_1(T); -is_valid_1([]) -> true; -is_valid_1(_) -> false. - --spec split(package_name()) -> [string()]. -split(Name) when is_atom(Name) -> - split_1(atom_to_list(Name), []); -split(Name) -> - split_1(Name, []). - -split_1([$. | T], Cs) -> - [lists:reverse(Cs) | split_1(T, [])]; -split_1([H | T], Cs) when is_integer(H), H >= 0 -> - split_1(T, [H | Cs]); -split_1([], Cs) -> - [lists:reverse(Cs)]; -split_1(_, _) -> - erlang:error(badarg). - -%% This is equivalent to testing if `split(Name)' yields a list of -%% length larger than one (i.e., if the name can be split into two or -%% more segments), but is cheaper. - --spec is_segmented(package_name()) -> boolean(). -is_segmented(Name) when is_atom(Name) -> - is_segmented_1(atom_to_list(Name)); -is_segmented(Name) -> - is_segmented_1(Name). - -is_segmented_1([$. | _]) -> true; -is_segmented_1([H | T]) when is_integer(H), H >= 0 -> - is_segmented_1(T); -is_segmented_1([]) -> false; -is_segmented_1(_) -> - erlang:error(badarg). - --spec last(package_name()) -> string(). -last(Name) -> - last_1(split(Name)). - -last_1([H]) -> H; -last_1([_ | T]) -> last_1(T). - --spec first(package_name()) -> [string()]. -first(Name) -> - first_1(split(Name)). - -first_1([H | T]) when T =/= [] -> [H | first_1(T)]; -first_1(_) -> []. - --spec strip_last(package_name()) -> string(). -strip_last(Name) -> - concat(first(Name)). - -%% This finds all modules available for a given package, using the -%% current code server search path. (There is no guarantee that the -%% modules are loadable; only that the object files exist.) - --spec find_modules(package_name()) -> [string()]. -find_modules(P) -> - find_modules(P, code:get_path()). - --spec find_modules(package_name(), [string()]) -> [string()]. -find_modules(P, Paths) -> - P1 = filename:join(packages:split(P)), - find_modules(P1, Paths, code:objfile_extension(), sets:new()). - -find_modules(P, [Path | Paths], Ext, S0) -> - case file:list_dir(filename:join(Path, P)) of - {ok, Fs} -> - Fs1 = [F || F <- Fs, filename:extension(F) =:= Ext], - S1 = lists:foldl(fun (F, S) -> - F1 = filename:rootname(F, Ext), - sets:add_element(F1, S) - end, - S0, Fs1), - find_modules(P, Paths, Ext, S1); - _ -> - find_modules(P, Paths, Ext, S0) - end; -find_modules(_P, [], _Ext, S) -> - sets:to_list(S). diff --git a/lib/kernel/src/ram_file.erl b/lib/kernel/src/ram_file.erl index 48ea871433..ca881ff8a4 100644 --- a/lib/kernel/src/ram_file.erl +++ b/lib/kernel/src/ram_file.erl @@ -29,6 +29,7 @@ %% Specialized file operations -export([get_size/1, get_file/1, set_file/2, get_file_close/1]). -export([compress/1, uncompress/1, uuencode/1, uudecode/1, advise/4]). +-export([allocate/3]). -export([open_mode/1]). %% used by ftp-file @@ -72,6 +73,7 @@ -define(RAM_FILE_UUDECODE, 36). -define(RAM_FILE_SIZE, 37). -define(RAM_FILE_ADVISE, 38). +-define(RAM_FILE_ALLOCATE, 39). %% Open modes for RAM_FILE_OPEN -define(RAM_FILE_MODE_READ, 1). @@ -383,6 +385,11 @@ advise(#file_descriptor{module = ?MODULE, data = Port}, Offset, advise(#file_descriptor{}, _Offset, _Length, _Advise) -> {error, enotsup}. +allocate(#file_descriptor{module = ?MODULE, data = Port}, Offset, Length) -> + call_port(Port, <<?RAM_FILE_ALLOCATE, Offset:64/signed, Length:64/signed>>); +allocate(#file_descriptor{}, _Offset, _Length) -> + {error, enotsup}. + %%%----------------------------------------------------------------- diff --git a/lib/kernel/test/Makefile b/lib/kernel/test/Makefile index 8eca37029d..7fd3afe93c 100644 --- a/lib/kernel/test/Makefile +++ b/lib/kernel/test/Makefile @@ -73,6 +73,7 @@ MODULES= \ seq_trace_SUITE \ wrap_log_reader_SUITE \ cleanup \ + ignore_cores \ zlib_SUITE \ loose_node \ sendfile_SUITE diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl index 9c507fd437..914f0d6127 100644 --- a/lib/kernel/test/file_SUITE.erl +++ b/lib/kernel/test/file_SUITE.erl @@ -84,6 +84,8 @@ -export([advise/1]). +-export([allocate/1]). + -export([standard_io/1,mini_server/1]). %% Debug exports @@ -116,7 +118,7 @@ groups() -> {files, [], [{group, open}, {group, pos}, {group, file_info}, {group, consult}, {group, eval}, {group, script}, - truncate, sync, datasync, advise]}, + truncate, sync, datasync, advise, allocate]}, {open, [], [open1, old_modes, new_modes, path_open, close, access, read_write, pread_write, append, open_errors, @@ -1617,6 +1619,74 @@ advise(Config) when is_list(Config) -> ?line test_server:timetrap_cancel(Dog), ok. +allocate(suite) -> []; +allocate(doc) -> "Tests that ?FILE_MODULE:allocate/3 at least doesn't crash."; +allocate(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(5)), + ?line PrivDir = ?config(priv_dir, Config), + ?line Allocate = filename:join(PrivDir, + atom_to_list(?MODULE) + ++"_allocate.fil"), + + Line1 = "Hello\n", + Line2 = "World!\n", + + ?line {ok, Fd} = ?FILE_MODULE:open(Allocate, [write, binary]), + allocate_and_assert(Fd, 1, iolist_size([Line1, Line2])), + ?line ok = io:format(Fd, "~s", [Line1]), + ?line ok = io:format(Fd, "~s", [Line2]), + ?line ok = ?FILE_MODULE:close(Fd), + + ?line {ok, Fd2} = ?FILE_MODULE:open(Allocate, [write, binary]), + allocate_and_assert(Fd2, 1, iolist_size(Line1)), + ?line ok = io:format(Fd2, "~s", [Line1]), + ?line ok = io:format(Fd2, "~s", [Line2]), + ?line ok = ?FILE_MODULE:close(Fd2), + + ?line {ok, Fd3} = ?FILE_MODULE:open(Allocate, [write, binary]), + allocate_and_assert(Fd3, 1, iolist_size(Line1) + 1), + ?line ok = io:format(Fd3, "~s", [Line1]), + ?line ok = io:format(Fd3, "~s", [Line2]), + ?line ok = ?FILE_MODULE:close(Fd3), + + ?line {ok, Fd4} = ?FILE_MODULE:open(Allocate, [write, binary]), + allocate_and_assert(Fd4, 1, 4 * iolist_size([Line1, Line2])), + ?line ok = io:format(Fd4, "~s", [Line1]), + ?line ok = io:format(Fd4, "~s", [Line2]), + ?line ok = ?FILE_MODULE:close(Fd4), + + ?line [] = flush(), + ?line test_server:timetrap_cancel(Dog), + ok. + +allocate_and_assert(Fd, Offset, Length) -> + % Just verify that calls to ?PRIM_FILE:allocate/3 don't crash or have + % any other negative side effect. We can't really asssert against a + % specific return value, because support for file space pre-allocation + % depends on the OS, OS version and underlying filesystem. + % + % The Linux kernel added support for fallocate() in version 2.6.23, + % which currently works only for the ext4, ocfs2, xfs and btrfs file + % systems. posix_fallocate() is available in glibc as of version + % 2.1.94, but it was buggy until glibc version 2.7. + % + % Mac OS X, as of version 10.3, supports the fcntl operation F_PREALLOCATE. + % + % Solaris supports posix_fallocate() but only for the UFS file system + % apparently (not supported for ZFS). + % + % FreeBSD 9.0 is the first FreeBSD release supporting posix_fallocate(). + % + % For Windows there's apparently no way to pre-allocate file space, at + % least with same semantics as posix_fallocate(), fallocate() and + % fcntl F_PREALLOCATE. + Result = ?FILE_MODULE:allocate(Fd, Offset, Length), + case os:type() of + {win32, _} -> + ?line {error, enotsup} = Result; + _ -> + ?line _ = Result + end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/lib/kernel/test/heart_SUITE.erl b/lib/kernel/test/heart_SUITE.erl index 2ec3b7c297..320b23bea1 100644 --- a/lib/kernel/test/heart_SUITE.erl +++ b/lib/kernel/test/heart_SUITE.erl @@ -83,10 +83,10 @@ init_per_suite(Config) when is_list(Config) -> {win32, windows} -> {skipped, "No use to run on Windows 95/98"}; _ -> - Config + ignore_cores:init(Config) end. end_per_suite(Config) when is_list(Config) -> - Config. + ignore_cores:fini(Config). start_check(Type, Name) -> @@ -188,8 +188,20 @@ reboot(Config) when is_list(Config) -> %% Check that a node is up and running after a crash. %% This test exhausts the atom table on the remote node. %% ERL_CRASH_DUMP_SECONDS=0 will force beam not to dump an erl_crash.dump. +%% May currently dump core in beam debug build due to lock-order violation +%% This should be removed when a non-lockad information retriever is implemented +%% for crash dumps node_start_immediately_after_crash(suite) -> {req, [{time, 10}]}; node_start_immediately_after_crash(Config) when is_list(Config) -> + Config2 = ignore_cores:setup(?MODULE, node_start_immediately_after_crash, Config, true), + try + node_start_immediately_after_crash_test(Config2) + after + ignore_cores:restore(Config2) + end. + + +node_start_immediately_after_crash_test(Config) when is_list(Config) -> {ok, Node} = start_check(loose, heart_test_imm, [{"ERL_CRASH_DUMP_SECONDS", "0"}]), ok = rpc:call(Node, heart, set_cmd, @@ -228,8 +240,19 @@ node_start_immediately_after_crash(Config) when is_list(Config) -> %% This test exhausts the atom table on the remote node. %% ERL_CRASH_DUMP_SECONDS=10 will force beam %% to only dump an erl_crash.dump for 10 seconds. +%% May currently dump core in beam debug build due to lock-order violation +%% This should be removed when a non-lockad information retriever is implemented +%% for crash dumps node_start_soon_after_crash(suite) -> {req, [{time, 10}]}; node_start_soon_after_crash(Config) when is_list(Config) -> + Config2 = ignore_cores:setup(?MODULE, node_start_soon_after_crash, Config, true), + try + node_start_soon_after_crash_test(Config2) + after + ignore_cores:restore(Config2) + end. + +node_start_soon_after_crash_test(Config) when is_list(Config) -> {ok, Node} = start_check(loose, heart_test_soon, [{"ERL_CRASH_DUMP_SECONDS", "10"}]), ok = rpc:call(Node, heart, set_cmd, diff --git a/lib/kernel/test/ignore_cores.erl b/lib/kernel/test/ignore_cores.erl new file mode 100644 index 0000000000..8b1ac0fe6c --- /dev/null +++ b/lib/kernel/test/ignore_cores.erl @@ -0,0 +1,158 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-2010. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%%%------------------------------------------------------------------- +%%% File : ignore_cores.erl +%%% Author : Rickard Green <rickard.s.green@ericsson.com> +%%% Description : +%%% +%%% Created : 11 Feb 2008 by Rickard Green <rickard.s.green@ericsson.com> +%%%------------------------------------------------------------------- + +-module(ignore_cores). + +-include_lib("test_server/include/test_server.hrl"). + +-export([init/1, fini/1, setup/3, setup/4, restore/1, dir/1]). + +-record(ignore_cores, {org_cwd, + org_path, + org_pwd_env, + ign_dir = false, + cores_dir = false}). + +%% +%% Takes a testcase config +%% + +init(Config) -> + {ok, OrgCWD} = file:get_cwd(), + [{ignore_cores, + #ignore_cores{org_cwd = OrgCWD, + org_path = code:get_path(), + org_pwd_env = os:getenv("PWD")}} + | lists:keydelete(ignore_cores, 1, Config)]. + +fini(Config) -> + #ignore_cores{org_cwd = OrgCWD, + org_path = OrgPath, + org_pwd_env = OrgPWD} = ?config(ignore_cores, Config), + ok = file:set_cwd(OrgCWD), + true = code:set_path(OrgPath), + case OrgPWD of + false -> ok; + _ -> true = os:putenv("PWD", OrgPWD) + end, + lists:keydelete(ignore_cores, 1, Config). + +setup(Suite, Testcase, Config) -> + setup(Suite, Testcase, Config, false). + +setup(Suite, Testcase, Config, SetCwd) when is_atom(Suite), + is_atom(Testcase), + is_list(Config) -> + #ignore_cores{org_cwd = OrgCWD, + org_path = OrgPath, + org_pwd_env = OrgPWD} = ?config(ignore_cores, Config), + Path = lists:map(fun (".") -> OrgCWD; (Dir) -> Dir end, OrgPath), + true = code:set_path(Path), + PrivDir = ?config(priv_dir, Config), + IgnDir = filename:join([PrivDir, + atom_to_list(Suite) + ++ "_" + ++ atom_to_list(Testcase) + ++ "_wd"]), + ok = file:make_dir(IgnDir), + case SetCwd of + false -> + ok; + _ -> + ok = file:set_cwd(IgnDir), + OrgPWD = case os:getenv("PWD") of + false -> false; + PWD -> + os:putenv("PWD", IgnDir), + PWD + end + end, + ok = file:write_file(filename:join([IgnDir, "ignore_core_files"]), <<>>), + %% cores are dumped in /cores on MacOS X + CoresDir = case {?t:os_type(), filelib:is_dir("/cores")} of + {{unix,darwin}, true} -> + filelib:fold_files("/cores", + "^core.*$", + false, + fun (C,Cs) -> [C|Cs] end, + []); + _ -> + false + end, + lists:keyreplace(ignore_cores, + 1, + Config, + {ignore_cores, + #ignore_cores{org_cwd = OrgCWD, + org_path = OrgPath, + org_pwd_env = OrgPWD, + ign_dir = IgnDir, + cores_dir = CoresDir}}). + +restore(Config) -> + #ignore_cores{org_cwd = OrgCWD, + org_path = OrgPath, + org_pwd_env = OrgPWD, + ign_dir = IgnDir, + cores_dir = CoresDir} = ?config(ignore_cores, Config), + try + case CoresDir of + false -> + ok; + _ -> + %% Move cores dumped by these testcases in /cores + %% to cwd. + lists:foreach(fun (C) -> + case lists:member(C, CoresDir) of + true -> ok; + _ -> + Dst = filename:join( + [IgnDir, + filename:basename(C)]), + {ok, _} = file:copy(C, Dst), + file:delete(C) + end + end, + filelib:fold_files("/cores", + "^core.*$", + false, + fun (C,Cs) -> [C|Cs] end, + [])) + end + after + catch file:set_cwd(OrgCWD), + catch code:set_path(OrgPath), + case OrgPWD of + false -> ok; + _ -> catch os:putenv("PWD", OrgPWD) + end + end. + + +dir(Config) -> + #ignore_cores{ign_dir = Dir} = ?config(ignore_cores, Config), + Dir. diff --git a/lib/kernel/test/prim_file_SUITE.erl b/lib/kernel/test/prim_file_SUITE.erl index a56746bbc4..4e93a593b3 100644 --- a/lib/kernel/test/prim_file_SUITE.erl +++ b/lib/kernel/test/prim_file_SUITE.erl @@ -57,6 +57,8 @@ %% System probe functions that might be handy to check from the shell -export([unix_free/1]). +-export([allocate/1]). + -include_lib("test_server/include/test_server.hrl"). -include_lib("kernel/include/file.hrl"). @@ -87,7 +89,7 @@ groups() -> cur_dir_1a, cur_dir_1b]}, {files, [], [{group, open}, {group, pos}, {group, file_info}, - truncate, sync, datasync, advise, large_write]}, + truncate, sync, datasync, advise, large_write, allocate]}, {open, [], [open1, modes, close, access, read_write, pread_write, append, exclusive]}, @@ -1359,6 +1361,76 @@ check_large_write(Dog, Fd, _, _, []) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +allocate(suite) -> []; +allocate(doc) -> "Tests that ?PRIM_FILE:allocate/3 at least doesn't crash."; +allocate(Config) when is_list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(5)), + ?line PrivDir = ?config(priv_dir, Config), + ?line Allocate = filename:join(PrivDir, + atom_to_list(?MODULE) + ++"_allocate.fil"), + + Line1 = "Hello\n", + Line2 = "World!\n", + + ?line {ok, Fd} = ?PRIM_FILE:open(Allocate, [write, binary]), + allocate_and_assert(Fd, 1, iolist_size([Line1, Line2])), + ?line ok = ?PRIM_FILE:write(Fd, Line1), + ?line ok = ?PRIM_FILE:write(Fd, Line2), + ?line ok = ?PRIM_FILE:close(Fd), + + ?line {ok, Fd2} = ?PRIM_FILE:open(Allocate, [write, binary]), + allocate_and_assert(Fd2, 1, iolist_size(Line1)), + ?line ok = ?PRIM_FILE:write(Fd2, Line1), + ?line ok = ?PRIM_FILE:write(Fd2, Line2), + ?line ok = ?PRIM_FILE:close(Fd2), + + ?line {ok, Fd3} = ?PRIM_FILE:open(Allocate, [write, binary]), + allocate_and_assert(Fd3, 1, iolist_size(Line1) + 1), + ?line ok = ?PRIM_FILE:write(Fd3, Line1), + ?line ok = ?PRIM_FILE:write(Fd3, Line2), + ?line ok = ?PRIM_FILE:close(Fd3), + + ?line {ok, Fd4} = ?PRIM_FILE:open(Allocate, [write, binary]), + allocate_and_assert(Fd4, 1, 4 * iolist_size([Line1, Line2])), + ?line ok = ?PRIM_FILE:write(Fd4, Line1), + ?line ok = ?PRIM_FILE:write(Fd4, Line2), + ?line ok = ?PRIM_FILE:close(Fd4), + + ?line test_server:timetrap_cancel(Dog), + ok. + +allocate_and_assert(Fd, Offset, Length) -> + % Just verify that calls to ?PRIM_FILE:allocate/3 don't crash or have + % any other negative side effect. We can't really asssert against a + % specific return value, because support for file space pre-allocation + % depends on the OS, OS version and underlying filesystem. + % + % The Linux kernel added support for fallocate() in version 2.6.23, + % which currently works only for the ext4, ocfs2, xfs and btrfs file + % systems. posix_fallocate() is available in glibc as of version + % 2.1.94, but it was buggy until glibc version 2.7. + % + % Mac OS X, as of version 10.3, supports the fcntl operation F_PREALLOCATE. + % + % Solaris supports posix_fallocate() but only for the UFS file system + % apparently (not supported for ZFS). + % + % FreeBSD 9.0 is the first FreeBSD release supporting posix_fallocate(). + % + % For Windows there's apparently no way to pre-allocate file space, at + % least with similar API/semantics as posix_fallocate(), fallocate() or + % fcntl F_PREALLOCATE. + Result = ?PRIM_FILE:allocate(Fd, Offset, Length), + case os:type() of + {win32, _} -> + ?line {error, enotsup} = Result; + _ -> + ?line _ = Result + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + delete_a(suite) -> []; delete_a(doc) -> []; delete_a(Config) when is_list(Config) -> diff --git a/lib/megaco/aclocal.m4 b/lib/megaco/aclocal.m4 new file mode 100644 index 0000000000..5d555a5123 --- /dev/null +++ b/lib/megaco/aclocal.m4 @@ -0,0 +1,1906 @@ +dnl +dnl %CopyrightBegin% +dnl +dnl Copyright Ericsson AB 1998-2012. All Rights Reserved. +dnl +dnl The contents of this file are subject to the Erlang Public License, +dnl Version 1.1, (the "License"); you may not use this file except in +dnl compliance with the License. You should have received a copy of the +dnl Erlang Public License along with this software. If not, it can be +dnl retrieved online at http://www.erlang.org/. +dnl +dnl Software distributed under the License is distributed on an "AS IS" +dnl basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +dnl the License for the specific language governing rights and limitations +dnl under the License. +dnl +dnl %CopyrightEnd% +dnl + +dnl +dnl aclocal.m4 +dnl +dnl Local macros used in configure.in. The Local Macros which +dnl could/should be part of autoconf are prefixed LM_, macros specific +dnl to the Erlang system are prefixed ERL_. +dnl + +AC_DEFUN(LM_PRECIOUS_VARS, +[ + +dnl ERL_TOP +AC_ARG_VAR(ERL_TOP, [Erlang/OTP top source directory]) + +dnl Tools +AC_ARG_VAR(CC, [C compiler]) +AC_ARG_VAR(CFLAGS, [C compiler flags]) +AC_ARG_VAR(STATIC_CFLAGS, [C compiler static flags]) +AC_ARG_VAR(CFLAG_RUNTIME_LIBRARY_PATH, [runtime library path linker flag passed via C compiler]) +AC_ARG_VAR(CPP, [C/C++ preprocessor]) +AC_ARG_VAR(CPPFLAGS, [C/C++ preprocessor flags]) +AC_ARG_VAR(CXX, [C++ compiler]) +AC_ARG_VAR(CXXFLAGS, [C++ compiler flags]) +AC_ARG_VAR(LD, [linker (is often overridden by configure)]) +AC_ARG_VAR(LDFLAGS, [linker flags (can be risky to set since LD may be overriden by configure)]) +AC_ARG_VAR(LIBS, [libraries]) +AC_ARG_VAR(DED_LD, [linker for Dynamic Erlang Drivers (set all DED_LD* variables or none)]) +AC_ARG_VAR(DED_LDFLAGS, [linker flags for Dynamic Erlang Drivers (set all DED_LD* variables or none)]) +AC_ARG_VAR(DED_LD_FLAG_RUNTIME_LIBRARY_PATH, [runtime library path linker flag for Dynamic Erlang Drivers (set all DED_LD* variables or none)]) +AC_ARG_VAR(LFS_CFLAGS, [large file support C compiler flags (set all LFS_* variables or none)]) +AC_ARG_VAR(LFS_LDFLAGS, [large file support linker flags (set all LFS_* variables or none)]) +AC_ARG_VAR(LFS_LIBS, [large file support libraries (set all LFS_* variables or none)]) +AC_ARG_VAR(RANLIB, [ranlib]) +AC_ARG_VAR(AR, [ar]) +AC_ARG_VAR(GETCONF, [getconf]) + +dnl Cross system root +AC_ARG_VAR(erl_xcomp_sysroot, [Absolute cross system root path (only used when cross compiling)]) +AC_ARG_VAR(erl_xcomp_isysroot, [Absolute cross system root include path (only used when cross compiling)]) + +dnl Cross compilation variables +AC_ARG_VAR(erl_xcomp_bigendian, [big endian system: yes|no (only used when cross compiling)]) +AC_ARG_VAR(erl_xcomp_double_middle_endian, [double-middle-endian system: yes|no (only used when cross compiling)]) +AC_ARG_VAR(erl_xcomp_linux_clock_gettime_correction, [clock_gettime() can be used for time correction: yes|no (only used when cross compiling)]) +AC_ARG_VAR(erl_xcomp_linux_nptl, [have Native POSIX Thread Library: yes|no (only used when cross compiling)]) +AC_ARG_VAR(erl_xcomp_linux_usable_sigusrx, [SIGUSR1 and SIGUSR2 can be used: yes|no (only used when cross compiling)]) +AC_ARG_VAR(erl_xcomp_linux_usable_sigaltstack, [have working sigaltstack(): yes|no (only used when cross compiling)]) +AC_ARG_VAR(erl_xcomp_poll, [have working poll(): yes|no (only used when cross compiling)]) +AC_ARG_VAR(erl_xcomp_kqueue, [have working kqueue(): yes|no (only used when cross compiling)]) +AC_ARG_VAR(erl_xcomp_putenv_copy, [putenv() stores key-value copy: yes|no (only used when cross compiling)]) +AC_ARG_VAR(erl_xcomp_reliable_fpe, [have reliable floating point exceptions: yes|no (only used when cross compiling)]) +AC_ARG_VAR(erl_xcomp_getaddrinfo, [have working getaddrinfo() for both IPv4 and IPv6: yes|no (only used when cross compiling)]) +AC_ARG_VAR(erl_xcomp_gethrvtime_procfs_ioctl, [have working gethrvtime() which can be used with procfs ioctl(): yes|no (only used when cross compiling)]) +AC_ARG_VAR(erl_xcomp_clock_gettime_cpu_time, [clock_gettime() can be used for retrieving process CPU time: yes|no (only used when cross compiling)]) +AC_ARG_VAR(erl_xcomp_after_morecore_hook, [__after_morecore_hook can track malloc()s core memory usage: yes|no (only used when cross compiling)]) +AC_ARG_VAR(erl_xcomp_dlsym_brk_wrappers, [dlsym(RTLD_NEXT, _) brk wrappers can track malloc()s core memory usage: yes|no (only used when cross compiling)]) + +]) + +AC_DEFUN(ERL_XCOMP_SYSROOT_INIT, +[ +erl_xcomp_without_sysroot=no +if test "$cross_compiling" = "yes"; then + test "$erl_xcomp_sysroot" != "" || erl_xcomp_without_sysroot=yes + test "$erl_xcomp_isysroot" != "" || erl_xcomp_isysroot="$erl_xcomp_sysroot" +else + erl_xcomp_sysroot= + erl_xcomp_isysroot= +fi +]) + +AC_DEFUN(LM_CHECK_GETCONF, +[ +if test "$cross_compiling" != "yes"; then + AC_CHECK_PROG([GETCONF], [getconf], [getconf], [false]) +else + dnl First check if we got a `<HOST>-getconf' in $PATH + host_getconf="$host_alias-getconf" + AC_CHECK_PROG([GETCONF], [$host_getconf], [$host_getconf], [false]) + if test "$GETCONF" = "false" && test "$erl_xcomp_sysroot" != ""; then + dnl We should perhaps give up if we have'nt found it by now, but at + dnl least in one Tilera MDE `getconf' under sysroot is a bourne + dnl shell script which we can use. We try to find `<HOST>-getconf' + dnl or `getconf' under sysconf, but only under sysconf since + dnl `getconf' in $PATH is almost guaranteed to be for the build + dnl machine. + GETCONF= + prfx="$erl_xcomp_sysroot" + AC_PATH_TOOL([GETCONF], [getconf], [false], + ["$prfx/usr/bin:$prfx/bin:$prfx/usr/local/bin"]) + fi +fi +]) + +dnl ---------------------------------------------------------------------- +dnl +dnl LM_WINDOWS_ENVIRONMENT +dnl +dnl +dnl Tries to determine thw windows build environment, i.e. +dnl MIXED_CYGWIN_VC or MIXED_MSYS_VC +dnl + +AC_DEFUN(LM_WINDOWS_ENVIRONMENT, +[ +MIXED_CYGWIN=no +MIXED_MSYS=no + +AC_MSG_CHECKING(for mixed cygwin or msys and native VC++ environment) +if test "X$host" = "Xwin32" -a "x$GCC" != "xyes"; then + if test -x /usr/bin/cygpath; then + CFLAGS="-O2" + MIXED_CYGWIN=yes + AC_MSG_RESULT([Cygwin and VC]) + MIXED_CYGWIN_VC=yes + CPPFLAGS="$CPPFLAGS -DERTS_MIXED_CYGWIN_VC" + elif test -x /usr/bin/msysinfo; then + CFLAGS="-O2" + MIXED_MSYS=yes + AC_MSG_RESULT([MSYS and VC]) + MIXED_MSYS_VC=yes + CPPFLAGS="$CPPFLAGS -DERTS_MIXED_MSYS_VC" + else + AC_MSG_RESULT([undeterminable]) + AC_MSG_ERROR(Seems to be mixed windows but not with cygwin, cannot handle this!) + fi +else + AC_MSG_RESULT([no]) + MIXED_CYGWIN_VC=no + MIXED_MSYS_VC=no +fi +AC_SUBST(MIXED_CYGWIN_VC) +AC_SUBST(MIXED_MSYS_VC) + +MIXED_VC=no +if test "x$MIXED_MSYS_VC" = "xyes" -o "x$MIXED_CYGWIN_VC" = "xyes" ; then + MIXED_VC=yes +fi + +AC_SUBST(MIXED_VC) + +if test "x$MIXED_MSYS" != "xyes"; then + AC_MSG_CHECKING(for mixed cygwin and native MinGW environment) + if test "X$host" = "Xwin32" -a "x$GCC" = x"yes"; then + if test -x /usr/bin/cygpath; then + CFLAGS="-O2" + MIXED_CYGWIN=yes + AC_MSG_RESULT([yes]) + MIXED_CYGWIN_MINGW=yes + CPPFLAGS="$CPPFLAGS -DERTS_MIXED_CYGWIN_MINGW" + else + AC_MSG_RESULT([undeterminable]) + AC_MSG_ERROR(Seems to be mixed windows but not with cygwin, cannot handle this!) + fi + else + AC_MSG_RESULT([no]) + MIXED_CYGWIN_MINGW=no + fi +else + MIXED_CYGWIN_MINGW=no +fi +AC_SUBST(MIXED_CYGWIN_MINGW) + +AC_MSG_CHECKING(if we mix cygwin with any native compiler) +if test "X$MIXED_CYGWIN" = "Xyes"; then + AC_MSG_RESULT([yes]) +else + AC_MSG_RESULT([no]) +fi + +AC_SUBST(MIXED_CYGWIN) + +AC_MSG_CHECKING(if we mix msys with another native compiler) +if test "X$MIXED_MSYS" = "Xyes" ; then + AC_MSG_RESULT([yes]) +else + AC_MSG_RESULT([no]) +fi + +AC_SUBST(MIXED_MSYS) +]) + +dnl ---------------------------------------------------------------------- +dnl +dnl LM_FIND_EMU_CC +dnl +dnl +dnl Tries fairly hard to find a C compiler that can handle jump tables. +dnl Defines the @EMU_CC@ variable for the makefiles and +dnl inserts NO_JUMP_TABLE in the header if one cannot be found... +dnl + +AC_DEFUN(LM_FIND_EMU_CC, + [AC_CACHE_CHECK(for a compiler that handles jumptables, + ac_cv_prog_emu_cc, + [ +AC_TRY_COMPILE([],[ +#if defined(__clang_major__) && __clang_major__ >= 3 + /* clang 3.x or later is fine */ +#elif defined(__llvm__) +#error "this version of llvm is unable to correctly compile beam_emu.c" +#endif + __label__ lbl1; + __label__ lbl2; + int x = magic(); + static void *jtab[2]; + + jtab[0] = &&lbl1; + jtab[1] = &&lbl2; + goto *jtab[x]; +lbl1: + return 1; +lbl2: + return 2; +],ac_cv_prog_emu_cc=$CC,ac_cv_prog_emu_cc=no) + +if test $ac_cv_prog_emu_cc = no; then + for ac_progname in emu_cc.sh gcc-4.2 gcc; do + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_progname; then + ac_cv_prog_emu_cc=$ac_dir/$ac_progname + break + fi + done + IFS="$ac_save_ifs" + if test $ac_cv_prog_emu_cc != no; then + break + fi + done +fi + +if test $ac_cv_prog_emu_cc != no; then + save_CC=$CC + save_CFLAGS=$CFLAGS + save_CPPFLAGS=$CPPFLAGS + CC=$ac_cv_prog_emu_cc + CFLAGS="" + CPPFLAGS="" + AC_TRY_COMPILE([],[ +#if defined(__clang_major__) && __clang_major__ >= 3 + /* clang 3.x or later is fine */ +#elif defined(__llvm__) +#error "this version of llvm is unable to correctly compile beam_emu.c" +#endif + __label__ lbl1; + __label__ lbl2; + int x = magic(); + static void *jtab[2]; + + jtab[0] = &&lbl1; + jtab[1] = &&lbl2; + goto *jtab[x]; + lbl1: + return 1; + lbl2: + return 2; + ],ac_cv_prog_emu_cc=$CC,ac_cv_prog_emu_cc=no) + CC=$save_CC + CFLAGS=$save_CFLAGS + CPPFLAGS=$save_CPPFLAGS +fi +]) +if test $ac_cv_prog_emu_cc = no; then + AC_DEFINE(NO_JUMP_TABLE,[],[Defined if no found C compiler can handle jump tables]) + EMU_CC=$CC +else + EMU_CC=$ac_cv_prog_emu_cc +fi +AC_SUBST(EMU_CC) +]) + + + +dnl ---------------------------------------------------------------------- +dnl +dnl LM_PROG_INSTALL_DIR +dnl +dnl This macro may be used by any OTP application. +dnl +dnl Figure out how to create directories with parents. +dnl (In my opinion INSTALL_DIR is a bad name, MKSUBDIRS or something is better) +dnl +dnl We prefer 'install -d', but use 'mkdir -p' if it exists. +dnl If none of these methods works, we give up. +dnl + + +AC_DEFUN(LM_PROG_INSTALL_DIR, +[AC_CACHE_CHECK(how to create a directory including parents, +ac_cv_prog_mkdir_p, +[ +temp_name_base=config.$$ +temp_name=$temp_name_base/x/y/z +$INSTALL -d $temp_name >/dev/null 2>&1 +ac_cv_prog_mkdir_p=none +if test -d $temp_name; then + ac_cv_prog_mkdir_p="$INSTALL -d" +else + mkdir -p $temp_name >/dev/null 2>&1 + if test -d $temp_name; then + ac_cv_prog_mkdir_p="mkdir -p" + fi +fi +rm -fr $temp_name_base +]) + +case "${ac_cv_prog_mkdir_p}" in + none) AC_MSG_ERROR(don't know how create directories with parents) ;; + *) INSTALL_DIR="$ac_cv_prog_mkdir_p" AC_SUBST(INSTALL_DIR) ;; +esac +]) + + +dnl ---------------------------------------------------------------------- +dnl +dnl LM_PROG_PERL5 +dnl +dnl Try to find perl version 5. If found set PERL to the absolute path +dnl of the program, if not found set PERL to false. +dnl +dnl On some systems /usr/bin/perl is perl 4 and e.g. +dnl /usr/local/bin/perl is perl 5. We try to handle this case by +dnl putting a couple of +dnl Tries to handle the case that there are two programs called perl +dnl in the path and one of them is perl 5 and the other isn't. +dnl +AC_DEFUN(LM_PROG_PERL5, +[AC_PATH_PROGS(PERL, perl5 perl, false, + /usr/local/bin:/opt/local/bin:/usr/local/gnu/bin:${PATH}) +changequote(, )dnl +dnl[ That bracket is needed to balance the right bracket below +if test "$PERL" = "false" || $PERL -e 'exit ($] >= 5)'; then +changequote([, ])dnl + ac_cv_path_PERL=false + PERL=false +dnl AC_MSG_WARN(perl version 5 not found) +fi +])dnl + + +dnl ---------------------------------------------------------------------- +dnl +dnl LM_DECL_SO_BSDCOMPAT +dnl +dnl Check if the system has the SO_BSDCOMPAT flag on sockets (linux) +dnl +AC_DEFUN(LM_DECL_SO_BSDCOMPAT, +[AC_CACHE_CHECK([for SO_BSDCOMPAT declaration], ac_cv_decl_so_bsdcompat, +AC_TRY_COMPILE([#include <sys/socket.h>], [int i = SO_BSDCOMPAT;], + ac_cv_decl_so_bsdcompat=yes, + ac_cv_decl_so_bsdcompat=no)) + +case "${ac_cv_decl_so_bsdcompat}" in + "yes" ) AC_DEFINE(HAVE_SO_BSDCOMPAT,[], + [Define if you have SO_BSDCOMPAT flag on sockets]) ;; + * ) ;; +esac +]) + + +dnl ---------------------------------------------------------------------- +dnl +dnl LM_DECL_INADDR_LOOPBACK +dnl +dnl Try to find declaration of INADDR_LOOPBACK, if nowhere provide a default +dnl + +AC_DEFUN(LM_DECL_INADDR_LOOPBACK, +[AC_CACHE_CHECK([for INADDR_LOOPBACK in netinet/in.h], + ac_cv_decl_inaddr_loopback, +[AC_TRY_COMPILE([#include <sys/types.h> +#include <netinet/in.h>], [int i = INADDR_LOOPBACK;], +ac_cv_decl_inaddr_loopback=yes, ac_cv_decl_inaddr_loopback=no) +]) + +if test ${ac_cv_decl_inaddr_loopback} = no; then + AC_CACHE_CHECK([for INADDR_LOOPBACK in rpc/types.h], + ac_cv_decl_inaddr_loopback_rpc, + AC_TRY_COMPILE([#include <rpc/types.h>], + [int i = INADDR_LOOPBACK;], + ac_cv_decl_inaddr_loopback_rpc=yes, + ac_cv_decl_inaddr_loopback_rpc=no)) + + case "${ac_cv_decl_inaddr_loopback_rpc}" in + "yes" ) + AC_DEFINE(DEF_INADDR_LOOPBACK_IN_RPC_TYPES_H,[], + [Define if you need to include rpc/types.h to get INADDR_LOOPBACK defined]) ;; + * ) + AC_CACHE_CHECK([for INADDR_LOOPBACK in winsock2.h], + ac_cv_decl_inaddr_loopback_winsock2, + AC_TRY_COMPILE([#define WIN32_LEAN_AND_MEAN + #include <winsock2.h>], + [int i = INADDR_LOOPBACK;], + ac_cv_decl_inaddr_loopback_winsock2=yes, + ac_cv_decl_inaddr_loopback_winsock2=no)) + case "${ac_cv_decl_inaddr_loopback_winsock2}" in + "yes" ) + AC_DEFINE(DEF_INADDR_LOOPBACK_IN_WINSOCK2_H,[], + [Define if you need to include winsock2.h to get INADDR_LOOPBACK defined]) ;; + * ) + # couldn't find it anywhere + AC_DEFINE(HAVE_NO_INADDR_LOOPBACK,[], + [Define if you don't have a definition of INADDR_LOOPBACK]) ;; + esac;; + esac +fi +]) + + +dnl ---------------------------------------------------------------------- +dnl +dnl LM_STRUCT_SOCKADDR_SA_LEN +dnl +dnl Check if the sockaddr structure has the field sa_len +dnl + +AC_DEFUN(LM_STRUCT_SOCKADDR_SA_LEN, +[AC_CACHE_CHECK([whether struct sockaddr has sa_len field], + ac_cv_struct_sockaddr_sa_len, +AC_TRY_COMPILE([#include <sys/types.h> +#include <sys/socket.h>], [struct sockaddr s; s.sa_len = 10;], + ac_cv_struct_sockaddr_sa_len=yes, ac_cv_struct_sockaddr_sa_len=no)) + +dnl FIXME convbreak +case ${ac_cv_struct_sockaddr_sa_len} in + "no" ) AC_DEFINE(NO_SA_LEN,[1],[Define if you dont have salen]) ;; + *) ;; +esac +]) + +dnl ---------------------------------------------------------------------- +dnl +dnl LM_STRUCT_EXCEPTION +dnl +dnl Check to see whether the system supports the matherr function +dnl and its associated type "struct exception". +dnl + +AC_DEFUN(LM_STRUCT_EXCEPTION, +[AC_CACHE_CHECK([for struct exception (and matherr function)], + ac_cv_struct_exception, +AC_TRY_COMPILE([#include <math.h>], + [struct exception x; x.type = DOMAIN; x.type = SING;], + ac_cv_struct_exception=yes, ac_cv_struct_exception=no)) + +case "${ac_cv_struct_exception}" in + "yes" ) AC_DEFINE(USE_MATHERR,[1],[Define if you have matherr() function and struct exception type]) ;; + * ) ;; +esac +]) + + +dnl ---------------------------------------------------------------------- +dnl +dnl LM_SYS_IPV6 +dnl +dnl Check for ipv6 support and what the in6_addr structure is called. +dnl (early linux used in_addr6 insted of in6_addr) +dnl + +AC_DEFUN(LM_SYS_IPV6, +[AC_MSG_CHECKING(for IP version 6 support) +AC_CACHE_VAL(ac_cv_sys_ipv6_support, +[ok_so_far=yes + AC_TRY_COMPILE([#include <sys/types.h> +#ifdef __WIN32__ +#include <winsock2.h> +#include <ws2tcpip.h> +#else +#include <netinet/in.h> +#endif], + [struct in6_addr a6; struct sockaddr_in6 s6;], ok_so_far=yes, ok_so_far=no) + +if test $ok_so_far = yes; then + ac_cv_sys_ipv6_support=yes +else + AC_TRY_COMPILE([#include <sys/types.h> +#ifdef __WIN32__ +#include <winsock2.h> +#include <ws2tcpip.h> +#else +#include <netinet/in.h> +#endif], + [struct in_addr6 a6; struct sockaddr_in6 s6;], + ac_cv_sys_ipv6_support=in_addr6, ac_cv_sys_ipv6_support=no) +fi +])dnl + +dnl +dnl Have to use old style AC_DEFINE due to BC with old autoconf. +dnl + +case ${ac_cv_sys_ipv6_support} in + yes) + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_IN6,[1],[Define if ipv6 is present]) + ;; + in_addr6) + AC_MSG_RESULT([yes (but I am redefining in_addr6 to in6_addr)]) + AC_DEFINE(HAVE_IN6,[1],[Define if ipv6 is present]) + AC_DEFINE(HAVE_IN_ADDR6_STRUCT,[],[Early linux used in_addr6 instead of in6_addr, define if you have this]) + ;; + *) + AC_MSG_RESULT(no) + ;; +esac +]) + + +dnl ---------------------------------------------------------------------- +dnl +dnl LM_SYS_MULTICAST +dnl +dnl Check for multicast support. Only checks for multicast options in +dnl setsockopt(), no check is performed that multicasting actually works. +dnl If options are found defines HAVE_MULTICAST_SUPPORT +dnl + +AC_DEFUN(LM_SYS_MULTICAST, +[AC_CACHE_CHECK([for multicast support], ac_cv_sys_multicast_support, +[AC_EGREP_CPP(yes, +[#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#if defined(IP_MULTICAST_TTL) && defined(IP_MULTICAST_LOOP) && defined(IP_MULTICAST_IF) && defined(IP_ADD_MEMBERSHIP) && defined(IP_DROP_MEMBERSHIP) +yes +#endif +], ac_cv_sys_multicast_support=yes, ac_cv_sys_multicast_support=no)]) +if test $ac_cv_sys_multicast_support = yes; then + AC_DEFINE(HAVE_MULTICAST_SUPPORT,[1], + [Define if setsockopt() accepts multicast options]) +fi +])dnl + + +dnl ---------------------------------------------------------------------- +dnl +dnl LM_DECL_SYS_ERRLIST +dnl +dnl Define SYS_ERRLIST_DECLARED if the variable sys_errlist is declared +dnl in a system header file, stdio.h or errno.h. +dnl + +AC_DEFUN(LM_DECL_SYS_ERRLIST, +[AC_CACHE_CHECK([for sys_errlist declaration in stdio.h or errno.h], + ac_cv_decl_sys_errlist, +[AC_TRY_COMPILE([#include <stdio.h> +#include <errno.h>], [char *msg = *(sys_errlist + 1);], + ac_cv_decl_sys_errlist=yes, ac_cv_decl_sys_errlist=no)]) +if test $ac_cv_decl_sys_errlist = yes; then + AC_DEFINE(SYS_ERRLIST_DECLARED,[], + [define if the variable sys_errlist is declared in a system header file]) +fi +]) + + +dnl ---------------------------------------------------------------------- +dnl +dnl LM_CHECK_FUNC_DECL( funname, declaration [, extra includes +dnl [, action-if-found [, action-if-not-found]]] ) +dnl +dnl Checks if the declaration "declaration" of "funname" conflicts +dnl with the header files idea of how the function should be +dnl declared. It is useful on systems which lack prototypes and you +dnl need to provide your own (e.g. when you want to take the address +dnl of a function). The 4'th argument is expanded if conflicting, +dnl the 5'th argument otherwise +dnl +dnl + +AC_DEFUN(LM_CHECK_FUNC_DECL, +[AC_MSG_CHECKING([for conflicting declaration of $1]) +AC_CACHE_VAL(ac_cv_func_decl_$1, +[AC_TRY_COMPILE([#include <stdio.h> +$3],[$2 +char *c = (char *)$1; +], eval "ac_cv_func_decl_$1=no", eval "ac_cv_func_decl_$1=yes")]) +if eval "test \"`echo '$ac_cv_func_decl_'$1`\" = yes"; then + AC_MSG_RESULT(yes) + ifelse([$4], , :, [$4]) +else + AC_MSG_RESULT(no) +ifelse([$5], , , [$5 +])dnl +fi +]) + +dnl ---------------------------------------------------------------------- +dnl +dnl AC_DOUBLE_MIDDLE_ENDIAN +dnl +dnl Checks whether doubles are represented in "middle-endian" format. +dnl Sets ac_cv_double_middle_endian={no,yes,unknown} accordingly, +dnl as well as DOUBLE_MIDDLE_ENDIAN. +dnl +dnl + +AC_DEFUN([AC_C_DOUBLE_MIDDLE_ENDIAN], +[AC_CACHE_CHECK(whether double word ordering is middle-endian, ac_cv_c_double_middle_endian, +[# It does not; compile a test program. +AC_RUN_IFELSE( +[AC_LANG_SOURCE([[#include <stdlib.h> + +int +main(void) +{ + int i = 0; + int zero = 0; + int bigendian; + int zero_index = 0; + + union + { + long int l; + char c[sizeof (long int)]; + } u; + + /* we'll use the one with 32-bit words */ + union + { + double d; + unsigned int c[2]; + } vint; + + union + { + double d; + unsigned long c[2]; + } vlong; + + union + { + double d; + unsigned short c[2]; + } vshort; + + + /* Are we little or big endian? From Harbison&Steele. */ + u.l = 1; + bigendian = (u.c[sizeof (long int) - 1] == 1); + + zero_index = bigendian ? 1 : 0; + + vint.d = 1.0; + vlong.d = 1.0; + vshort.d = 1.0; + + if (sizeof(unsigned int) == 4) + { + if (vint.c[zero_index] != 0) + zero = 1; + } + else if (sizeof(unsigned long) == 4) + { + if (vlong.c[zero_index] != 0) + zero = 1; + } + else if (sizeof(unsigned short) == 4) + { + if (vshort.c[zero_index] != 0) + zero = 1; + } + + exit (zero); +} +]])], + [ac_cv_c_double_middle_endian=no], + [ac_cv_c_double_middle_endian=yes], + [ac_cv_c_double_middle=unknown])]) +case $ac_cv_c_double_middle_endian in + yes) + m4_default([$1], + [AC_DEFINE([DOUBLE_MIDDLE_ENDIAN], 1, + [Define to 1 if your processor stores the words in a double in + middle-endian format (like some ARMs).])]) ;; + no) + $2 ;; + *) + m4_default([$3], + [AC_MSG_WARN([unknown double endianness +presetting ac_cv_c_double_middle_endian=no (or yes) will help])]) ;; +esac +])# AC_C_DOUBLE_MIDDLE_ENDIAN + + +dnl ---------------------------------------------------------------------- +dnl +dnl LM_CHECK_THR_LIB +dnl +dnl This macro may be used by any OTP application. +dnl +dnl LM_CHECK_THR_LIB sets THR_LIBS, THR_DEFS, and THR_LIB_NAME. It also +dnl checks for some pthread headers which will appear in DEFS or config.h. +dnl + +AC_DEFUN(LM_CHECK_THR_LIB, +[ + +NEED_NPTL_PTHREAD_H=no + +dnl win32? +AC_MSG_CHECKING([for native win32 threads]) +if test "X$host_os" = "Xwin32"; then + AC_MSG_RESULT(yes) + THR_DEFS="-DWIN32_THREADS" + THR_LIBS= + THR_LIB_NAME=win32_threads + THR_LIB_TYPE=win32_threads +else + AC_MSG_RESULT(no) + THR_DEFS= + THR_LIBS= + THR_LIB_NAME= + THR_LIB_TYPE=posix_unknown + +dnl Try to find POSIX threads + +dnl The usual pthread lib... + AC_CHECK_LIB(pthread, pthread_create, THR_LIBS="-lpthread") + +dnl Very old versions of FreeBSD have pthreads in special c library, c_r... + if test "x$THR_LIBS" = "x"; then + AC_CHECK_LIB(c_r, pthread_create, THR_LIBS="-lc_r") + fi + +dnl QNX has pthreads in standard C library + if test "x$THR_LIBS" = "x"; then + AC_CHECK_FUNC(pthread_create, THR_LIBS="none_needed") + fi + +dnl On ofs1 the '-pthread' switch should be used + if test "x$THR_LIBS" = "x"; then + AC_MSG_CHECKING([if the '-pthread' switch can be used]) + saved_cflags=$CFLAGS + CFLAGS="$CFLAGS -pthread" + AC_TRY_LINK([#include <pthread.h>], + pthread_create((void*)0,(void*)0,(void*)0,(void*)0);, + [THR_DEFS="-pthread" + THR_LIBS="-pthread"]) + CFLAGS=$saved_cflags + if test "x$THR_LIBS" != "x"; then + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + fi + fi + + if test "x$THR_LIBS" != "x"; then + THR_DEFS="$THR_DEFS -D_THREAD_SAFE -D_REENTRANT -DPOSIX_THREADS" + THR_LIB_NAME=pthread + if test "x$THR_LIBS" = "xnone_needed"; then + THR_LIBS= + fi + case $host_os in + solaris*) + THR_DEFS="$THR_DEFS -D_POSIX_PTHREAD_SEMANTICS" ;; + linux*) + THR_DEFS="$THR_DEFS -D_POSIX_THREAD_SAFE_FUNCTIONS" + + LM_CHECK_GETCONF + AC_MSG_CHECKING(for Native POSIX Thread Library) + libpthr_vsn=`$GETCONF GNU_LIBPTHREAD_VERSION 2>/dev/null` + if test $? -eq 0; then + case "$libpthr_vsn" in + *nptl*|*NPTL*) nptl=yes;; + *) nptl=no;; + esac + elif test "$cross_compiling" = "yes"; then + case "$erl_xcomp_linux_nptl" in + "") nptl=cross;; + yes|no) nptl=$erl_xcomp_linux_nptl;; + *) AC_MSG_ERROR([Bad erl_xcomp_linux_nptl value: $erl_xcomp_linux_nptl]);; + esac + else + nptl=no + fi + AC_MSG_RESULT($nptl) + if test $nptl = cross; then + nptl=yes + AC_MSG_WARN([result yes guessed because of cross compilation]) + fi + if test $nptl = yes; then + THR_LIB_TYPE=posix_nptl + need_nptl_incldir=no + AC_CHECK_HEADER(nptl/pthread.h, + [need_nptl_incldir=yes + NEED_NPTL_PTHREAD_H=yes]) + if test $need_nptl_incldir = yes; then + # Ahh... + nptl_path="$C_INCLUDE_PATH:$CPATH" + if test X$cross_compiling != Xyes; then + nptl_path="$nptl_path:/usr/local/include:/usr/include" + else + IROOT="$erl_xcomp_isysroot" + test "$IROOT" != "" || IROOT="$erl_xcomp_sysroot" + test "$IROOT" != "" || AC_MSG_ERROR([Don't know where to search for includes! Please set erl_xcomp_isysroot]) + nptl_path="$nptl_path:$IROOT/usr/local/include:$IROOT/usr/include" + fi + nptl_ws_path= + save_ifs="$IFS"; IFS=":" + for dir in $nptl_path; do + if test "x$dir" != "x"; then + nptl_ws_path="$nptl_ws_path $dir" + fi + done + IFS=$save_ifs + nptl_incldir= + for dir in $nptl_ws_path; do + AC_CHECK_HEADER($dir/nptl/pthread.h, + nptl_incldir=$dir/nptl) + if test "x$nptl_incldir" != "x"; then + THR_DEFS="$THR_DEFS -isystem $nptl_incldir" + break + fi + done + if test "x$nptl_incldir" = "x"; then + AC_MSG_ERROR(Failed to locate nptl system include directory) + fi + fi + fi + ;; + *) ;; + esac + + dnl We sometimes need THR_DEFS in order to find certain headers + dnl (at least for pthread.h on osf1). + saved_cppflags=$CPPFLAGS + CPPFLAGS="$CPPFLAGS $THR_DEFS" + + dnl + dnl Check for headers + dnl + + AC_CHECK_HEADER(pthread.h, + AC_DEFINE(HAVE_PTHREAD_H, 1, \ +[Define if you have the <pthread.h> header file.])) + + dnl Some Linuxes have <pthread/mit/pthread.h> instead of <pthread.h> + AC_CHECK_HEADER(pthread/mit/pthread.h, \ + AC_DEFINE(HAVE_MIT_PTHREAD_H, 1, \ +[Define if the pthread.h header file is in pthread/mit directory.])) + + dnl restore CPPFLAGS + CPPFLAGS=$saved_cppflags + + fi +fi + +]) + +AC_DEFUN(ERL_INTERNAL_LIBS, +[ + +ERTS_INTERNAL_X_LIBS= + +AC_CHECK_LIB(kstat, kstat_open, +[AC_DEFINE(HAVE_KSTAT, 1, [Define if you have kstat]) +ERTS_INTERNAL_X_LIBS="$ERTS_INTERNAL_X_LIBS -lkstat"]) + +AC_SUBST(ERTS_INTERNAL_X_LIBS) + +]) + +AC_DEFUN(ETHR_CHK_SYNC_OP, +[ + AC_MSG_CHECKING([for $3-bit $1()]) + case "$2" in + "1") sync_call="$1(&var);";; + "2") sync_call="$1(&var, ($4) 0);";; + "3") sync_call="$1(&var, ($4) 0, ($4) 0);";; + esac + have_sync_op=no + AC_TRY_LINK([], + [ + $4 res; + volatile $4 var; + res = $sync_call + ], + [have_sync_op=yes]) + test $have_sync_op = yes && $5 + AC_MSG_RESULT([$have_sync_op]) +]) + +AC_DEFUN(ETHR_CHK_INTERLOCKED, +[ + ilckd="$1" + AC_MSG_CHECKING([for ${ilckd}()]) + case "$2" in + "1") ilckd_call="${ilckd}(var);";; + "2") ilckd_call="${ilckd}(var, ($3) 0);";; + "3") ilckd_call="${ilckd}(var, ($3) 0, ($3) 0);";; + "4") ilckd_call="${ilckd}(var, ($3) 0, ($3) 0, arr);";; + esac + have_interlocked_op=no + AC_TRY_LINK( + [ + #define WIN32_LEAN_AND_MEAN + #include <windows.h> + #include <intrin.h> + ], + [ + volatile $3 *var; + volatile $3 arr[2]; + + $ilckd_call + return 0; + ], + [have_interlocked_op=yes]) + test $have_interlocked_op = yes && $4 + AC_MSG_RESULT([$have_interlocked_op]) +]) + +dnl ---------------------------------------------------------------------- +dnl +dnl ERL_FIND_ETHR_LIB +dnl +dnl NOTE! This macro may be changed at any time! Should *only* be used by +dnl ERTS! +dnl +dnl Find a thread library to use. Sets ETHR_LIBS to libraries to link +dnl with, ETHR_X_LIBS to extra libraries to link with (same as ETHR_LIBS +dnl except that the ethread lib itself is not included), ETHR_DEFS to +dnl defines to compile with, ETHR_THR_LIB_BASE to the name of the +dnl thread library which the ethread library is based on, and ETHR_LIB_NAME +dnl to the name of the library where the ethread implementation is located. +dnl ERL_FIND_ETHR_LIB currently searches for 'pthreads', and +dnl 'win32_threads'. If no thread library was found ETHR_LIBS, ETHR_X_LIBS, +dnl ETHR_DEFS, ETHR_THR_LIB_BASE, and ETHR_LIB_NAME are all set to the +dnl empty string. +dnl + +AC_DEFUN(ERL_FIND_ETHR_LIB, +[ + +LM_CHECK_THR_LIB +ERL_INTERNAL_LIBS + +ethr_have_native_atomics=no +ethr_have_native_spinlock=no +ETHR_THR_LIB_BASE="$THR_LIB_NAME" +ETHR_THR_LIB_BASE_TYPE="$THR_LIB_TYPE" +ETHR_DEFS="$THR_DEFS" +ETHR_X_LIBS="$THR_LIBS $ERTS_INTERNAL_X_LIBS" +ETHR_LIBS= +ETHR_LIB_NAME= + +ethr_modified_default_stack_size= + +dnl Name of lib where ethread implementation is located +ethr_lib_name=ethread + +case "$THR_LIB_NAME" in + + win32_threads) + ETHR_THR_LIB_BASE_DIR=win + # * _WIN32_WINNT >= 0x0400 is needed for + # TryEnterCriticalSection + # * _WIN32_WINNT >= 0x0403 is needed for + # InitializeCriticalSectionAndSpinCount + # The ethread lib will refuse to build if _WIN32_WINNT < 0x0403. + # + # -D_WIN32_WINNT should have been defined in $CPPFLAGS; fetch it + # and save it in ETHR_DEFS. + found_win32_winnt=no + for cppflag in $CPPFLAGS; do + case $cppflag in + -DWINVER*) + ETHR_DEFS="$ETHR_DEFS $cppflag" + ;; + -D_WIN32_WINNT*) + ETHR_DEFS="$ETHR_DEFS $cppflag" + found_win32_winnt=yes + ;; + *) + ;; + esac + done + if test $found_win32_winnt = no; then + AC_MSG_ERROR([-D_WIN32_WINNT missing in CPPFLAGS]) + fi + + AC_DEFINE(ETHR_WIN32_THREADS, 1, [Define if you have win32 threads]) + + ETHR_CHK_INTERLOCKED([_InterlockedDecrement], [1], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDDECREMENT, 1, [Define if you have _InterlockedDecrement()])) + ETHR_CHK_INTERLOCKED([_InterlockedDecrement_rel], [1], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDDECREMENT_REL, 1, [Define if you have _InterlockedDecrement_rel()])) + ETHR_CHK_INTERLOCKED([_InterlockedIncrement], [1], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDINCREMENT, 1, [Define if you have _InterlockedIncrement()])) + ETHR_CHK_INTERLOCKED([_InterlockedIncrement_acq], [1], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDINCREMENT_ACQ, 1, [Define if you have _InterlockedIncrement_acq()])) + ETHR_CHK_INTERLOCKED([_InterlockedExchangeAdd], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGEADD, 1, [Define if you have _InterlockedExchangeAdd()])) + ETHR_CHK_INTERLOCKED([_InterlockedExchangeAdd_acq], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGEADD_ACQ, 1, [Define if you have _InterlockedExchangeAdd_acq()])) + ETHR_CHK_INTERLOCKED([_InterlockedAnd], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDAND, 1, [Define if you have _InterlockedAnd()])) + ETHR_CHK_INTERLOCKED([_InterlockedOr], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDOR, 1, [Define if you have _InterlockedOr()])) + ETHR_CHK_INTERLOCKED([_InterlockedExchange], [2], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGE, 1, [Define if you have _InterlockedExchange()])) + ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange], [3], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE, 1, [Define if you have _InterlockedCompareExchange()])) + test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes + ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange_acq], [3], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE_ACQ, 1, [Define if you have _InterlockedCompareExchange_acq()])) + test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes + ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange_rel], [3], [long], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE_REL, 1, [Define if you have _InterlockedCompareExchange_rel()])) + test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes + + ETHR_CHK_INTERLOCKED([_InterlockedDecrement64], [1], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDDECREMENT64, 1, [Define if you have _InterlockedDecrement64()])) + ETHR_CHK_INTERLOCKED([_InterlockedDecrement64_rel], [1], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDDECREMENT64_REL, 1, [Define if you have _InterlockedDecrement64_rel()])) + ETHR_CHK_INTERLOCKED([_InterlockedIncrement64], [1], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDINCREMENT64, 1, [Define if you have _InterlockedIncrement64()])) + ETHR_CHK_INTERLOCKED([_InterlockedIncrement64_acq], [1], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDINCREMENT64_ACQ, 1, [Define if you have _InterlockedIncrement64_acq()])) + ETHR_CHK_INTERLOCKED([_InterlockedExchangeAdd64], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGEADD64, 1, [Define if you have _InterlockedExchangeAdd64()])) + ETHR_CHK_INTERLOCKED([_InterlockedExchangeAdd64_acq], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGEADD64_ACQ, 1, [Define if you have _InterlockedExchangeAdd64_acq()])) + ETHR_CHK_INTERLOCKED([_InterlockedAnd64], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDAND64, 1, [Define if you have _InterlockedAnd64()])) + ETHR_CHK_INTERLOCKED([_InterlockedOr64], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDOR64, 1, [Define if you have _InterlockedOr64()])) + ETHR_CHK_INTERLOCKED([_InterlockedExchange64], [2], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDEXCHANGE64, 1, [Define if you have _InterlockedExchange64()])) + ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange64], [3], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64, 1, [Define if you have _InterlockedCompareExchange64()])) + test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes + ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange64_acq], [3], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64_ACQ, 1, [Define if you have _InterlockedCompareExchange64_acq()])) + test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes + ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange64_rel], [3], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE64_REL, 1, [Define if you have _InterlockedCompareExchange64_rel()])) + test "$have_interlocked_op" = "yes" && ethr_have_native_atomics=yes + + ETHR_CHK_INTERLOCKED([_InterlockedCompareExchange128], [4], [__int64], AC_DEFINE_UNQUOTED(ETHR_HAVE__INTERLOCKEDCOMPAREEXCHANGE128, 1, [Define if you have _InterlockedCompareExchange128()])) + + test "$ethr_have_native_atomics" = "yes" && ethr_have_native_spinlock=yes + ;; + + pthread) + ETHR_THR_LIB_BASE_DIR=pthread + AC_DEFINE(ETHR_PTHREADS, 1, [Define if you have pthreads]) + case $host_os in + openbsd*) + # The default stack size is insufficient for our needs + # on OpenBSD. We increase it to 256 kilo words. + ethr_modified_default_stack_size=256;; + linux*) + ETHR_DEFS="$ETHR_DEFS -D_GNU_SOURCE" + + if test X$cross_compiling = Xyes; then + case X$erl_xcomp_linux_usable_sigusrx in + X) usable_sigusrx=cross;; + Xyes|Xno) usable_sigusrx=$erl_xcomp_linux_usable_sigusrx;; + *) AC_MSG_ERROR([Bad erl_xcomp_linux_usable_sigusrx value: $erl_xcomp_linux_usable_sigusrx]);; + esac + case X$erl_xcomp_linux_usable_sigaltstack in + X) usable_sigaltstack=cross;; + Xyes|Xno) usable_sigaltstack=$erl_xcomp_linux_usable_sigaltstack;; + *) AC_MSG_ERROR([Bad erl_xcomp_linux_usable_sigaltstack value: $erl_xcomp_linux_usable_sigaltstack]);; + esac + else + # FIXME: Test for actual problems instead of kernel versions + linux_kernel_vsn_=`uname -r` + case $linux_kernel_vsn_ in + [[0-1]].*|2.[[0-1]]|2.[[0-1]].*) + usable_sigusrx=no + usable_sigaltstack=no;; + 2.[[2-3]]|2.[[2-3]].*) + usable_sigusrx=yes + usable_sigaltstack=no;; + *) + usable_sigusrx=yes + usable_sigaltstack=yes;; + esac + fi + + AC_MSG_CHECKING(if SIGUSR1 and SIGUSR2 can be used) + AC_MSG_RESULT($usable_sigusrx) + if test $usable_sigusrx = cross; then + usable_sigusrx=yes + AC_MSG_WARN([result yes guessed because of cross compilation]) + fi + if test $usable_sigusrx = no; then + ETHR_DEFS="$ETHR_DEFS -DETHR_UNUSABLE_SIGUSRX" + fi + + AC_MSG_CHECKING(if sigaltstack can be used) + AC_MSG_RESULT($usable_sigaltstack) + if test $usable_sigaltstack = cross; then + usable_sigaltstack=yes + AC_MSG_WARN([result yes guessed because of cross compilation]) + fi + if test $usable_sigaltstack = no; then + ETHR_DEFS="$ETHR_DEFS -DETHR_UNUSABLE_SIGALTSTACK" + fi + ;; + *) ;; + esac + + dnl We sometimes need ETHR_DEFS in order to find certain headers + dnl (at least for pthread.h on osf1). + saved_cppflags="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $ETHR_DEFS" + + dnl We need the thread library in order to find some functions + saved_libs="$LIBS" + LIBS="$LIBS $ETHR_X_LIBS" + + dnl + dnl Check for headers + dnl + + AC_CHECK_HEADER(pthread.h, \ + AC_DEFINE(ETHR_HAVE_PTHREAD_H, 1, \ +[Define if you have the <pthread.h> header file.])) + + dnl Some Linuxes have <pthread/mit/pthread.h> instead of <pthread.h> + AC_CHECK_HEADER(pthread/mit/pthread.h, \ + AC_DEFINE(ETHR_HAVE_MIT_PTHREAD_H, 1, \ +[Define if the pthread.h header file is in pthread/mit directory.])) + + if test $NEED_NPTL_PTHREAD_H = yes; then + AC_DEFINE(ETHR_NEED_NPTL_PTHREAD_H, 1, \ +[Define if you need the <nptl/pthread.h> header file.]) + fi + + AC_CHECK_HEADER(sched.h, \ + AC_DEFINE(ETHR_HAVE_SCHED_H, 1, \ +[Define if you have the <sched.h> header file.])) + + AC_CHECK_HEADER(sys/time.h, \ + AC_DEFINE(ETHR_HAVE_SYS_TIME_H, 1, \ +[Define if you have the <sys/time.h> header file.])) + + AC_TRY_COMPILE([#include <time.h> + #include <sys/time.h>], + [struct timeval *tv; return 0;], + AC_DEFINE(ETHR_TIME_WITH_SYS_TIME, 1, \ +[Define if you can safely include both <sys/time.h> and <time.h>.])) + + + dnl + dnl Check for functions + dnl + + AC_CHECK_FUNC(pthread_spin_lock, \ + [ethr_have_native_spinlock=yes \ + AC_DEFINE(ETHR_HAVE_PTHREAD_SPIN_LOCK, 1, \ +[Define if you have the pthread_spin_lock function.])]) + + have_sched_yield=no + have_librt_sched_yield=no + AC_CHECK_FUNC(sched_yield, [have_sched_yield=yes]) + if test $have_sched_yield = no; then + AC_CHECK_LIB(rt, sched_yield, + [have_librt_sched_yield=yes + ETHR_X_LIBS="$ETHR_X_LIBS -lrt"]) + fi + if test $have_sched_yield = yes || test $have_librt_sched_yield = yes; then + AC_DEFINE(ETHR_HAVE_SCHED_YIELD, 1, [Define if you have the sched_yield() function.]) + AC_MSG_CHECKING([whether sched_yield() returns an int]) + sched_yield_ret_int=no + AC_TRY_COMPILE([ + #ifdef ETHR_HAVE_SCHED_H + #include <sched.h> + #endif + ], + [int sched_yield();], + [sched_yield_ret_int=yes]) + AC_MSG_RESULT([$sched_yield_ret_int]) + if test $sched_yield_ret_int = yes; then + AC_DEFINE(ETHR_SCHED_YIELD_RET_INT, 1, [Define if sched_yield() returns an int.]) + fi + fi + + have_pthread_yield=no + AC_CHECK_FUNC(pthread_yield, [have_pthread_yield=yes]) + if test $have_pthread_yield = yes; then + AC_DEFINE(ETHR_HAVE_PTHREAD_YIELD, 1, [Define if you have the pthread_yield() function.]) + AC_MSG_CHECKING([whether pthread_yield() returns an int]) + pthread_yield_ret_int=no + AC_TRY_COMPILE([ + #if defined(ETHR_NEED_NPTL_PTHREAD_H) + #include <nptl/pthread.h> + #elif defined(ETHR_HAVE_MIT_PTHREAD_H) + #include <pthread/mit/pthread.h> + #elif defined(ETHR_HAVE_PTHREAD_H) + #include <pthread.h> + #endif + ], + [int pthread_yield();], + [pthread_yield_ret_int=yes]) + AC_MSG_RESULT([$pthread_yield_ret_int]) + if test $pthread_yield_ret_int = yes; then + AC_DEFINE(ETHR_PTHREAD_YIELD_RET_INT, 1, [Define if pthread_yield() returns an int.]) + fi + fi + + have_pthread_rwlock_init=no + AC_CHECK_FUNC(pthread_rwlock_init, [have_pthread_rwlock_init=yes]) + if test $have_pthread_rwlock_init = yes; then + + ethr_have_pthread_rwlockattr_setkind_np=no + AC_CHECK_FUNC(pthread_rwlockattr_setkind_np, + [ethr_have_pthread_rwlockattr_setkind_np=yes]) + + if test $ethr_have_pthread_rwlockattr_setkind_np = yes; then + AC_DEFINE(ETHR_HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP, 1, \ +[Define if you have the pthread_rwlockattr_setkind_np() function.]) + + AC_MSG_CHECKING([for PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP]) + ethr_pthread_rwlock_writer_nonrecursive_initializer_np=no + AC_TRY_LINK([ + #if defined(ETHR_NEED_NPTL_PTHREAD_H) + #include <nptl/pthread.h> + #elif defined(ETHR_HAVE_MIT_PTHREAD_H) + #include <pthread/mit/pthread.h> + #elif defined(ETHR_HAVE_PTHREAD_H) + #include <pthread.h> + #endif + ], + [ + pthread_rwlockattr_t *attr; + return pthread_rwlockattr_setkind_np(attr, + PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP); + ], + [ethr_pthread_rwlock_writer_nonrecursive_initializer_np=yes]) + AC_MSG_RESULT([$ethr_pthread_rwlock_writer_nonrecursive_initializer_np]) + if test $ethr_pthread_rwlock_writer_nonrecursive_initializer_np = yes; then + AC_DEFINE(ETHR_HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, 1, \ +[Define if you have the PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP rwlock attribute.]) + fi + fi + fi + + if test "$force_pthread_rwlocks" = "yes"; then + + AC_DEFINE(ETHR_FORCE_PTHREAD_RWLOCK, 1, \ +[Define if you want to force usage of pthread rwlocks]) + + if test $have_pthread_rwlock_init = yes; then + AC_MSG_WARN([Forced usage of pthread rwlocks. Note that this implementation may suffer from starvation issues.]) + else + AC_MSG_ERROR([User forced usage of pthread rwlock, but no such implementation was found]) + fi + fi + + AC_CHECK_FUNC(pthread_attr_setguardsize, \ + AC_DEFINE(ETHR_HAVE_PTHREAD_ATTR_SETGUARDSIZE, 1, \ +[Define if you have the pthread_attr_setguardsize function.])) + + linux_futex=no + AC_MSG_CHECKING([for Linux futexes]) + AC_TRY_LINK([ + #include <sys/syscall.h> + #include <unistd.h> + #include <linux/futex.h> + #include <sys/time.h> + ], + [ + int i = 1; + syscall(__NR_futex, (void *) &i, FUTEX_WAKE, 1, + (void*)0,(void*)0, 0); + syscall(__NR_futex, (void *) &i, FUTEX_WAIT, 0, + (void*)0,(void*)0, 0); + return 0; + ], + linux_futex=yes) + AC_MSG_RESULT([$linux_futex]) + test $linux_futex = yes && AC_DEFINE(ETHR_HAVE_LINUX_FUTEX, 1, [Define if you have a linux futex implementation.]) + + AC_CHECK_SIZEOF(int) + AC_CHECK_SIZEOF(long) + AC_CHECK_SIZEOF(long long) + AC_CHECK_SIZEOF(__int128_t) + + if test "$ac_cv_sizeof_int" = "4"; then + int32="int" + elif test "$ac_cv_sizeof_long" = "4"; then + int32="long" + elif test "$ac_cv_sizeof_long_long" = "4"; then + int32="long long" + else + AC_MSG_ERROR([No 32-bit type found]) + fi + + if test "$ac_cv_sizeof_int" = "8"; then + int64="int" + elif test "$ac_cv_sizeof_long" = "8"; then + int64="long" + elif test "$ac_cv_sizeof_long_long" = "8"; then + int64="long long" + else + AC_MSG_ERROR([No 64-bit type found]) + fi + + int128=no + if test "$ac_cv_sizeof___int128_t" = "16"; then + int128="__int128_t" + fi + + ETHR_CHK_SYNC_OP([__sync_val_compare_and_swap], [3], [32], [$int32], AC_DEFINE(ETHR_HAVE___SYNC_VAL_COMPARE_AND_SWAP32, 1, [Define if you have __sync_val_compare_and_swap() for 32-bit integers])) + test "$have_sync_op" = "yes" && ethr_have_native_atomics=yes + ETHR_CHK_SYNC_OP([__sync_add_and_fetch], [2], [32], [$int32], AC_DEFINE(ETHR_HAVE___SYNC_ADD_AND_FETCH32, 1, [Define if you have __sync_add_and_fetch() for 32-bit integers])) + ETHR_CHK_SYNC_OP([__sync_fetch_and_and], [2], [32], [$int32], AC_DEFINE(ETHR_HAVE___SYNC_FETCH_AND_AND32, 1, [Define if you have __sync_fetch_and_and() for 32-bit integers])) + ETHR_CHK_SYNC_OP([__sync_fetch_and_or], [2], [32], [$int32], AC_DEFINE(ETHR_HAVE___SYNC_FETCH_AND_OR32, 1, [Define if you have __sync_fetch_and_or() for 32-bit integers])) + + ETHR_CHK_SYNC_OP([__sync_val_compare_and_swap], [3], [64], [$int64], AC_DEFINE(ETHR_HAVE___SYNC_VAL_COMPARE_AND_SWAP64, 1, [Define if you have __sync_val_compare_and_swap() for 64-bit integers])) + test "$have_sync_op" = "yes" && ethr_have_native_atomics=yes + ETHR_CHK_SYNC_OP([__sync_add_and_fetch], [2], [64], [$int64], AC_DEFINE(ETHR_HAVE___SYNC_ADD_AND_FETCH64, 1, [Define if you have __sync_add_and_fetch() for 64-bit integers])) + ETHR_CHK_SYNC_OP([__sync_fetch_and_and], [2], [64], [$int64], AC_DEFINE(ETHR_HAVE___SYNC_FETCH_AND_AND64, 1, [Define if you have __sync_fetch_and_and() for 64-bit integers])) + ETHR_CHK_SYNC_OP([__sync_fetch_and_or], [2], [64], [$int64], AC_DEFINE(ETHR_HAVE___SYNC_FETCH_AND_OR64, 1, [Define if you have __sync_fetch_and_or() for 64-bit integers])) + + if test $int128 != no; then + ETHR_CHK_SYNC_OP([__sync_val_compare_and_swap], [3], [128], [$int128], AC_DEFINE(ETHR_HAVE___SYNC_VAL_COMPARE_AND_SWAP128, 1, [Define if you have __sync_val_compare_and_swap() for 128-bit integers])) + fi + + AC_MSG_CHECKING([for a usable libatomic_ops implementation]) + case "x$with_libatomic_ops" in + xno | xyes | x) + libatomic_ops_include= + ;; + *) + if test -d "${with_libatomic_ops}/include"; then + libatomic_ops_include="-I$with_libatomic_ops/include" + CPPFLAGS="$CPPFLAGS $libatomic_ops_include" + else + AC_MSG_ERROR([libatomic_ops include directory $with_libatomic_ops/include not found]) + fi;; + esac + ethr_have_libatomic_ops=no + AC_TRY_LINK([#include "atomic_ops.h"], + [ + volatile AO_t x; + AO_t y; + int z; + + AO_nop_full(); + AO_store(&x, (AO_t) 0); + z = AO_load(&x); + z = AO_compare_and_swap_full(&x, (AO_t) 0, (AO_t) 1); + ], + [ethr_have_native_atomics=yes + ethr_have_libatomic_ops=yes]) + AC_MSG_RESULT([$ethr_have_libatomic_ops]) + if test $ethr_have_libatomic_ops = yes; then + AC_CHECK_SIZEOF(AO_t, , + [ + #include <stdio.h> + #include "atomic_ops.h" + ]) + AC_DEFINE_UNQUOTED(ETHR_SIZEOF_AO_T, $ac_cv_sizeof_AO_t, [Define to the size of AO_t if libatomic_ops is used]) + + AC_DEFINE(ETHR_HAVE_LIBATOMIC_OPS, 1, [Define if you have libatomic_ops atomic operations]) + if test "x$with_libatomic_ops" != "xno" && test "x$with_libatomic_ops" != "x"; then + AC_DEFINE(ETHR_PREFER_LIBATOMIC_OPS_NATIVE_IMPLS, 1, [Define if you prefer libatomic_ops native ethread implementations]) + fi + ETHR_DEFS="$ETHR_DEFS $libatomic_ops_include" + elif test "x$with_libatomic_ops" != "xno" && test "x$with_libatomic_ops" != "x"; then + AC_MSG_ERROR([No usable libatomic_ops implementation found]) + fi + + case "$host_cpu" in + sparc | sun4u | sparc64 | sun4v) + case "$with_sparc_memory_order" in + "TSO") + AC_DEFINE(ETHR_SPARC_TSO, 1, [Define if only run in Sparc TSO mode]);; + "PSO") + AC_DEFINE(ETHR_SPARC_PSO, 1, [Define if only run in Sparc PSO, or TSO mode]);; + "RMO"|"") + AC_DEFINE(ETHR_SPARC_RMO, 1, [Define if run in Sparc RMO, PSO, or TSO mode]);; + *) + AC_MSG_ERROR([Unsupported Sparc memory order: $with_sparc_memory_order]);; + esac + ethr_have_native_atomics=yes;; + i86pc | i*86 | x86_64 | amd64) + if test "$enable_x86_out_of_order" = "yes"; then + AC_DEFINE(ETHR_X86_OUT_OF_ORDER, 1, [Define if x86/x86_64 out of order instructions should be synchronized]) + fi + ethr_have_native_atomics=yes;; + macppc | ppc | "Power Macintosh") + ethr_have_native_atomics=yes;; + tile) + ethr_have_native_atomics=yes;; + *) + ;; + esac + + test ethr_have_native_atomics = "yes" && ethr_have_native_spinlock=yes + + dnl Restore LIBS + LIBS=$saved_libs + dnl restore CPPFLAGS + CPPFLAGS=$saved_cppflags + + ;; + *) + ;; +esac + +AC_MSG_CHECKING([whether default stack size should be modified]) +if test "x$ethr_modified_default_stack_size" != "x"; then + AC_DEFINE_UNQUOTED(ETHR_MODIFIED_DEFAULT_STACK_SIZE, $ethr_modified_default_stack_size, [Define if you want to modify the default stack size]) + AC_MSG_RESULT([yes; to $ethr_modified_default_stack_size kilo words]) +else + AC_MSG_RESULT([no]) +fi + +if test "x$ETHR_THR_LIB_BASE" != "x"; then + ETHR_DEFS="-DUSE_THREADS $ETHR_DEFS" + ETHR_LIBS="-l$ethr_lib_name -lerts_internal_r $ETHR_X_LIBS" + ETHR_LIB_NAME=$ethr_lib_name +fi + +AC_CHECK_SIZEOF(void *) +AC_DEFINE_UNQUOTED(ETHR_SIZEOF_PTR, $ac_cv_sizeof_void_p, [Define to the size of pointers]) + +AC_CHECK_SIZEOF(int) +AC_DEFINE_UNQUOTED(ETHR_SIZEOF_INT, $ac_cv_sizeof_int, [Define to the size of int]) +AC_CHECK_SIZEOF(long) +AC_DEFINE_UNQUOTED(ETHR_SIZEOF_LONG, $ac_cv_sizeof_long, [Define to the size of long]) +AC_CHECK_SIZEOF(long long) +AC_DEFINE_UNQUOTED(ETHR_SIZEOF_LONG_LONG, $ac_cv_sizeof_long_long, [Define to the size of long long]) +AC_CHECK_SIZEOF(__int64) +AC_DEFINE_UNQUOTED(ETHR_SIZEOF___INT64, $ac_cv_sizeof___int64, [Define to the size of __int64]) +AC_CHECK_SIZEOF(__int128_t) +AC_DEFINE_UNQUOTED(ETHR_SIZEOF___INT128_T, $ac_cv_sizeof___int128_t, [Define to the size of __int128_t]) + + +case X$erl_xcomp_bigendian in + X) ;; + Xyes|Xno) ac_cv_c_bigendian=$erl_xcomp_bigendian;; + *) AC_MSG_ERROR([Bad erl_xcomp_bigendian value: $erl_xcomp_bigendian]);; +esac + +AC_C_BIGENDIAN + +if test "$ac_cv_c_bigendian" = "yes"; then + AC_DEFINE(ETHR_BIGENDIAN, 1, [Define if bigendian]) +fi + +case X$erl_xcomp_double_middle_endian in + X) ;; + Xyes|Xno|Xunknown) ac_cv_c_double_middle_endian=$erl_xcomp_double_middle_endian;; + *) AC_MSG_ERROR([Bad erl_xcomp_double_middle_endian value: $erl_xcomp_double_middle_endian]);; +esac + +AC_C_DOUBLE_MIDDLE_ENDIAN + +AC_ARG_ENABLE(native-ethr-impls, + AS_HELP_STRING([--disable-native-ethr-impls], + [disable native ethread implementations]), +[ case "$enableval" in + no) disable_native_ethr_impls=yes ;; + *) disable_native_ethr_impls=no ;; + esac ], disable_native_ethr_impls=no) + +AC_ARG_ENABLE(x86-out-of-order, + AS_HELP_STRING([--enable-x86-out-of-order], + [enable x86/x84_64 out of order support (default disabled)])) + +test "X$disable_native_ethr_impls" = "Xyes" && + AC_DEFINE(ETHR_DISABLE_NATIVE_IMPLS, 1, [Define if you want to disable native ethread implementations]) + +AC_ARG_ENABLE(prefer-gcc-native-ethr-impls, + AS_HELP_STRING([--enable-prefer-gcc-native-ethr-impls], + [prefer gcc native ethread implementations]), +[ case "$enableval" in + yes) enable_prefer_gcc_native_ethr_impls=yes ;; + *) enable_prefer_gcc_native_ethr_impls=no ;; + esac ], enable_prefer_gcc_native_ethr_impls=no) + +test $enable_prefer_gcc_native_ethr_impls = yes && + AC_DEFINE(ETHR_PREFER_GCC_NATIVE_IMPLS, 1, [Define if you prefer gcc native ethread implementations]) + +AC_ARG_WITH(libatomic_ops, + AS_HELP_STRING([--with-libatomic_ops=PATH], + [specify and prefer usage of libatomic_ops in the ethread library])) + +AC_ARG_WITH(with_sparc_memory_order, + AS_HELP_STRING([--with-sparc-memory-order=TSO|PSO|RMO], + [specify sparc memory order (defaults to RMO)])) + +ETHR_X86_SSE2_ASM=no +case "$GCC-$ac_cv_sizeof_void_p-$host_cpu" in + yes-4-i86pc | yes-4-i*86 | yes-4-x86_64 | yes-4-amd64) + AC_MSG_CHECKING([for gcc sse2 asm support]) + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -msse2" + gcc_sse2_asm=no + AC_TRY_COMPILE([], + [ + long long x, *y; + __asm__ __volatile__("movq %1, %0\n\t" : "=x"(x) : "m"(*y) : "memory"); + ], + [gcc_sse2_asm=yes]) + CFLAGS="$save_CFLAGS" + AC_MSG_RESULT([$gcc_sse2_asm]) + if test "$gcc_sse2_asm" = "yes"; then + AC_DEFINE(ETHR_GCC_HAVE_SSE2_ASM_SUPPORT, 1, [Define if you use a gcc that supports -msse2 and understand sse2 specific asm statements]) + ETHR_X86_SSE2_ASM=yes + fi + ;; + *) + ;; +esac + +case "$GCC-$host_cpu" in + yes-i86pc | yes-i*86 | yes-x86_64 | yes-amd64) + gcc_dw_cmpxchg_asm=no + AC_MSG_CHECKING([for gcc double word cmpxchg asm support]) + AC_TRY_COMPILE([], + [ + char xchgd; + long new[2], xchg[2], *p; + __asm__ __volatile__( +#if ETHR_SIZEOF_PTR == 4 && defined(__PIC__) && __PIC__ + "pushl %%ebx\n\t" + "movl %8, %%ebx\n\t" +#endif +#if ETHR_SIZEOF_PTR == 4 + "lock; cmpxchg8b %0\n\t" +#else + "lock; cmpxchg16b %0\n\t" +#endif + "setz %3\n\t" +#if ETHR_SIZEOF_PTR == 4 && defined(__PIC__) && __PIC__ + "popl %%ebx\n\t" +#endif + : "=m"(*p), "=d"(xchg[1]), "=a"(xchg[0]), "=c"(xchgd) + : "m"(*p), "1"(xchg[1]), "2"(xchg[0]), "3"(new[1]), +#if ETHR_SIZEOF_PTR == 4 && defined(__PIC__) && __PIC__ + "r"(new[0]) +#else + "b"(new[0]) +#endif + : "cc", "memory"); + + ], + [gcc_dw_cmpxchg_asm=yes]) + if test $gcc_dw_cmpxchg_asm = no && test $ac_cv_sizeof_void_p = 4; then + AC_TRY_COMPILE([], + [ + char xchgd; + long new[2], xchg[2], *p; +#if !defined(__PIC__) || !__PIC__ +# error nope +#endif + __asm__ __volatile__( + "pushl %%ebx\n\t" + "movl (%7), %%ebx\n\t" + "movl 4(%7), %%ecx\n\t" + "lock; cmpxchg8b %0\n\t" + "setz %3\n\t" + "popl %%ebx\n\t" + : "=m"(*p), "=d"(xchg[1]), "=a"(xchg[0]), "=c"(xchgd) + : "m"(*p), "1"(xchg[1]), "2"(xchg[0]), "3"(new) + : "cc", "memory"); + + ], + [gcc_dw_cmpxchg_asm=yes]) + if test "$gcc_dw_cmpxchg_asm" = "yes"; then + AC_DEFINE(ETHR_CMPXCHG8B_REGISTER_SHORTAGE, 1, [Define if you get a register shortage with cmpxchg8b and position independent code]) + fi + fi + AC_MSG_RESULT([$gcc_dw_cmpxchg_asm]) + if test "$gcc_dw_cmpxchg_asm" = "yes"; then + AC_DEFINE(ETHR_GCC_HAVE_DW_CMPXCHG_ASM_SUPPORT, 1, [Define if you use a gcc that supports the double word cmpxchg instruction]) + fi;; + *) + ;; +esac + +AC_DEFINE(ETHR_HAVE_ETHREAD_DEFINES, 1, \ +[Define if you have all ethread defines]) + +AC_SUBST(ETHR_X_LIBS) +AC_SUBST(ETHR_LIBS) +AC_SUBST(ETHR_LIB_NAME) +AC_SUBST(ETHR_DEFS) +AC_SUBST(ETHR_THR_LIB_BASE) +AC_SUBST(ETHR_THR_LIB_BASE_DIR) +AC_SUBST(ETHR_X86_SSE2_ASM) + +]) + + + +dnl ---------------------------------------------------------------------- +dnl +dnl ERL_TIME_CORRECTION +dnl +dnl In the presence of a high resolution realtime timer Erlang can adapt +dnl its view of time relative to this timer. On solaris such a timer is +dnl available with the syscall gethrtime(). On other OS's a fallback +dnl solution using times() is implemented. (However on e.g. FreeBSD times() +dnl is implemented using gettimeofday so it doesn't make much sense to +dnl use it there...) On second thought, it seems to be safer to do it the +dnl other way around. I.e. only use times() on OS's where we know it will +dnl work... +dnl + +AC_DEFUN(ERL_TIME_CORRECTION, +[if test x$ac_cv_func_gethrtime = x; then + AC_CHECK_FUNC(gethrtime) +fi +if test x$clock_gettime_correction = xunknown; then + AC_TRY_COMPILE([#include <time.h>], + [struct timespec ts; + long long result; + clock_gettime(CLOCK_MONOTONIC,&ts); + result = ((long long) ts.tv_sec) * 1000000000LL + + ((long long) ts.tv_nsec);], + clock_gettime_compiles=yes, + clock_gettime_compiles=no) +else + clock_gettime_compiles=no +fi + + +AC_CACHE_CHECK([how to correct for time adjustments], erl_cv_time_correction, +[ +case $clock_gettime_correction in + yes) + erl_cv_time_correction=clock_gettime;; + no|unknown) + case $ac_cv_func_gethrtime in + yes) + erl_cv_time_correction=hrtime ;; + no) + case $host_os in + linux*) + case $clock_gettime_correction in + unknown) + if test x$clock_gettime_compiles = xyes; then + if test X$cross_compiling != Xyes; then + linux_kernel_vsn_=`uname -r` + case $linux_kernel_vsn_ in + [[0-1]].*|2.[[0-5]]|2.[[0-5]].*) + erl_cv_time_correction=times ;; + *) + erl_cv_time_correction=clock_gettime;; + esac + else + case X$erl_xcomp_linux_clock_gettime_correction in + X) + erl_cv_time_correction=cross;; + Xyes|Xno) + if test $erl_xcomp_linux_clock_gettime_correction = yes; then + erl_cv_time_correction=clock_gettime + else + erl_cv_time_correction=times + fi;; + *) + AC_MSG_ERROR([Bad erl_xcomp_linux_clock_gettime_correction value: $erl_xcomp_linux_clock_gettime_correction]);; + esac + fi + else + erl_cv_time_correction=times + fi + ;; + *) + erl_cv_time_correction=times ;; + esac + ;; + *) + erl_cv_time_correction=none ;; + esac + ;; + esac + ;; +esac +]) + +xrtlib="" +case $erl_cv_time_correction in + times) + AC_DEFINE(CORRECT_USING_TIMES,[], + [Define if you do not have a high-res. timer & want to use times() instead]) + ;; + clock_gettime|cross) + if test $erl_cv_time_correction = cross; then + erl_cv_time_correction=clock_gettime + AC_MSG_WARN([result clock_gettime guessed because of cross compilation]) + fi + xrtlib="-lrt" + AC_DEFINE(GETHRTIME_WITH_CLOCK_GETTIME,[1], + [Define if you want to use clock_gettime to simulate gethrtime]) + ;; +esac +dnl +dnl Check if gethrvtime is working, and if to use procfs ioctl +dnl or (yet to be written) write to the procfs ctl file. +dnl + +AC_MSG_CHECKING([if gethrvtime works and how to use it]) +AC_TRY_RUN([ +/* gethrvtime procfs ioctl test */ +/* These need to be undef:ed to not break activation of + * micro level process accounting on /proc/self + */ +#ifdef _LARGEFILE_SOURCE +# undef _LARGEFILE_SOURCE +#endif +#ifdef _FILE_OFFSET_BITS +# undef _FILE_OFFSET_BITS +#endif +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <stdio.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/signal.h> +#include <sys/fault.h> +#include <sys/syscall.h> +#include <sys/procfs.h> +#include <fcntl.h> + +int main() { + long msacct = PR_MSACCT; + int fd; + long long start, stop; + int i; + pid_t pid = getpid(); + char proc_self[30] = "/proc/"; + + sprintf(proc_self+strlen(proc_self), "%lu", (unsigned long) pid); + if ( (fd = open(proc_self, O_WRONLY)) == -1) + exit(1); + if (ioctl(fd, PIOCSET, &msacct) < 0) + exit(2); + if (close(fd) < 0) + exit(3); + start = gethrvtime(); + for (i = 0; i < 100; i++) + stop = gethrvtime(); + if (start == 0) + exit(4); + if (start == stop) + exit(5); + exit(0); return 0; +} +], +erl_gethrvtime=procfs_ioctl, +erl_gethrvtime=false, +[ +case X$erl_xcomp_gethrvtime_procfs_ioctl in + X) + erl_gethrvtime=cross;; + Xyes|Xno) + if test $erl_xcomp_gethrvtime_procfs_ioctl = yes; then + erl_gethrvtime=procfs_ioctl + else + erl_gethrvtime=false + fi;; + *) + AC_MSG_ERROR([Bad erl_xcomp_gethrvtime_procfs_ioctl value: $erl_xcomp_gethrvtime_procfs_ioctl]);; +esac +]) + +case $erl_gethrvtime in + procfs_ioctl) + AC_DEFINE(HAVE_GETHRVTIME_PROCFS_IOCTL,[1], + [define if gethrvtime() works and uses ioctl() to /proc/self]) + AC_MSG_RESULT(uses ioctl to procfs) + ;; + *) + if test $erl_gethrvtime = cross; then + erl_gethrvtime=false + AC_MSG_RESULT(cross) + AC_MSG_WARN([result 'not working' guessed because of cross compilation]) + else + AC_MSG_RESULT(not working) + fi + + dnl + dnl Check if clock_gettime (linux) is working + dnl + + AC_MSG_CHECKING([if clock_gettime can be used to get process CPU time]) + save_libs=$LIBS + LIBS="-lrt" + AC_TRY_RUN([ + #include <stdlib.h> + #include <unistd.h> + #include <string.h> + #include <stdio.h> + #include <time.h> + int main() { + long long start, stop; + int i; + struct timespec tp; + + if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp) < 0) + exit(1); + start = ((long long)tp.tv_sec * 1000000000LL) + (long long)tp.tv_nsec; + for (i = 0; i < 100; i++) + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp); + stop = ((long long)tp.tv_sec * 1000000000LL) + (long long)tp.tv_nsec; + if (start == 0) + exit(4); + if (start == stop) + exit(5); + exit(0); return 0; + } + ], + erl_clock_gettime=yes, + erl_clock_gettime=no, + [ + case X$erl_xcomp_clock_gettime_cpu_time in + X) erl_clock_gettime=cross;; + Xyes|Xno) erl_clock_gettime=$erl_xcomp_clock_gettime_cpu_time;; + *) AC_MSG_ERROR([Bad erl_xcomp_clock_gettime_cpu_time value: $erl_xcomp_clock_gettime_cpu_time]);; + esac + ]) + LIBS=$save_libs + case $host_os in + linux*) + AC_MSG_RESULT([no; not stable]) + LIBRT=$xrtlib + ;; + *) + AC_MSG_RESULT($erl_clock_gettime) + case $erl_clock_gettime in + yes) + AC_DEFINE(HAVE_CLOCK_GETTIME,[], + [define if clock_gettime() works for getting process time]) + LIBRT=-lrt + ;; + cross) + erl_clock_gettime=no + AC_MSG_WARN([result no guessed because of cross compilation]) + LIBRT=$xrtlib + ;; + *) + LIBRT=$xrtlib + ;; + esac + ;; + esac + AC_SUBST(LIBRT) + ;; +esac +])dnl + +dnl ---------------------------------------------------------------------- +dnl +dnl LM_TRY_ENABLE_CFLAG +dnl +dnl +dnl Tries a CFLAG and sees if it can be enabled without compiler errors +dnl $1: textual cflag to add +dnl $2: variable to store the modified CFLAG in +dnl Usage example LM_TRY_ENABLE_CFLAG([-Werror=return-type], [CFLAGS]) +dnl +dnl +AC_DEFUN([LM_TRY_ENABLE_CFLAG], [ + AC_MSG_CHECKING([if we can add $1 to CFLAGS]) + saved_CFLAGS=$CFLAGS; + CFLAGS="$1 $CFLAGS"; + AC_TRY_COMPILE([],[return 0;],can_enable_flag=true,can_enable_flag=false) + CFLAGS=$saved_CFLAGS; + if test "X$can_enable_flag" = "Xtrue"; then + AC_MSG_RESULT([yes]) + AS_VAR_SET($2, "$1 $CFLAGS") + else + AC_MSG_RESULT([no]) + AS_VAR_SET($2, "$CFLAGS") + fi +]) + +dnl ERL_TRY_LINK_JAVA(CLASSES, FUNCTION-BODY +dnl [ACTION_IF_FOUND [, ACTION-IF-NOT-FOUND]]) +dnl Freely inspired by AC_TRY_LINK. (Maybe better to create a +dnl AC_LANG_JAVA instead...) +AC_DEFUN(ERL_TRY_LINK_JAVA, +[java_link='$JAVAC conftest.java 1>&AC_FD_CC' +changequote(, )dnl +cat > conftest.java <<EOF +$1 +class conftest { public static void main(String[] args) { + $2 + ; return; }} +EOF +changequote([, ])dnl +if AC_TRY_EVAL(java_link) && test -s conftest.class; then + ifelse([$3], , :, [rm -rf conftest* + $3]) +else + echo "configure: failed program was:" 1>&AC_FD_CC + cat conftest.java 1>&AC_FD_CC + echo "configure: PATH was $PATH" 1>&AC_FD_CC +ifelse([$4], , , [ rm -rf conftest* + $4 +])dnl +fi +rm -f conftest*]) +#define UNSAFE_MASK 0xc0000000 /* Mask for bits that must be constant */ + + diff --git a/lib/megaco/configure.in b/lib/megaco/configure.in index 722ccc3fb4..9c3858f562 100644 --- a/lib/megaco/configure.in +++ b/lib/megaco/configure.in @@ -273,6 +273,11 @@ if test "$PERL" = no_perl; then AC_MSG_ERROR([Perl is required to build the flex scanner!]) fi +if test "x$GCC" = xyes; then + # Treat certain GCC warnings as errors + LM_TRY_ENABLE_CFLAG([-Werror=return-type], [CFLAGS]) +fi + AC_OUTPUT(examples/meas/Makefile:examples/meas/Makefile.in) AC_OUTPUT(src/flex/$host/Makefile:src/flex/Makefile.in) diff --git a/lib/odbc/aclocal.m4 b/lib/odbc/aclocal.m4 index 9578cd35c4..5d555a5123 100644 --- a/lib/odbc/aclocal.m4 +++ b/lib/odbc/aclocal.m4 @@ -1849,6 +1849,32 @@ case $erl_gethrvtime in esac ])dnl +dnl ---------------------------------------------------------------------- +dnl +dnl LM_TRY_ENABLE_CFLAG +dnl +dnl +dnl Tries a CFLAG and sees if it can be enabled without compiler errors +dnl $1: textual cflag to add +dnl $2: variable to store the modified CFLAG in +dnl Usage example LM_TRY_ENABLE_CFLAG([-Werror=return-type], [CFLAGS]) +dnl +dnl +AC_DEFUN([LM_TRY_ENABLE_CFLAG], [ + AC_MSG_CHECKING([if we can add $1 to CFLAGS]) + saved_CFLAGS=$CFLAGS; + CFLAGS="$1 $CFLAGS"; + AC_TRY_COMPILE([],[return 0;],can_enable_flag=true,can_enable_flag=false) + CFLAGS=$saved_CFLAGS; + if test "X$can_enable_flag" = "Xtrue"; then + AC_MSG_RESULT([yes]) + AS_VAR_SET($2, "$1 $CFLAGS") + else + AC_MSG_RESULT([no]) + AS_VAR_SET($2, "$CFLAGS") + fi +]) + dnl ERL_TRY_LINK_JAVA(CLASSES, FUNCTION-BODY dnl [ACTION_IF_FOUND [, ACTION-IF-NOT-FOUND]]) dnl Freely inspired by AC_TRY_LINK. (Maybe better to create a diff --git a/lib/odbc/configure.in b/lib/odbc/configure.in index bec65c71bf..e6ba9f57f5 100644 --- a/lib/odbc/configure.in +++ b/lib/odbc/configure.in @@ -212,4 +212,9 @@ AC_SUBST(ODBC_INCLUDE) fi dnl "$with_odbc" != "no" +if test "x$GCC" = xyes; then + # Treat certain GCC warnings as errors + LM_TRY_ENABLE_CFLAG([-Werror=return-type], [CFLAGS]) +fi + AC_OUTPUT(c_src/$host/Makefile:c_src/Makefile.in) diff --git a/lib/os_mon/src/os_mon.erl b/lib/os_mon/src/os_mon.erl index df1eccb064..19acae9f0e 100644 --- a/lib/os_mon/src/os_mon.erl +++ b/lib/os_mon/src/os_mon.erl @@ -176,9 +176,7 @@ services({unix, sunos}) -> services({unix, _}) -> % Other unix. [cpu_sup, disksup, memsup]; services({win32, _}) -> - [disksup, memsup, os_sup, sysinfo]; -services(_) -> - []. + [disksup, memsup, os_sup, sysinfo]. server_name(cpu_sup) -> cpu_sup; server_name(disksup) -> disksup; diff --git a/lib/public_key/doc/src/cert_records.xml b/lib/public_key/doc/src/cert_records.xml index 94c7c46350..b1d2a05200 100644 --- a/lib/public_key/doc/src/cert_records.xml +++ b/lib/public_key/doc/src/cert_records.xml @@ -137,7 +137,7 @@ issuer, % {rdnSequence, [#AttributeTypeAndValue'{}]} validity, % #'Validity'{} subject, % {rdnSequence, [#AttributeTypeAndValue'{}]} - subjectPublicKeyInfo, % #'SubjectPublicKeyInfo'{} + subjectPublicKeyInfo, % #'OTPSubjectPublicKeyInfo'{} issuerUniqueID, % binary() | asn1_novalue subjectUniqueID, % binary() | asn1_novalue extensions % [#'Extension'{}] diff --git a/lib/reltool/src/reltool_target.erl b/lib/reltool/src/reltool_target.erl index 6cb7ba0163..1f4ce7226a 100644 --- a/lib/reltool/src/reltool_target.erl +++ b/lib/reltool/src/reltool_target.erl @@ -482,33 +482,12 @@ do_gen_script(#rel{name = RelName, vsn = RelVsn}, %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -load_app_mods(#app{mods = Mods} = App, Mand, PathFlag, Variables) -> +load_app_mods(#app{mods = Mods0} = App, Mand, PathFlag, Variables) -> Path = cr_path(App, PathFlag, Variables), - PartNames = - lists:sort([{packages:split(M),M} || - #mod{name = M, is_included=true} <- Mods, - not lists:member(M, Mand)]), - SplitMods = - lists:foldl( - fun({Parts,M}, [{Last, Acc}|Rest]) -> - [_|Tail] = lists:reverse(Parts), - case lists:reverse(Tail) of - Subs when Subs == Last -> - [{Last,[M|Acc]}|Rest]; - Subs -> - [{Subs, [M]}|[{Last,Acc}|Rest]] - end - end, - [{[], - []}], - PartNames), - lists:foldl( - fun({Subs,Ms}, Cmds) -> - [{path, [filename:join([Path | Subs])]}, - {primLoad, lists:sort(Ms)} | Cmds] - end, - [], - SplitMods). + Mods = [M || #mod{name = M, is_included=true} <- Mods0, + not lists:member(M, Mand)], + [{path, [filename:join([Path])]}, + {primLoad, lists:sort(Mods)}]. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% sort_used_and_incl_apps(Apps, OrderedApps) -> Apps diff --git a/lib/sasl/src/systools_make.erl b/lib/sasl/src/systools_make.erl index 29c4a0d168..9b2e2c809b 100644 --- a/lib/sasl/src/systools_make.erl +++ b/lib/sasl/src/systools_make.erl @@ -1067,11 +1067,10 @@ check_mod(Mod,App,Dir,Ext,IncPath) -> end. mod_to_filename(Dir, Mod, Ext) -> - Parts = packages:split(Mod), - filename:join([Dir | Parts]) ++ Ext. + filename:join(Dir, atom_to_list(Mod) ++ Ext). check_module(Mod, Dir, ObjModTime, IncPath) -> - {SrcDirs,_IncDirs}= smart_guess(Mod, Dir,IncPath), + {SrcDirs,_IncDirs}= smart_guess(Dir,IncPath), case locate_src(Mod,SrcDirs) of {ok,_FDir,_File,LastModTime} -> if @@ -1085,7 +1084,7 @@ check_module(Mod, Dir, ObjModTime, IncPath) -> end. locate_src(Mod,[Dir|Dirs]) -> - File = filename:join(Dir, mod_to_fname(Mod) ++ ".erl"), + File = mod_to_filename(Dir, Mod, ".erl"), case file:read_file_info(File) of {ok,FileInfo} -> LastModTime = FileInfo#file_info.mtime, @@ -1096,9 +1095,6 @@ locate_src(Mod,[Dir|Dirs]) -> locate_src(_,[]) -> false. -mod_to_fname(Mod) -> - hd(lists:reverse(packages:split(Mod))). - %%______________________________________________________________________ %% smart_guess(Mod, Dir,IncludePath) -> {[Dirs],[IncDirs]} @@ -1106,17 +1102,12 @@ mod_to_fname(Mod) -> %% src-dir should be one of .../src or .../src/e_src %% If dir does not contain .../ebin set dir to the same directory. -smart_guess(Mod, Dir,IncPath) -> +smart_guess(Dir,IncPath) -> case reverse(filename:split(Dir)) of ["ebin"|D] -> - Subdirs = case packages:split(Mod) of - [_] -> []; - [_|_] = Parts -> - lists:reverse(tl(lists:reverse(Parts))) - end, D1 = reverse(D), - Dirs = [filename:join(D1 ++ ["src" | Subdirs]), - filename:join(D1 ++ ["src", "e_src" | Subdirs])], + Dirs = [filename:join(D1 ++ ["src"]), + filename:join(D1 ++ ["src", "e_src"])], {Dirs,Dirs ++ IncPath}; _ -> {[Dir],[Dir] ++ IncPath} @@ -1423,23 +1414,8 @@ load_appl_mods([], _, _, _) -> [{progress, modules_loaded}]. load_commands(Mods, Path) -> - SplitMods = lists:foldl( - fun({Parts,M}, [{Last, Acc}|Rest]) -> - [_|Tail] = lists:reverse(Parts), - case lists:reverse(Tail) of - Subs when Subs == Last -> - [{Last,[M|Acc]}|Rest]; - Subs -> - [{Subs, [M]}|[{Last,Acc}|Rest]] - end - end, [{[],[]}], - lists:sort([{packages:split(M),M} || M <- Mods])), - lists:foldl( - fun({Subs,Ms}, Cmds) -> - [{path, [filename:join([Path | Subs])]}, - {primLoad,lists:sort(Ms)} | Cmds] - end, [], SplitMods). - + [{path, [filename:join([Path])]}, + {primLoad,lists:sort(Mods)}]. %%______________________________________________________________________ %% Pack an application to an application term. diff --git a/lib/ssh/doc/src/ssh_protocol.xml b/lib/ssh/doc/src/ssh_protocol.xml index 6a253c43eb..28f42f5707 100644 --- a/lib/ssh/doc/src/ssh_protocol.xml +++ b/lib/ssh/doc/src/ssh_protocol.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2012</year> + <year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -110,8 +110,7 @@ read-eval-print loop. It is also possible, but much more work, to provide your own CLI (Command Line Interface) implementation. </item> - <item><em>Exec</em> - one-time remote execution (like - SCP). See <seealso + <item><em>Exec</em> - one-time remote execution of commands. See <seealso marker="ssh_connection#exec-4">ssh_connection:exec/4</seealso></item> </list> </section> diff --git a/lib/ssl/test/Makefile b/lib/ssl/test/Makefile index d36dcb588b..847907cde8 100644 --- a/lib/ssl/test/Makefile +++ b/lib/ssl/test/Makefile @@ -37,15 +37,16 @@ VSN=$(GS_VSN) MODULES = \ ssl_test_lib \ ssl_basic_SUITE \ - ssl_handshake_SUITE \ - ssl_packet_SUITE \ ssl_cipher_SUITE \ - ssl_payload_SUITE \ - ssl_to_openssl_SUITE \ - ssl_session_cache_SUITE \ + ssl_certificate_verify_SUITE\ ssl_dist_SUITE \ + ssl_handshake_SUITE \ ssl_npn_hello_SUITE \ ssl_npn_handshake_SUITE \ + ssl_packet_SUITE \ + ssl_payload_SUITE \ + ssl_session_cache_SUITE \ + ssl_to_openssl_SUITE \ make_certs\ erl_make_certs diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl index faed91e559..5ba71f9218 100644 --- a/lib/ssl/test/ssl_basic_SUITE.erl +++ b/lib/ssl/test/ssl_basic_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2012. All Rights Reserved. +%% Copyright Ericsson AB 2007-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -41,127 +41,10 @@ -define(RENEGOTIATION_DISABLE_TIME, 12000). -define(CLEAN_SESSION_DB, 60000). -%% Test server callback functions %%-------------------------------------------------------------------- -%% Function: init_per_suite(Config) -> Config -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% Description: Initialization before the whole suite -%% -%% Note: This function is free to add any key/value pairs to the Config -%% variable, but should NOT alter/remove any existing entries. -%%-------------------------------------------------------------------- -init_per_suite(Config0) -> - Dog = ssl_test_lib:timetrap(?LONG_TIMEOUT *2), - catch crypto:stop(), - try crypto:start() of - ok -> - application:start(public_key), - - %% make rsa certs using oppenssl - Result = - (catch make_certs:all(?config(data_dir, Config0), - ?config(priv_dir, Config0))), - test_server:format("Make certs ~p~n", [Result]), - - Config1 = ssl_test_lib:make_dsa_cert(Config0), - Config = ssl_test_lib:cert_options(Config1), - [{watchdog, Dog} | Config] - catch _:_ -> - {skip, "Crypto did not start"} - end. -%%-------------------------------------------------------------------- -%% Function: end_per_suite(Config) -> _ -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% Description: Cleanup after the whole suite -%%-------------------------------------------------------------------- -end_per_suite(_Config) -> - ssl:stop(), - application:stop(crypto). - -%%-------------------------------------------------------------------- -%% Function: init_per_testcase(TestCase, Config) -> Config -%% Case - atom() -%% Name of the test case that is about to be run. -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% -%% Description: Initialization before each test case -%% -%% Note: This function is free to add any key/value pairs to the Config -%% variable, but should NOT alter/remove any existing entries. -%% Description: Initialization before each test case -%%-------------------------------------------------------------------- -init_per_testcase(no_authority_key_identifier, Config) -> - %% Clear cach so that root cert will not - %% be found. - ssl:clear_pem_cache(), - Config; - -init_per_testcase(protocol_versions, Config) -> - ssl:stop(), - application:load(ssl), - %% For backwards compatibility sslv2 should be filtered out. - application:set_env(ssl, protocol_version, [sslv2, sslv3, tlsv1]), - ssl:start(), - Config; - -init_per_testcase(reuse_session_expired, Config0) -> - Config = lists:keydelete(watchdog, 1, Config0), - ssl:stop(), - application:load(ssl), - application:set_env(ssl, session_lifetime, ?EXPIRE), - application:set_env(ssl, session_delay_cleanup_time, 500), - ssl:start(), - Config; - -init_per_testcase(empty_protocol_versions, Config) -> - ssl:stop(), - application:load(ssl), - application:set_env(ssl, protocol_version, []), - ssl:start(), - Config; - -%% init_per_testcase(different_ca_peer_sign, Config0) -> -%% ssl_test_lib:make_mix_cert(Config0); - -init_per_testcase(_TestCase, Config0) -> - test_server:format("TLS/SSL version ~p~n ", [ssl_record:supported_protocol_versions()]), - Config = lists:keydelete(watchdog, 1, Config0), - Dog = test_server:timetrap(?TIMEOUT), - [{watchdog, Dog} | Config]. - -%%-------------------------------------------------------------------- -%% Function: end_per_testcase(TestCase, Config) -> _ -%% Case - atom() -%% Name of the test case that is about to be run. -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% Description: Cleanup after each test case +%% Common Test interface functions ----------------------------------- %%-------------------------------------------------------------------- -end_per_testcase(reuse_session_expired, Config) -> - application:unset_env(ssl, session_lifetime), - application:unset_env(ssl, session_delay_cleanup_time), - end_per_testcase(default_action, Config); -end_per_testcase(_TestCase, Config) -> - Dog = ?config(watchdog, Config), - case Dog of - undefined -> - ok; - _ -> - test_server:timetrap_cancel(Dog) - end. - -%%-------------------------------------------------------------------- -%% Function: all(Clause) -> TestCases -%% Clause - atom() - suite | doc -%% TestCases - [Case] -%% Case - atom() -%% Name of a test case. -%% Description: Returns a list of all test cases in this test suite -%%-------------------------------------------------------------------- suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> @@ -183,7 +66,6 @@ groups() -> {'tlsv1', [], all_versions_groups() ++ rizzo_tests()}, {'sslv3', [], all_versions_groups() ++ rizzo_tests()}, {api,[], api_tests()}, - {certificate_verify, [], certificate_verify_tests()}, {session, [], session_tests()}, {renegotiate, [], renegotiate_tests()}, {ciphers, [], cipher_tests()}, @@ -192,29 +74,10 @@ groups() -> all_versions_groups ()-> [{group, api}, - {group, certificate_verify}, {group, renegotiate}, {group, ciphers}, {group, error_handling_tests}]. -init_per_group(GroupName, Config) -> - case ssl_test_lib:is_tls_version(GroupName) of - true -> - case ssl_test_lib:sufficient_crypto_support(GroupName) of - true -> - ssl_test_lib:init_tls_version(GroupName), - Config; - false -> - {skip, "Missing crypto support"} - end; - _ -> - ssl:start(), - Config - end. - - -end_per_group(_GroupName, Config) -> - Config. basic_tests() -> [app, @@ -242,7 +105,8 @@ options_tests() -> protocol_versions, empty_protocol_versions, ipv6, - reuseaddr]. + reuseaddr, + tcp_reuseaddr]. api_tests() -> [connection_info, @@ -264,38 +128,6 @@ api_tests() -> ssl_recv_timeout ]. -certificate_verify_tests() -> - [server_verify_peer_passive, - server_verify_peer_active, - server_verify_peer_active_once, - server_verify_none_passive, - server_verify_none_active, - server_verify_none_active_once, - server_verify_no_cacerts, - server_require_peer_cert_ok, - server_require_peer_cert_fail, - server_verify_client_once_passive, - server_verify_client_once_active, - server_verify_client_once_active_once, - new_server_wants_peer_cert, - client_verify_none_passive, - client_verify_none_active, - client_verify_none_active_once, - extended_key_usage_verify_peer, - extended_key_usage_verify_none, - invalid_signature_client, - invalid_signature_server, - cert_expired, - client_with_cert_cipher_suites_handshake, - verify_fun_always_run_client, - verify_fun_always_run_server, - unknown_server_ca_fail, - unknown_server_ca_accept_verify_none, - unknown_server_ca_accept_verify_peer, - unknown_server_ca_accept_backwardscompatibility, - no_authority_key_identifier - ]. - session_tests() -> [reuse_session, reuse_session_expired, @@ -335,19 +167,109 @@ rizzo_tests() -> [rizzo, no_rizzo_rc4]. -%% Test cases starts here. %%-------------------------------------------------------------------- -app(doc) -> - "Test that the ssl app file is ok"; -app(suite) -> - []; +init_per_suite(Config0) -> + Dog = ct:timetrap(?LONG_TIMEOUT *2), + catch crypto:stop(), + try crypto:start() of + ok -> + application:start(public_key), + + %% make rsa certs using oppenssl + Result = + (catch make_certs:all(?config(data_dir, Config0), + ?config(priv_dir, Config0))), + ct:print("Make certs ~p~n", [Result]), + + Config1 = ssl_test_lib:make_dsa_cert(Config0), + Config = ssl_test_lib:cert_options(Config1), + [{watchdog, Dog} | Config] + catch _:_ -> + {skip, "Crypto did not start"} + end. + +end_per_suite(_Config) -> + ssl:stop(), + application:stop(crypto). + +%%-------------------------------------------------------------------- +init_per_group(GroupName, Config) -> + case ssl_test_lib:is_tls_version(GroupName) of + true -> + case ssl_test_lib:sufficient_crypto_support(GroupName) of + true -> + ssl_test_lib:init_tls_version(GroupName), + Config; + false -> + {skip, "Missing crypto support"} + end; + _ -> + ssl:start(), + Config + end. + + +end_per_group(_GroupName, Config) -> + Config. + +%%-------------------------------------------------------------------- +init_per_testcase(no_authority_key_identifier, Config) -> + %% Clear cach so that root cert will not + %% be found. + ssl:clear_pem_cache(), + Config; + +init_per_testcase(protocol_versions, Config) -> + ssl:stop(), + application:load(ssl), + %% For backwards compatibility sslv2 should be filtered out. + application:set_env(ssl, protocol_version, [sslv2, sslv3, tlsv1]), + ssl:start(), + Config; + +init_per_testcase(reuse_session_expired, Config0) -> + Config = lists:keydelete(watchdog, 1, Config0), + ssl:stop(), + application:load(ssl), + application:set_env(ssl, session_lifetime, ?EXPIRE), + application:set_env(ssl, session_delay_cleanup_time, 500), + ssl:start(), + Config; + +init_per_testcase(empty_protocol_versions, Config) -> + ssl:stop(), + application:load(ssl), + application:set_env(ssl, protocol_version, []), + ssl:start(), + Config; + +%% init_per_testcase(different_ca_peer_sign, Config0) -> +%% ssl_test_lib:make_mix_cert(Config0); + +init_per_testcase(_TestCase, Config0) -> + ct:print("TLS/SSL version ~p~n ", [ssl_record:supported_protocol_versions()]), + Config = lists:keydelete(watchdog, 1, Config0), + Dog = ct:timetrap(?TIMEOUT), + [{watchdog, Dog} | Config]. + +end_per_testcase(reuse_session_expired, Config) -> + application:unset_env(ssl, session_lifetime), + application:unset_env(ssl, session_delay_cleanup_time), + end_per_testcase(default_action, Config); + +end_per_testcase(_TestCase, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Test Cases -------------------------------------------------------- +%%-------------------------------------------------------------------- +app() -> + [{doc, "Test that the ssl app file is ok"}]. app(Config) when is_list(Config) -> - ok = test_server:app_test(ssl). + ok = ?t:app_test(ssl). %%-------------------------------------------------------------------- -alerts(doc) -> - "Test ssl_alert:alert_txt/1"; -alerts(suite) -> - []; +alerts() -> + [{doc, "Test ssl_alert:alert_txt/1"}]. alerts(Config) when is_list(Config) -> Descriptions = [?CLOSE_NOTIFY, ?UNEXPECTED_MESSAGE, ?BAD_RECORD_MAC, ?DECRYPTION_FAILED, ?RECORD_OVERFLOW, ?DECOMPRESSION_FAILURE, @@ -364,14 +286,12 @@ alerts(Config) when is_list(Config) -> Txt when is_list(Txt) -> ok; Other -> - test_server:fail({unexpected, Other}) + ct:fail({unexpected, Other}) end end, Alerts). %%-------------------------------------------------------------------- -connection_info(doc) -> - ["Test the API function ssl:connection_info/1"]; -connection_info(suite) -> - []; +connection_info() -> + [{doc,"Test the API function ssl:connection_info/1"}]. connection_info(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -390,7 +310,7 @@ connection_info(Config) when is_list(Config) -> [{ciphers,[{rsa,rc4_128,sha,no_export}]} | ClientOpts]}]), - test_server:format("Testcase ~p, Client ~p Server ~p ~n", + ct:print("Testcase ~p, Client ~p Server ~p ~n", [self(), Client, Server]), Version = @@ -403,58 +323,23 @@ connection_info(Config) when is_list(Config) -> ssl_test_lib:close(Server), ssl_test_lib:close(Client). -connection_info_result(Socket) -> - ssl:connection_info(Socket). - %%-------------------------------------------------------------------- - -protocol_versions(doc) -> - ["Test to set a list of protocol versions in app environment."]; - -protocol_versions(suite) -> - []; +protocol_versions() -> + [{doc,"Test to set a list of protocol versions in app environment."}]. protocol_versions(Config) when is_list(Config) -> basic_test(Config). - -empty_protocol_versions(doc) -> - ["Test to set an empty list of protocol versions in app environment."]; - -empty_protocol_versions(suite) -> - []; +%%-------------------------------------------------------------------- +empty_protocol_versions() -> + [{doc,"Test to set an empty list of protocol versions in app environment."}]. empty_protocol_versions(Config) when is_list(Config) -> basic_test(Config). - -basic_test(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send_recv_result_active, []}}, - {options, ServerOpts}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, send_recv_result_active, []}}, - {options, ClientOpts}]), - - ssl_test_lib:check_result(Server, ok, Client, ok), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). %%-------------------------------------------------------------------- -controlling_process(doc) -> - ["Test API function controlling_process/2"]; - -controlling_process(suite) -> - []; +controlling_process() -> + [{doc,"Test API function controlling_process/2"}]. controlling_process(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -478,7 +363,7 @@ controlling_process(Config) when is_list(Config) -> ClientMsg]}}, {options, ClientOpts}]), - test_server:format("Testcase ~p, Client ~p Server ~p ~n", + ct:print("Testcase ~p, Client ~p Server ~p ~n", [self(), Client, Server]), receive @@ -497,46 +382,15 @@ controlling_process(Config) when is_list(Config) -> ok end; Unexpected -> - test_server:fail(Unexpected) + ct:fail(Unexpected) end, ssl_test_lib:close(Server), ssl_test_lib:close(Client). -controlling_process_result(Socket, Pid, Msg) -> - ok = ssl:controlling_process(Socket, Pid), - %% Make sure other side has evaluated controlling_process - %% before message is sent - test_server:sleep(?SLEEP), - ssl:send(Socket, Msg), - no_result_msg. - -receive_s_rizzo_duong_beast() -> - receive - {ssl, _, "erver hello"} -> - receive - {ssl, _, "C"} -> - receive - {ssl, _, "lient hello"} -> - ok - end - end - end. -receive_c_rizzo_duong_beast() -> - receive - {ssl, _, "lient hello"} -> - receive - {ssl, _, "S"} -> - receive - {ssl, _, "erver hello"} -> - ok - end - end - end. %%-------------------------------------------------------------------- -controller_dies(doc) -> - ["Test that the socket is closed after controlling process dies"]; -controller_dies(suite) -> []; +controller_dies() -> + [{doc,"Test that the socket is closed after controlling process dies"}]. controller_dies(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -559,8 +413,8 @@ controller_dies(Config) when is_list(Config) -> ClientMsg]}}, {options, ClientOpts}]), - test_server:format("Testcase ~p, Client ~p Server ~p ~n", [self(), Client, Server]), - test_server:sleep(?SLEEP), %% so that they are connected + ct:print("Testcase ~p, Client ~p Server ~p ~n", [self(), Client, Server]), + ct:sleep(?SLEEP), %% so that they are connected process_flag(trap_exit, true), @@ -577,7 +431,7 @@ controller_dies(Config) when is_list(Config) -> %% Make sure server finishes and verification %% and is in coonection state before %% killing client - test_server:sleep(?SLEEP), + ct:sleep(?SLEEP), Pid ! {self(), connected, Socket}, receive die_nice -> normal end end, @@ -597,13 +451,13 @@ controller_dies(Config) when is_list(Config) -> Client3 ! die_nice end, - test_server:format("Wating on exit ~p~n",[Client3]), + ct:print("Wating on exit ~p~n",[Client3]), receive {'EXIT', Client3, normal} -> ok end, receive %% Client3 is dead but that doesn't matter, socket should not be closed. Unexpected -> - test_server:format("Unexpected ~p~n",[Unexpected]), - test_server:fail({line, ?LINE-1}) + ct:print("Unexpected ~p~n",[Unexpected]), + ct:fail({line, ?LINE-1}) after 1000 -> ok end, @@ -619,39 +473,17 @@ controller_dies(Config) when is_list(Config) -> controller_dies_result, [self(), ClientMsg]}}, {options, [{reuseaddr,true}|ClientOpts]}]), - test_server:sleep(?SLEEP), %% so that they are connected + ct:sleep(?SLEEP), %% so that they are connected exit(Server, killed), get_close(Server, ?LINE), process_flag(trap_exit, false), ssl_test_lib:close(LastClient). -controller_dies_result(_Socket, _Pid, _Msg) -> - receive Result -> Result end. - -get_close(Pid, Where) -> - receive - {'EXIT', Pid, _Reason} -> - receive - {_, {ssl_closed, Socket}} -> - test_server:format("Socket closed ~p~n",[Socket]); - Unexpected -> - test_server:format("Unexpected ~p~n",[Unexpected]), - test_server:fail({line, ?LINE-1}) - after 5000 -> - test_server:fail({timeout, {line, ?LINE, Where}}) - end; - Unexpected -> - test_server:format("Unexpected ~p~n",[Unexpected]), - test_server:fail({line, ?LINE-1}) - after 5000 -> - test_server:fail({timeout, {line, ?LINE, Where}}) - end. - %%-------------------------------------------------------------------- -client_closes_socket(doc) -> - ["Test what happens when client closes socket before handshake is compleated"]; -client_closes_socket(suite) -> []; +client_closes_socket() -> + [{doc,"Test what happens when client closes socket before handshake is compleated"}]. + client_closes_socket(Config) when is_list(Config) -> ServerOpts = ?config(server_opts, Config), {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), @@ -668,7 +500,7 @@ client_closes_socket(Config) when is_list(Config) -> [Hostname, Port, TcpOpts]), %% Make sure that ssl_accept is called before %% client process ends and closes socket. - test_server:sleep(?SLEEP) + ct:sleep(?SLEEP) end, _Client = spawn_link(Connect), @@ -676,11 +508,8 @@ client_closes_socket(Config) when is_list(Config) -> ssl_test_lib:check_result(Server, {error,closed}). %%-------------------------------------------------------------------- -connect_dist(doc) -> - ["Test a simple connect as is used by distribution"]; - -connect_dist(suite) -> - []; +connect_dist() -> + [{doc,"Test a simple connect as is used by distribution"}]. connect_dist(Config) when is_list(Config) -> ClientOpts0 = ?config(client_kc_opts, Config), @@ -706,22 +535,9 @@ connect_dist(Config) when is_list(Config) -> ssl_test_lib:close(Server), ssl_test_lib:close(Client). -connect_dist_s(S) -> - Msg = term_to_binary({erlang,term}), - ok = ssl:send(S, Msg). - -connect_dist_c(S) -> - Test = binary_to_list(term_to_binary({erlang,term})), - {ok, Test} = ssl:recv(S, 0, 10000), - ok. - - %%-------------------------------------------------------------------- -peername(doc) -> - ["Test API function peername/1"]; - -peername(suite) -> - []; +peername() -> + [{doc,"Test API function peername/1"}]. peername(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -744,7 +560,7 @@ peername(Config) when is_list(Config) -> ServerMsg = {ok, {ClientIp, ClientPort}}, ClientMsg = {ok, {ServerIp, Port}}, - test_server:format("Testcase ~p, Client ~p Server ~p ~n", + ct:print("Testcase ~p, Client ~p Server ~p ~n", [self(), Client, Server]), ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg), @@ -752,14 +568,9 @@ peername(Config) when is_list(Config) -> ssl_test_lib:close(Server), ssl_test_lib:close(Client). -peername_result(S) -> - ssl:peername(S). - %%-------------------------------------------------------------------- -peercert(doc) -> - [""]; -peercert(suite) -> - []; +peercert() -> + [{doc,"Test API function peercert/1"}]. peercert(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -782,7 +593,7 @@ peercert(Config) when is_list(Config) -> ServerMsg = {error, no_peercert}, ClientMsg = {ok, BinCert}, - test_server:format("Testcase ~p, Client ~p Server ~p ~n", + ct:print("Testcase ~p, Client ~p Server ~p ~n", [self(), Client, Server]), ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg), @@ -794,10 +605,8 @@ peercert_result(Socket) -> ssl:peercert(Socket). %%-------------------------------------------------------------------- -peercert_with_client_cert(doc) -> - [""]; -peercert_with_client_cert(suite) -> - []; +peercert_with_client_cert() -> + [{doc,"Test API function peercert/1"}]. peercert_with_client_cert(Config) when is_list(Config) -> ClientOpts = ?config(client_dsa_opts, Config), ServerOpts = ?config(server_dsa_verify_opts, Config), @@ -822,7 +631,7 @@ peercert_with_client_cert(Config) when is_list(Config) -> ServerMsg = {ok, ClientBinCert}, ClientMsg = {ok, ServerBinCert}, - test_server:format("Testcase ~p, Client ~p Server ~p ~n", + ct:print("Testcase ~p, Client ~p Server ~p ~n", [self(), Client, Server]), ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg), @@ -831,12 +640,8 @@ peercert_with_client_cert(Config) when is_list(Config) -> ssl_test_lib:close(Client). %%-------------------------------------------------------------------- -sockname(doc) -> - ["Test API function sockname/1"]; - -sockname(suite) -> - []; - +sockname() -> + [{doc,"Test API function sockname/1"}]. sockname(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -858,7 +663,7 @@ sockname(Config) when is_list(Config) -> ServerMsg = {ok, {ServerIp, Port}}, ClientMsg = {ok, {ClientIp, ClientPort}}, - test_server:format("Testcase ~p, Client ~p Server ~p ~n", + ct:print("Testcase ~p, Client ~p Server ~p ~n", [self(), Client, Server]), ssl_test_lib:check_result(Server, ServerMsg, Client, ClientMsg), @@ -870,11 +675,8 @@ sockname_result(S) -> ssl:sockname(S). %%-------------------------------------------------------------------- -cipher_suites(doc) -> - ["Test API function cipher_suites/0"]; - -cipher_suites(suite) -> - []; +cipher_suites() -> + [{doc,"Test API function cipher_suites/0"}]. cipher_suites(Config) when is_list(Config) -> MandatoryCipherSuite = {rsa,'3des_ede_cbc',sha}, @@ -884,11 +686,8 @@ cipher_suites(Config) when is_list(Config) -> [_|_] =ssl:cipher_suites(openssl). %%-------------------------------------------------------------------- -socket_options(doc) -> - ["Test API function getopts/2 and setopts/2"]; - -socket_options(suite) -> - []; +socket_options() -> + [{doc,"Test API function getopts/2 and setopts/2"}]. socket_options(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -937,16 +736,13 @@ socket_options_result(Socket, Options, DefaultValues, NewOptions, NewValues) -> ssl:setopts(Socket, [{nodelay, true}]), {ok,[{nodelay, true}]} = ssl:getopts(Socket, [nodelay]), {ok, All} = ssl:getopts(Socket, []), - test_server:format("All opts ~p~n", [All]), + ct:print("All opts ~p~n", [All]), ok. %%-------------------------------------------------------------------- -invalid_inet_get_option(doc) -> - ["Test handling of invalid inet options in getopts"]; - -invalid_inet_get_option(suite) -> - []; +invalid_inet_get_option() -> + [{doc,"Test handling of invalid inet options in getopts"}]. invalid_inet_get_option(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -963,24 +759,16 @@ invalid_inet_get_option(Config) when is_list(Config) -> {mfa, {ssl_test_lib, no_result, []}}, {options, ClientOpts}]), - test_server:format("Testcase ~p, Client ~p Server ~p ~n", + ct:print("Testcase ~p, Client ~p Server ~p ~n", [self(), Client, Server]), ssl_test_lib:check_result(Server, ok), ssl_test_lib:close(Server), ssl_test_lib:close(Client). - -get_invalid_inet_option(Socket) -> - {error, {eoptions, {inet_option, foo, _}}} = ssl:getopts(Socket, [foo]), - ok. - %%-------------------------------------------------------------------- -invalid_inet_get_option_not_list(doc) -> - ["Test handling of invalid type in getopts"]; - -invalid_inet_get_option_not_list(suite) -> - []; +invalid_inet_get_option_not_list() -> + [{doc,"Test handling of invalid type in getopts"}]. invalid_inet_get_option_not_list(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -997,7 +785,7 @@ invalid_inet_get_option_not_list(Config) when is_list(Config) -> {mfa, {ssl_test_lib, no_result, []}}, {options, ClientOpts}]), - test_server:format("Testcase ~p, Client ~p Server ~p ~n", + ct:print("Testcase ~p, Client ~p Server ~p ~n", [self(), Client, Server]), ssl_test_lib:check_result(Server, ok), @@ -1011,11 +799,8 @@ get_invalid_inet_option_not_list(Socket) -> ok. %%-------------------------------------------------------------------- -invalid_inet_get_option_improper_list(doc) -> - ["Test handling of invalid type in getopts"]; - -invalid_inet_get_option_improper_list(suite) -> - []; +invalid_inet_get_option_improper_list() -> + [{doc,"Test handling of invalid type in getopts"}]. invalid_inet_get_option_improper_list(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -1032,7 +817,7 @@ invalid_inet_get_option_improper_list(Config) when is_list(Config) -> {mfa, {ssl_test_lib, no_result, []}}, {options, ClientOpts}]), - test_server:format("Testcase ~p, Client ~p Server ~p ~n", + ct:print("Testcase ~p, Client ~p Server ~p ~n", [self(), Client, Server]), ssl_test_lib:check_result(Server, ok), @@ -1045,11 +830,8 @@ get_invalid_inet_option_improper_list(Socket) -> ok. %%-------------------------------------------------------------------- -invalid_inet_set_option(doc) -> - ["Test handling of invalid inet options in setopts"]; - -invalid_inet_set_option(suite) -> - []; +invalid_inet_set_option() -> + [{doc,"Test handling of invalid inet options in setopts"}]. invalid_inet_set_option(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -1066,7 +848,7 @@ invalid_inet_set_option(Config) when is_list(Config) -> {mfa, {ssl_test_lib, no_result, []}}, {options, ClientOpts}]), - test_server:format("Testcase ~p, Client ~p Server ~p ~n", + ct:print("Testcase ~p, Client ~p Server ~p ~n", [self(), Client, Server]), ssl_test_lib:check_result(Server, ok), @@ -1080,11 +862,8 @@ set_invalid_inet_option(Socket) -> {error, {eoptions, {inet_opt, {mode, foo}}}} = ssl:setopts(Socket, [{mode, foo}]), ok. %%-------------------------------------------------------------------- -invalid_inet_set_option_not_list(doc) -> - ["Test handling of invalid type in setopts"]; - -invalid_inet_set_option_not_list(suite) -> - []; +invalid_inet_set_option_not_list() -> + [{doc,"Test handling of invalid type in setopts"}]. invalid_inet_set_option_not_list(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -1101,7 +880,7 @@ invalid_inet_set_option_not_list(Config) when is_list(Config) -> {mfa, {ssl_test_lib, no_result, []}}, {options, ClientOpts}]), - test_server:format("Testcase ~p, Client ~p Server ~p ~n", + ct:print("Testcase ~p, Client ~p Server ~p ~n", [self(), Client, Server]), ssl_test_lib:check_result(Server, ok), @@ -1115,11 +894,8 @@ set_invalid_inet_option_not_list(Socket) -> ok. %%-------------------------------------------------------------------- -invalid_inet_set_option_improper_list(doc) -> - ["Test handling of invalid tye in setopts"]; - -invalid_inet_set_option_improper_list(suite) -> - []; +invalid_inet_set_option_improper_list() -> + [{doc,"Test handling of invalid tye in setopts"}]. invalid_inet_set_option_improper_list(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -1136,7 +912,7 @@ invalid_inet_set_option_improper_list(Config) when is_list(Config) -> {mfa, {ssl_test_lib, no_result, []}}, {options, ClientOpts}]), - test_server:format("Testcase ~p, Client ~p Server ~p ~n", + ct:print("Testcase ~p, Client ~p Server ~p ~n", [self(), Client, Server]), ssl_test_lib:check_result(Server, ok), @@ -1149,11 +925,8 @@ set_invalid_inet_option_improper_list(Socket) -> ok. %%-------------------------------------------------------------------- -misc_ssl_options(doc) -> - ["Test what happens when we give valid options"]; - -misc_ssl_options(suite) -> - []; +misc_ssl_options() -> + [{doc,"Test what happens when we give valid options"}]. misc_ssl_options(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -1171,17 +944,17 @@ misc_ssl_options(Config) when is_list(Config) -> Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, {from, self()}, - {mfa, {?MODULE, send_recv_result_active, []}}, + {mfa, {ssl_test_lib, send_recv_result_active, []}}, {options, TestOpts ++ ServerOpts}]), Port = ssl_test_lib:inet_port(Server), Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, {from, self()}, - {mfa, {?MODULE, send_recv_result_active, []}}, + {mfa, {ssl_test_lib, send_recv_result_active, []}}, {options, TestOpts ++ ClientOpts}]), - test_server:format("Testcase ~p, Client ~p Server ~p ~n", + ct:print("Testcase ~p, Client ~p Server ~p ~n", [self(), Client, Server]), ssl_test_lib:check_result(Server, ok, Client, ok), @@ -1189,23 +962,16 @@ misc_ssl_options(Config) when is_list(Config) -> ssl_test_lib:close(Client). %%-------------------------------------------------------------------- -versions(doc) -> - ["Test API function versions/0"]; - -versions(suite) -> - []; +versions() -> + [{doc,"Test API function versions/0"}]. versions(Config) when is_list(Config) -> [_|_] = Versions = ssl:versions(), - test_server:format("~p~n", [Versions]). + ct:print("~p~n", [Versions]). %%-------------------------------------------------------------------- -send_recv(doc) -> - [""]; - -send_recv(suite) -> - []; - +send_recv() -> + [{doc,""}]. send_recv(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -1213,17 +979,17 @@ send_recv(Config) when is_list(Config) -> Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, {from, self()}, - {mfa, {?MODULE, send_recv_result, []}}, + {mfa, {ssl_test_lib, send_recv_result, []}}, {options, [{active, false} | ServerOpts]}]), Port = ssl_test_lib:inet_port(Server), Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, {from, self()}, - {mfa, {?MODULE, send_recv_result, []}}, + {mfa, {ssl_test_lib, send_recv_result, []}}, {options, [{active, false} | ClientOpts]}]), - test_server:format("Testcase ~p, Client ~p Server ~p ~n", + ct:print("Testcase ~p, Client ~p Server ~p ~n", [self(), Client, Server]), ssl_test_lib:check_result(Server, ok, Client, ok), @@ -1232,12 +998,8 @@ send_recv(Config) when is_list(Config) -> ssl_test_lib:close(Client). %%-------------------------------------------------------------------- -send_close(doc) -> - [""]; - -send_close(suite) -> - []; - +send_close() -> + [{doc,""}]. send_close(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -1245,7 +1007,7 @@ send_close(Config) when is_list(Config) -> Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, {from, self()}, - {mfa, {?MODULE, send_recv_result, []}}, + {mfa, {ssl_test_lib, send_recv_result, []}}, {options, [{active, false} | ServerOpts]}]), Port = ssl_test_lib:inet_port(Server), {ok, TcpS} = rpc:call(ClientNode, gen_tcp, connect, @@ -1253,7 +1015,7 @@ send_close(Config) when is_list(Config) -> {ok, SslS} = rpc:call(ClientNode, ssl, connect, [TcpS,[{active, false}|ClientOpts]]), - test_server:format("Testcase ~p, Client ~p Server ~p ~n", + ct:print("Testcase ~p, Client ~p Server ~p ~n", [self(), self(), Server]), ok = ssl:send(SslS, "Hello world"), {ok,<<"Hello world">>} = ssl:recv(SslS, 11), @@ -1261,11 +1023,8 @@ send_close(Config) when is_list(Config) -> {error, _} = ssl:send(SslS, "Hello world"). %%-------------------------------------------------------------------- -close_transport_accept(doc) -> - ["Tests closing ssl socket when waiting on ssl:transport_accept/1"]; - -close_transport_accept(suite) -> - []; +close_transport_accept() -> + [{doc,"Tests closing ssl socket when waiting on ssl:transport_accept/1"}]. close_transport_accept(Config) when is_list(Config) -> ServerOpts = ?config(server_opts, Config), @@ -1275,7 +1034,7 @@ close_transport_accept(Config) when is_list(Config) -> Opts = [{active, false} | ServerOpts], {ok, ListenSocket} = rpc:call(ServerNode, ssl, listen, [Port, Opts]), spawn_link(fun() -> - test_server:sleep(?SLEEP), + ct:sleep(?SLEEP), rpc:call(ServerNode, ssl, close, [ListenSocket]) end), case rpc:call(ServerNode, ssl, transport_accept, [ListenSocket]) of @@ -1286,11 +1045,8 @@ close_transport_accept(Config) when is_list(Config) -> end. %%-------------------------------------------------------------------- -dh_params(doc) -> - ["Test to specify DH-params file in server."]; - -dh_params(suite) -> - []; +dh_params() -> + [{doc,"Test to specify DH-params file in server."}]. dh_params(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -1302,13 +1058,13 @@ dh_params(Config) when is_list(Config) -> Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, {from, self()}, - {mfa, {?MODULE, send_recv_result_active, []}}, + {mfa, {ssl_test_lib, send_recv_result_active, []}}, {options, [{dhfile, DHParamFile} | ServerOpts]}]), Port = ssl_test_lib:inet_port(Server), Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, {from, self()}, - {mfa, {?MODULE, send_recv_result_active, []}}, + {mfa, {ssl_test_lib, send_recv_result_active, []}}, {options, [{ciphers,[{dhe_rsa,aes_256_cbc,sha,ignore}]} | ClientOpts]}]), @@ -1319,11 +1075,8 @@ dh_params(Config) when is_list(Config) -> ssl_test_lib:close(Client). %%-------------------------------------------------------------------- -upgrade(doc) -> - ["Test that you can upgrade an tcp connection to an ssl connection"]; - -upgrade(suite) -> - []; +upgrade() -> + [{doc,"Test that you can upgrade an tcp connection to an ssl connection"}]. upgrade(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -1347,7 +1100,7 @@ upgrade(Config) when is_list(Config) -> {tcp_options, TcpOpts}, {ssl_options, ClientOpts}]), - test_server:format("Testcase ~p, Client ~p Server ~p ~n", + ct:print("Testcase ~p, Client ~p Server ~p ~n", [self(), Client, Server]), ssl_test_lib:check_result(Server, ok, Client, ok), @@ -1371,11 +1124,8 @@ upgrade_result(Socket) -> end. %%-------------------------------------------------------------------- -upgrade_with_timeout(doc) -> - ["Test ssl_accept/3"]; - -upgrade_with_timeout(suite) -> - []; +upgrade_with_timeout() -> + [{doc,"Test ssl_accept/3"}]. upgrade_with_timeout(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -1400,7 +1150,7 @@ upgrade_with_timeout(Config) when is_list(Config) -> {tcp_options, TcpOpts}, {ssl_options, ClientOpts}]), - test_server:format("Testcase ~p, Client ~p Server ~p ~n", + ct:print("Testcase ~p, Client ~p Server ~p ~n", [self(), Client, Server]), ssl_test_lib:check_result(Server, ok, Client, ok), @@ -1409,11 +1159,8 @@ upgrade_with_timeout(Config) when is_list(Config) -> ssl_test_lib:close(Client). %%-------------------------------------------------------------------- -tcp_connect(doc) -> - ["Test what happens when a tcp tries to connect, i,e. a bad (ssl) packet is sent first"]; - -tcp_connect(suite) -> - []; +tcp_connect() -> + [{doc,"Test what happens when a tcp tries to connect, i,e. a bad (ssl) packet is sent first"}]. tcp_connect(Config) when is_list(Config) -> ServerOpts = ?config(server_opts, Config), @@ -1429,22 +1176,19 @@ tcp_connect(Config) when is_list(Config) -> Port = ssl_test_lib:inet_port(Server), {ok, Socket} = gen_tcp:connect(Hostname, Port, [binary, {packet, 0}]), - test_server:format("Testcase ~p connected to Server ~p ~n", [self(), Server]), + ct:print("Testcase ~p connected to Server ~p ~n", [self(), Server]), gen_tcp:send(Socket, "<SOME GARBLED NON SSL MESSAGE>"), receive {tcp_closed, Socket} -> receive {Server, {error, Error}} -> - test_server:format("Error ~p", [Error]) + ct:print("Error ~p", [Error]) end end. - -tcp_connect_big(doc) -> - ["Test what happens when a tcp tries to connect, i,e. a bad big (ssl) packet is sent first"]; - -tcp_connect_big(suite) -> - []; +%%-------------------------------------------------------------------- +tcp_connect_big() -> + [{doc,"Test what happens when a tcp tries to connect, i,e. a bad big (ssl) packet is sent first"}]. tcp_connect_big(Config) when is_list(Config) -> ServerOpts = ?config(server_opts, Config), @@ -1460,7 +1204,7 @@ tcp_connect_big(Config) when is_list(Config) -> Port = ssl_test_lib:inet_port(Server), {ok, Socket} = gen_tcp:connect(Hostname, Port, [binary, {packet, 0}]), - test_server:format("Testcase ~p connected to Server ~p ~n", [self(), Server]), + ct:print("Testcase ~p connected to Server ~p ~n", [self(), Server]), Rand = crypto:rand_bytes(?MAX_CIPHER_TEXT_LENGTH+1), gen_tcp:send(Socket, <<?BYTE(0), @@ -1470,24 +1214,16 @@ tcp_connect_big(Config) when is_list(Config) -> {tcp_closed, Socket} -> receive {Server, {error, timeout}} -> - test_server:fail("hangs"); + ct:fail("hangs"); {Server, {error, Error}} -> - test_server:format("Error ~p", [Error]) + ct:print("Error ~p", [Error]) end end. -dummy(_Socket) -> - %% Should not happen as the ssl connection will not be established - %% due to fatal handshake failiure - exit(kill). - %%-------------------------------------------------------------------- ipv6() -> - [{require, ipv6_hosts}]. -ipv6(doc) -> - ["Test ipv6."]; -ipv6(suite) -> - []; + [{require, ipv6_hosts}, + {doc,"Test ipv6."}]. ipv6(Config) when is_list(Config) -> {ok, Hostname0} = inet:gethostname(), @@ -1499,18 +1235,18 @@ ipv6(Config) when is_list(Config) -> ssl_test_lib:run_where(Config, ipv6), Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, {from, self()}, - {mfa, {?MODULE, send_recv_result, []}}, + {mfa, {ssl_test_lib, send_recv_result, []}}, {options, [inet6, {active, false} | ServerOpts]}]), Port = ssl_test_lib:inet_port(Server), Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, {from, self()}, - {mfa, {?MODULE, send_recv_result, []}}, + {mfa, {ssl_test_lib, send_recv_result, []}}, {options, [inet6, {active, false} | ClientOpts]}]), - test_server:format("Testcase ~p, Client ~p Server ~p ~n", + ct:print("Testcase ~p, Client ~p Server ~p ~n", [self(), Client, Server]), ssl_test_lib:check_result(Server, ok, Client, ok), @@ -1523,12 +1259,8 @@ ipv6(Config) when is_list(Config) -> %%-------------------------------------------------------------------- -ekeyfile(doc) -> - ["Test what happens with an invalid key file"]; - -ekeyfile(suite) -> - []; - +ekeyfile() -> + [{doc,"Test what happens with an invalid key file"}]. ekeyfile(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), BadOpts = ?config(server_bad_key, Config), @@ -1551,11 +1283,8 @@ ekeyfile(Config) when is_list(Config) -> %%-------------------------------------------------------------------- -ecertfile(doc) -> - ["Test what happens with an invalid cert file"]; - -ecertfile(suite) -> - []; +ecertfile() -> + [{doc,"Test what happens with an invalid cert file"}]. ecertfile(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -1580,11 +1309,8 @@ ecertfile(Config) when is_list(Config) -> %%-------------------------------------------------------------------- -ecacertfile(doc) -> - ["Test what happens with an invalid cacert file"]; - -ecacertfile(suite) -> - []; +ecacertfile() -> + [{doc,"Test what happens with an invalid cacert file"}]. ecacertfile(Config) when is_list(Config) -> ClientOpts = [{reuseaddr, true}|?config(client_opts, Config)], @@ -1632,12 +1358,9 @@ ecacertfile(Config) when is_list(Config) -> %%-------------------------------------------------------------------- -eoptions(doc) -> - ["Test what happens when we give invalid options"]; +eoptions() -> + [{doc,"Test what happens when we give invalid options"}]. -eoptions(suite) -> - []; - eoptions(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -1694,12 +1417,8 @@ eoptions(Config) when is_list(Config) -> ok. %%-------------------------------------------------------------------- -shutdown(doc) -> - [""]; - -shutdown(suite) -> - []; - +shutdown() -> + [{doc,"Test API function ssl:shutdown/2"}]. shutdown(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -1724,25 +1443,9 @@ shutdown(Config) when is_list(Config) -> ssl_test_lib:close(Server), ssl_test_lib:close(Client). -shutdown_result(Socket, server) -> - ssl:send(Socket, "Hej"), - ssl:shutdown(Socket, write), - {ok, "Hej hopp"} = ssl:recv(Socket, 8), - ok; - -shutdown_result(Socket, client) -> - {ok, "Hej"} = ssl:recv(Socket, 3), - ssl:send(Socket, "Hej hopp"), - ssl:shutdown(Socket, write), - ok. - %%-------------------------------------------------------------------- -shutdown_write(doc) -> - [""]; - -shutdown_write(suite) -> - []; - +shutdown_write() -> + [{doc,"Test API function ssl:shutdown/2 with option write."}]. shutdown_write(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -1759,20 +1462,10 @@ shutdown_write(Config) when is_list(Config) -> {options, [{active, false} | ClientOpts]}]), ssl_test_lib:check_result(Server, ok, Client, {error, closed}). - -shutdown_write_result(Socket, server) -> - test_server:sleep(?SLEEP), - ssl:shutdown(Socket, write); -shutdown_write_result(Socket, client) -> - ssl:recv(Socket, 0). %%-------------------------------------------------------------------- -shutdown_both(doc) -> - [""]; - -shutdown_both(suite) -> - []; - +shutdown_both() -> + [{doc,"Test API function ssl:shutdown/2 with option both."}]. shutdown_both(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -1790,19 +1483,9 @@ shutdown_both(Config) when is_list(Config) -> ssl_test_lib:check_result(Server, ok, Client, {error, closed}). -shutdown_both_result(Socket, server) -> - test_server:sleep(?SLEEP), - ssl:shutdown(Socket, read_write); -shutdown_both_result(Socket, client) -> - ssl:recv(Socket, 0). - %%-------------------------------------------------------------------- -shutdown_error(doc) -> - [""]; - -shutdown_error(suite) -> - []; - +shutdown_error() -> + [{doc,"Test ssl:shutdown/2 error handling"}]. shutdown_error(Config) when is_list(Config) -> ServerOpts = ?config(server_opts, Config), Port = ssl_test_lib:inet_port(node()), @@ -1812,141 +1495,60 @@ shutdown_error(Config) when is_list(Config) -> {error, closed} = ssl:shutdown(Listen, read_write). %%------------------------------------------------------------------- -ciphers_rsa_signed_certs(doc) -> - ["Test all rsa ssl cipher suites in highest support ssl/tls version"]; +ciphers_rsa_signed_certs() -> + [{doc,"Test all rsa ssl cipher suites in highest support ssl/tls version"}]. -ciphers_rsa_signed_certs(suite) -> - []; - ciphers_rsa_signed_certs(Config) when is_list(Config) -> Version = ssl_record:protocol_version(ssl_record:highest_protocol_version([])), Ciphers = ssl_test_lib:rsa_suites(), - test_server:format("~p erlang cipher suites ~p~n", [Version, Ciphers]), + ct:print("~p erlang cipher suites ~p~n", [Version, Ciphers]), run_suites(Ciphers, Version, Config, rsa). - -ciphers_rsa_signed_certs_openssl_names(doc) -> - ["Test all rsa ssl cipher suites in highest support ssl/tls version"]; +%%------------------------------------------------------------------- +ciphers_rsa_signed_certs_openssl_names() -> + [{doc,"Test all rsa ssl cipher suites in highest support ssl/tls version"}]. -ciphers_rsa_signed_certs_openssl_names(suite) -> - []; - ciphers_rsa_signed_certs_openssl_names(Config) when is_list(Config) -> Version = ssl_record:protocol_version(ssl_record:highest_protocol_version([])), Ciphers = ssl_test_lib:openssl_rsa_suites(), - test_server:format("tls1 openssl cipher suites ~p~n", [Ciphers]), + ct:print("tls1 openssl cipher suites ~p~n", [Ciphers]), run_suites(Ciphers, Version, Config, rsa). - -ciphers_dsa_signed_certs(doc) -> - ["Test all dsa ssl cipher suites in highest support ssl/tls version"]; +%%------------------------------------------------------------------- +ciphers_dsa_signed_certs() -> + [{doc,"Test all dsa ssl cipher suites in highest support ssl/tls version"}]. -ciphers_dsa_signed_certs(suite) -> - []; - ciphers_dsa_signed_certs(Config) when is_list(Config) -> Version = ssl_record:protocol_version(ssl_record:highest_protocol_version([])), Ciphers = ssl_test_lib:dsa_suites(), - test_server:format("~p erlang cipher suites ~p~n", [Version, Ciphers]), + ct:print("~p erlang cipher suites ~p~n", [Version, Ciphers]), run_suites(Ciphers, Version, Config, dsa). - -ciphers_dsa_signed_certs_openssl_names(doc) -> - ["Test all dsa ssl cipher suites in highest support ssl/tls version"]; +%%------------------------------------------------------------------- +ciphers_dsa_signed_certs_openssl_names() -> + [{doc,"Test all dsa ssl cipher suites in highest support ssl/tls version"}]. -ciphers_dsa_signed_certs_openssl_names(suite) -> - []; - ciphers_dsa_signed_certs_openssl_names(Config) when is_list(Config) -> Version = ssl_record:protocol_version(ssl_record:highest_protocol_version([])), Ciphers = ssl_test_lib:openssl_dsa_suites(), - test_server:format("tls1 openssl cipher suites ~p~n", [Ciphers]), + ct:print("tls1 openssl cipher suites ~p~n", [Ciphers]), run_suites(Ciphers, Version, Config, dsa). - -anonymous_cipher_suites(doc)-> - ["Test the anonymous ciphersuites"]; -anonymous_cipher_suites(suite) -> - []; +%%------------------------------------------------------------------- +anonymous_cipher_suites()-> + [{doc,"Test the anonymous ciphersuites"}]. anonymous_cipher_suites(Config) when is_list(Config) -> Version = ssl_record:protocol_version(ssl_record:highest_protocol_version([])), Ciphers = ssl_test_lib:anonymous_suites(), run_suites(Ciphers, Version, Config, anonymous). -run_suites(Ciphers, Version, Config, Type) -> - {ClientOpts, ServerOpts} = - case Type of - rsa -> - {?config(client_opts, Config), - ?config(server_opts, Config)}; - dsa -> - {?config(client_opts, Config), - ?config(server_dsa_opts, Config)}; - anonymous -> - %% No certs in opts! - {?config(client_opts, Config), - ?config(server_anon, Config)} - end, - - Result = lists:map(fun(Cipher) -> - cipher(Cipher, Version, Config, ClientOpts, ServerOpts) end, - Ciphers), - case lists:flatten(Result) of - [] -> - ok; - Error -> - test_server:format("Cipher suite errors: ~p~n", [Error]), - test_server:fail(cipher_suite_failed_see_test_case_log) - end. - -erlang_cipher_suite(Suite) when is_list(Suite)-> - ssl:suite_definition(ssl_cipher:openssl_suite(Suite)); -erlang_cipher_suite(Suite) -> - Suite. - -cipher(CipherSuite, Version, Config, ClientOpts, ServerOpts) -> - %% process_flag(trap_exit, true), - test_server:format("Testing CipherSuite ~p~n", [CipherSuite]), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - - ErlangCipherSuite = erlang_cipher_suite(CipherSuite), - - ConnectionInfo = {ok, {Version, ErlangCipherSuite}}, - - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, {ssl_test_lib, cipher_result, [ConnectionInfo]}}, - {options, ServerOpts}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {ssl_test_lib, cipher_result, [ConnectionInfo]}}, - {options, - [{ciphers,[CipherSuite]} | - ClientOpts]}]), - - Result = ssl_test_lib:wait_for_result(Server, ok, Client, ok), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client), - - case Result of - ok -> - []; - Error -> - [{ErlangCipherSuite, Error}] - end. - %%-------------------------------------------------------------------- -default_reject_anonymous(doc)-> - ["Test that by default anonymous cipher suites are rejected "]; -default_reject_anonymous(suite) -> - []; +default_reject_anonymous()-> + [{doc,"Test that by default anonymous cipher suites are rejected "}]. default_reject_anonymous(Config) when is_list(Config) -> {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), ClientOpts = ?config(client_opts, Config), @@ -1969,12 +1571,8 @@ default_reject_anonymous(Config) when is_list(Config) -> Client, {error, "insufficient security"}). %%-------------------------------------------------------------------- -reuse_session(doc) -> - ["Test reuse of sessions (short handshake)"]; - -reuse_session(suite) -> - []; - +reuse_session() -> + [{doc,"Test reuse of sessions (short handshake)"}]. reuse_session(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -2000,7 +1598,7 @@ reuse_session(Config) when is_list(Config) -> Server ! {listen, {mfa, {ssl_test_lib, no_result, []}}}, %% Make sure session is registered - test_server:sleep(?SLEEP), + ct:sleep(?SLEEP), Client1 = ssl_test_lib:start_client([{node, ClientNode}, @@ -2011,9 +1609,9 @@ reuse_session(Config) when is_list(Config) -> {Client1, SessionInfo} -> ok; {Client1, Other} -> - test_server:format("Expected: ~p, Unexpected: ~p~n", + ct:print("Expected: ~p, Unexpected: ~p~n", [SessionInfo, Other]), - test_server:fail(session_not_reused) + ct:fail(session_not_reused) end, Server ! {listen, {mfa, {ssl_test_lib, no_result, []}}}, @@ -2026,7 +1624,7 @@ reuse_session(Config) when is_list(Config) -> | ClientOpts]}]), receive {Client2, SessionInfo} -> - test_server:fail( + ct:fail( session_reused_when_session_reuse_disabled_by_client); {Client2, _} -> ok @@ -2056,7 +1654,7 @@ reuse_session(Config) when is_list(Config) -> Server1 ! {listen, {mfa, {ssl_test_lib, no_result, []}}}, %% Make sure session is registered - test_server:sleep(?SLEEP), + ct:sleep(?SLEEP), Client4 = ssl_test_lib:start_client([{node, ClientNode}, @@ -2066,10 +1664,10 @@ reuse_session(Config) when is_list(Config) -> receive {Client4, SessionInfo1} -> - test_server:fail( + ct:fail( session_reused_when_session_reuse_disabled_by_server); {Client4, _Other} -> - test_server:format("OTHER: ~p ~n", [_Other]), + ct:print("OTHER: ~p ~n", [_Other]), ok end, @@ -2081,12 +1679,8 @@ reuse_session(Config) when is_list(Config) -> ssl_test_lib:close(Client4). %%-------------------------------------------------------------------- -reuse_session_expired(doc) -> - ["Test sessions is not reused when it has expired"]; - -reuse_session_expired(suite) -> - []; - +reuse_session_expired() -> + [{doc,"Test sessions is not reused when it has expired"}]. reuse_session_expired(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -2112,7 +1706,7 @@ reuse_session_expired(Config) when is_list(Config) -> Server ! {listen, {mfa, {ssl_test_lib, no_result, []}}}, %% Make sure session is registered - test_server:sleep(?SLEEP), + ct:sleep(?SLEEP), Client1 = ssl_test_lib:start_client([{node, ClientNode}, @@ -2123,15 +1717,15 @@ reuse_session_expired(Config) when is_list(Config) -> {Client1, SessionInfo} -> ok; {Client1, Other} -> - test_server:format("Expected: ~p, Unexpected: ~p~n", + ct:print("Expected: ~p, Unexpected: ~p~n", [SessionInfo, Other]), - test_server:fail(session_not_reused) + ct:fail(session_not_reused) end, Server ! listen, %% Make sure session is unregistered due to expiration - test_server:sleep((?EXPIRE+1)), + ct:sleep((?EXPIRE+1)), [{session_id, Id} |_] = SessionInfo, make_sure_expired(Hostname, Port, Id), @@ -2143,7 +1737,7 @@ reuse_session_expired(Config) when is_list(Config) -> {from, self()}, {options, ClientOpts}]), receive {Client2, SessionInfo} -> - test_server:fail(session_reused_when_session_expired); + ct:fail(session_reused_when_session_expired); {Client2, _} -> ok end, @@ -2165,17 +1759,13 @@ make_sure_expired(Host, Port, Id) -> #session{is_resumable = false} -> ok; _ -> - test_server:sleep(?SLEEP), + ct:sleep(?SLEEP), make_sure_expired(Host, Port, Id) end. %%-------------------------------------------------------------------- -server_does_not_want_to_reuse_session(doc) -> - ["Test reuse of sessions (short handshake)"]; - -server_does_not_want_to_reuse_session(suite) -> - []; - +server_does_not_want_to_reuse_session() -> + [{doc,"Test reuse of sessions (short handshake)"}]. server_does_not_want_to_reuse_session(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -2204,7 +1794,7 @@ server_does_not_want_to_reuse_session(Config) when is_list(Config) -> Server ! {listen, {mfa, {ssl_test_lib, no_result, []}}}, %% Make sure session is registered - test_server:sleep(?SLEEP), + ct:sleep(?SLEEP), ssl_test_lib:close(Client0), Client1 = @@ -2214,7 +1804,7 @@ server_does_not_want_to_reuse_session(Config) when is_list(Config) -> {from, self()}, {options, ClientOpts}]), receive {Client1, SessionInfo} -> - test_server:fail(session_reused_when_server_does_not_want_to); + ct:fail(session_reused_when_server_does_not_want_to); {Client1, _Other} -> ok end, @@ -2223,512 +1813,55 @@ server_does_not_want_to_reuse_session(Config) when is_list(Config) -> ssl_test_lib:close(Client1). %%-------------------------------------------------------------------- - -server_verify_peer_passive(doc) -> - ["Test server option verify_peer"]; - -server_verify_peer_passive(suite) -> - []; - -server_verify_peer_passive(Config) when is_list(Config) -> - ClientOpts = ?config(client_verification_opts, Config), - ServerOpts = ?config(server_verification_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send_recv_result, []}}, - {options, [{active, false}, {verify, verify_peer} - | ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, send_recv_result, []}}, - {options, [{active, false} | ClientOpts]}]), - - ssl_test_lib:check_result(Server, ok, Client, ok), - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). - -%%-------------------------------------------------------------------- - -server_verify_peer_active(doc) -> - ["Test server option verify_peer"]; - -server_verify_peer_active(suite) -> - []; - -server_verify_peer_active(Config) when is_list(Config) -> - ClientOpts = ?config(client_verification_opts, Config), - ServerOpts = ?config(server_verification_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send_recv_result_active, []}}, - {options, [{active, true}, {verify, verify_peer} - | ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, send_recv_result_active, []}}, - {options, [{active, true} | ClientOpts]}]), - - ssl_test_lib:check_result(Server, ok, Client, ok), - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). - -%%-------------------------------------------------------------------- -server_verify_peer_active_once(doc) -> - ["Test server option verify_peer"]; - -server_verify_peer_active_once(suite) -> - []; - -server_verify_peer_active_once(Config) when is_list(Config) -> - ClientOpts = ?config(client_verification_opts, Config), - ServerOpts = ?config(server_verification_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send_recv_result_active_once, []}}, - {options, [{active, once}, {verify, verify_peer} - | ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, send_recv_result_active_once, []}}, - {options, [{active, once} | ClientOpts]}]), - - ssl_test_lib:check_result(Server, ok, Client, ok), - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). - -%%-------------------------------------------------------------------- - -server_verify_none_passive(doc) -> - ["Test server option verify_none"]; - -server_verify_none_passive(suite) -> - []; - -server_verify_none_passive(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send_recv_result, []}}, - {options, [{active, false}, {verify, verify_none} - | ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, send_recv_result, []}}, - {options, [{active, false} | ClientOpts]}]), - - ssl_test_lib:check_result(Server, ok, Client, ok), - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). - -%%-------------------------------------------------------------------- - -server_verify_none_active(doc) -> - ["Test server option verify_none"]; - -server_verify_none_active(suite) -> - []; - -server_verify_none_active(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send_recv_result_active, []}}, - {options, [{active, true}, {verify, verify_none} | - ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, send_recv_result_active, []}}, - {options, [{active, true} | ClientOpts]}]), - - ssl_test_lib:check_result(Server, ok, Client, ok), - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). - -%%-------------------------------------------------------------------- -server_verify_none_active_once(doc) -> - ["Test server option verify_none"]; - -server_verify_none_active_once(suite) -> - []; - -server_verify_none_active_once(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send_recv_result_active_once, []}}, - {options, [{active, once}, {verify, verify_none} - | ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, send_recv_result_active_once, []}}, - {options, [{active, once} | ClientOpts]}]), - - ssl_test_lib:check_result(Server, ok, Client, ok), - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). - -%%-------------------------------------------------------------------- - -server_verify_client_once_passive(doc) -> - ["Test server option verify_client_once"]; - -server_verify_client_once_passive(suite) -> - []; - -server_verify_client_once_passive(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_verification_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send_recv_result, []}}, - {options, [{active, false}, {verify, verify_peer}, - {verify_client_once, true} - | ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - Client0 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, send_recv_result, []}}, - {options, [{active, false} | ClientOpts]}]), - - ssl_test_lib:check_result(Server, ok, Client0, ok), - Server ! {listen, {mfa, {ssl_test_lib, no_result, []}}}, - ssl_test_lib:close(Client0), - Client1 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, result_ok, []}}, - {options, [{active, false} | ClientOpts]}]), - - ssl_test_lib:check_result(Client1, ok), - ssl_test_lib:close(Server), - ssl_test_lib:close(Client1). - -%%-------------------------------------------------------------------- - -server_verify_client_once_active(doc) -> - ["Test server option verify_client_once"]; - -server_verify_client_once_active(suite) -> - []; - -server_verify_client_once_active(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_verification_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send_recv_result_active, []}}, - {options, [{active, true}, {verify, verify_peer}, - {verify_client_once, true} - | ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - Client0 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, send_recv_result_active, []}}, - {options, [{active, true} | ClientOpts]}]), - - ssl_test_lib:check_result(Server, ok, Client0, ok), - Server ! {listen, {mfa, {ssl_test_lib, no_result, []}}}, - ssl_test_lib:close(Client0), - Client1 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, result_ok, []}}, - {options, [{active, true} | ClientOpts]}]), - - ssl_test_lib:check_result(Client1, ok), - ssl_test_lib:close(Server), - ssl_test_lib:close(Client1). - -%%-------------------------------------------------------------------- - -server_verify_client_once_active_once(doc) -> - ["Test server option verify_client_once"]; - -server_verify_client_once_active_once(suite) -> - []; - -server_verify_client_once_active_once(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_verification_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send_recv_result_active_once, []}}, - {options, [{active, once}, {verify, verify_peer}, - {verify_client_once, true} - | ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - Client0 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, send_recv_result_active_once, []}}, - {options, [{active, once} | ClientOpts]}]), - - ssl_test_lib:check_result(Server, ok, Client0, ok), - Server ! {listen, {mfa, {ssl_test_lib, no_result, []}}}, - ssl_test_lib:close(Client0), - Client1 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, result_ok, []}}, - {options, [{active, once} | ClientOpts]}]), - - ssl_test_lib:check_result(Client1, ok), - ssl_test_lib:close(Server), - ssl_test_lib:close(Client1). - -%%-------------------------------------------------------------------- - -server_verify_no_cacerts(doc) -> - ["Test server must have cacerts if it wants to verify client"]; - -server_verify_no_cacerts(suite) -> - []; -server_verify_no_cacerts(Config) when is_list(Config) -> - ServerOpts = ?config(server_opts, Config), - {_, ServerNode, _} = ssl_test_lib:run_where(Config), - Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0}, - {from, self()}, - {options, [{verify, verify_peer} - | ServerOpts]}]), - - ssl_test_lib:check_result(Server, {error, {eoptions, {cacertfile, ""}}}). - -%%-------------------------------------------------------------------- - -server_require_peer_cert_ok(doc) -> - ["Test server option fail_if_no_peer_cert when peer sends cert"]; - -server_require_peer_cert_ok(suite) -> - []; - -server_require_peer_cert_ok(Config) when is_list(Config) -> - ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true} - | ?config(server_verification_opts, Config)], - ClientOpts = ?config(client_verification_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send_recv_result, []}}, - {options, [{active, false} | ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, send_recv_result, []}}, - {options, [{active, false} | ClientOpts]}]), - - ssl_test_lib:check_result(Server, ok, Client, ok), - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). - -%%-------------------------------------------------------------------- - -server_require_peer_cert_fail(doc) -> - ["Test server option fail_if_no_peer_cert when peer doesn't send cert"]; - -server_require_peer_cert_fail(suite) -> - []; - -server_require_peer_cert_fail(Config) when is_list(Config) -> - ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true} - | ?config(server_verification_opts, Config)], - BadClientOpts = ?config(client_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - - Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0}, - {from, self()}, - {options, [{active, false} | ServerOpts]}]), - - Port = ssl_test_lib:inet_port(Server), - - Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {options, [{active, false} | BadClientOpts]}]), - - ssl_test_lib:check_result(Server, {error, esslaccept}, - Client, {error, esslconnect}). - -%%-------------------------------------------------------------------- - -client_verify_none_passive(doc) -> - ["Test client option verify_none"]; - -client_verify_none_passive(suite) -> - []; - -client_verify_none_passive(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send_recv_result, []}}, - {options, [{active, false} - | ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, send_recv_result, []}}, - {options, [{active, false}, - {verify, verify_none} - | ClientOpts]}]), - - ssl_test_lib:check_result(Server, ok, Client, ok), - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). - -%%-------------------------------------------------------------------- - -client_verify_none_active(doc) -> - ["Test client option verify_none"]; - -client_verify_none_active(suite) -> - []; - -client_verify_none_active(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, - send_recv_result_active, []}}, - {options, [{active, true} - | ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, - send_recv_result_active, []}}, - {options, [{active, true}, - {verify, verify_none} - | ClientOpts]}]), - - ssl_test_lib:check_result(Server, ok, Client, ok), - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). - -%%-------------------------------------------------------------------- -client_verify_none_active_once(doc) -> - ["Test client option verify_none"]; - -client_verify_none_active_once(suite) -> - []; - -client_verify_none_active_once(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send_recv_result_active_once, []}}, - {options, [{active, once} | ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, - send_recv_result_active_once, - []}}, - {options, [{active, once}, - {verify, verify_none} - | ClientOpts]}]), - - ssl_test_lib:check_result(Server, ok, Client, ok), - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). - -%%-------------------------------------------------------------------- -client_renegotiate(doc) -> - ["Test ssl:renegotiate/1 on client."]; - -client_renegotiate(suite) -> - []; - +client_renegotiate() -> + [{doc,"Test ssl:renegotiate/1 on client."}]. client_renegotiate(Config) when is_list(Config) -> - ServerOpts = ?config(server_opts, Config), - ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + ClientOpts = ?config(client_opts, Config), {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - + Data = "From erlang to erlang", - Server = - ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + Server = + ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, {from, self()}, {mfa, {?MODULE, erlang_ssl_receive, [Data]}}, {options, ServerOpts}]), Port = ssl_test_lib:inet_port(Server), - + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, + {from, self()}, + {mfa, {?MODULE, renegotiate, [Data]}}, {options, [{reuse_sessions, false} | ClientOpts]}]), - ssl_test_lib:check_result(Client, ok, Server, ok), + ssl_test_lib:check_result(Client, ok, Server, ok), ssl_test_lib:close(Server), ssl_test_lib:close(Client). %%-------------------------------------------------------------------- -server_renegotiate(doc) -> - ["Test ssl:renegotiate/1 on server."]; - -server_renegotiate(suite) -> - []; - +server_renegotiate() -> + [{doc,"Test ssl:renegotiate/1 on server."}]. server_renegotiate(Config) when is_list(Config) -> - ServerOpts = ?config(server_opts, Config), - ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + ClientOpts = ?config(client_opts, Config), {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - + Data = "From erlang to erlang", Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, {from, self()}, - {mfa, {?MODULE, + {mfa, {?MODULE, renegotiate, [Data]}}, {options, ServerOpts}]), Port = ssl_test_lib:inet_port(Server), - + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, - {from, self()}, + {from, self()}, {mfa, {?MODULE, erlang_ssl_receive, [Data]}}, {options, [{reuse_sessions, false} | ClientOpts]}]), @@ -2737,805 +1870,133 @@ server_renegotiate(Config) when is_list(Config) -> ssl_test_lib:close(Client). %%-------------------------------------------------------------------- -client_renegotiate_reused_session(doc) -> - ["Test ssl:renegotiate/1 on client when the ssl session will be reused."]; - -client_renegotiate_reused_session(suite) -> - []; - +client_renegotiate_reused_session() -> + [{doc,"Test ssl:renegotiate/1 on client when the ssl session will be reused."}]. client_renegotiate_reused_session(Config) when is_list(Config) -> - ServerOpts = ?config(server_opts, Config), - ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + ClientOpts = ?config(client_opts, Config), {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - + Data = "From erlang to erlang", - Server = - ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + Server = + ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, {from, self()}, {mfa, {?MODULE, erlang_ssl_receive, [Data]}}, {options, ServerOpts}]), Port = ssl_test_lib:inet_port(Server), - + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, + {from, self()}, + {mfa, {?MODULE, renegotiate_reuse_session, [Data]}}, {options, [{reuse_sessions, true} | ClientOpts]}]), - ssl_test_lib:check_result(Client, ok, Server, ok), + ssl_test_lib:check_result(Client, ok, Server, ok), ssl_test_lib:close(Server), ssl_test_lib:close(Client). %%-------------------------------------------------------------------- -server_renegotiate_reused_session(doc) -> - ["Test ssl:renegotiate/1 on server when the ssl session will be reused."]; - -server_renegotiate_reused_session(suite) -> - []; - +server_renegotiate_reused_session() -> + [{doc,"Test ssl:renegotiate/1 on server when the ssl session will be reused."}]. server_renegotiate_reused_session(Config) when is_list(Config) -> - ServerOpts = ?config(server_opts, Config), - ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + ClientOpts = ?config(client_opts, Config), {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), Data = "From erlang to erlang", - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, renegotiate_reuse_session, [Data]}}, {options, ServerOpts}]), Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, - {from, self()}, + {from, self()}, {mfa, {?MODULE, erlang_ssl_receive, [Data]}}, {options, [{reuse_sessions, true} | ClientOpts]}]), - + ssl_test_lib:check_result(Server, ok, Client, ok), ssl_test_lib:close(Server), ssl_test_lib:close(Client). %%-------------------------------------------------------------------- -client_no_wrap_sequence_number(doc) -> - ["Test that erlang client will renegotiate session when", +client_no_wrap_sequence_number() -> + [{doc,"Test that erlang client will renegotiate session when", "max sequence number celing is about to be reached. Although" - "in the testcase we use the test option renegotiate_at" - " to lower treashold substantially."]; - -client_no_wrap_sequence_number(suite) -> - []; + "in the testcase we use the test option renegotiate_at" + " to lower treashold substantially."}]. client_no_wrap_sequence_number(Config) when is_list(Config) -> - ServerOpts = ?config(server_opts, Config), - ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + ClientOpts = ?config(client_opts, Config), {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - + ErlData = "From erlang to erlang", N = 10, - Server = - ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + Server = + ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, {from, self()}, {mfa, {ssl_test_lib, no_result, []}}, {options, ServerOpts}]), Port = ssl_test_lib:inet_port(Server), - + Version = ssl_record:highest_protocol_version(ssl_record:supported_protocol_versions()), - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, - {from, self()}, - {mfa, {ssl_test_lib, + {from, self()}, + {mfa, {ssl_test_lib, trigger_renegotiate, [[ErlData, treashold(N, Version)]]}}, {options, [{reuse_sessions, false}, {renegotiate_at, N} | ClientOpts]}]), - - ssl_test_lib:check_result(Client, ok), + + ssl_test_lib:check_result(Client, ok), ssl_test_lib:close(Server), ssl_test_lib:close(Client). - %% First two clauses handles 1/n-1 splitting countermeasure Rizzo/Duong-Beast -treashold(N, {3,0}) -> - (N div 2) + 1; -treashold(N, {3,1}) -> - (N div 2) + 1; -treashold(N, _) -> - N + 1. - %%-------------------------------------------------------------------- -server_no_wrap_sequence_number(doc) -> - ["Test that erlang server will renegotiate session when", +server_no_wrap_sequence_number() -> + [{doc, "Test that erlang server will renegotiate session when", "max sequence number celing is about to be reached. Although" - "in the testcase we use the test option renegotiate_at" - " to lower treashold substantially."]; - -server_no_wrap_sequence_number(suite) -> - []; + "in the testcase we use the test option renegotiate_at" + " to lower treashold substantially."}]. server_no_wrap_sequence_number(Config) when is_list(Config) -> - ServerOpts = ?config(server_opts, Config), - ClientOpts = ?config(client_opts, Config), - - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - - Data = "From erlang to erlang", - N = 10, - - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, {ssl_test_lib, - trigger_renegotiate, [[Data, N+2]]}}, - {options, [{renegotiate_at, N} | ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {ssl_test_lib, no_result, []}}, - {options, [{reuse_sessions, false} | ClientOpts]}]), - - ssl_test_lib:check_result(Server, ok), - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). -%%-------------------------------------------------------------------- -extended_key_usage_verify_peer(doc) -> - ["Test cert that has a critical extended_key_usage extension in verify_peer mode"]; - -extended_key_usage_verify_peer(suite) -> - []; - -extended_key_usage_verify_peer(Config) when is_list(Config) -> - ClientOpts = ?config(client_verification_opts, Config), - ServerOpts = ?config(server_verification_opts, Config), - PrivDir = ?config(priv_dir, Config), - - KeyFile = filename:join(PrivDir, "otpCA/private/key.pem"), - [KeyEntry] = ssl_test_lib:pem_to_der(KeyFile), - Key = ssl_test_lib:public_key(public_key:pem_entry_decode(KeyEntry)), - - ServerCertFile = proplists:get_value(certfile, ServerOpts), - NewServerCertFile = filename:join(PrivDir, "server/new_cert.pem"), - [{'Certificate', ServerDerCert, _}] = ssl_test_lib:pem_to_der(ServerCertFile), - ServerOTPCert = public_key:pkix_decode_cert(ServerDerCert, otp), - ServerExtKeyUsageExt = {'Extension', ?'id-ce-extKeyUsage', true, [?'id-kp-serverAuth']}, - ServerOTPTbsCert = ServerOTPCert#'OTPCertificate'.tbsCertificate, - ServerExtensions = ServerOTPTbsCert#'OTPTBSCertificate'.extensions, - NewServerOTPTbsCert = ServerOTPTbsCert#'OTPTBSCertificate'{extensions = - [ServerExtKeyUsageExt | - ServerExtensions]}, - NewServerDerCert = public_key:pkix_sign(NewServerOTPTbsCert, Key), - ssl_test_lib:der_to_pem(NewServerCertFile, [{'Certificate', NewServerDerCert, not_encrypted}]), - NewServerOpts = [{certfile, NewServerCertFile} | proplists:delete(certfile, ServerOpts)], - - ClientCertFile = proplists:get_value(certfile, ClientOpts), - NewClientCertFile = filename:join(PrivDir, "client/new_cert.pem"), - [{'Certificate', ClientDerCert, _}] = ssl_test_lib:pem_to_der(ClientCertFile), - ClientOTPCert = public_key:pkix_decode_cert(ClientDerCert, otp), - ClientExtKeyUsageExt = {'Extension', ?'id-ce-extKeyUsage', true, [?'id-kp-clientAuth']}, - ClientOTPTbsCert = ClientOTPCert#'OTPCertificate'.tbsCertificate, - ClientExtensions = ClientOTPTbsCert#'OTPTBSCertificate'.extensions, - NewClientOTPTbsCert = ClientOTPTbsCert#'OTPTBSCertificate'{extensions = - [ClientExtKeyUsageExt | - ClientExtensions]}, - NewClientDerCert = public_key:pkix_sign(NewClientOTPTbsCert, Key), - ssl_test_lib:der_to_pem(NewClientCertFile, [{'Certificate', NewClientDerCert, not_encrypted}]), - NewClientOpts = [{certfile, NewClientCertFile} | proplists:delete(certfile, ClientOpts)], - - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send_recv_result_active, []}}, - {options, [{verify, verify_peer} | NewServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, send_recv_result_active, []}}, - {options, [{verify, verify_peer} | NewClientOpts]}]), - - ssl_test_lib:check_result(Server, ok, Client, ok), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). - -%%-------------------------------------------------------------------- -extended_key_usage_verify_none(doc) -> - ["Test cert that has a critical extended_key_usage extension in verify_none mode"]; - -extended_key_usage_verify_none(suite) -> - []; - -extended_key_usage_verify_none(Config) when is_list(Config) -> - ClientOpts = ?config(client_verification_opts, Config), - ServerOpts = ?config(server_verification_opts, Config), - PrivDir = ?config(priv_dir, Config), - - KeyFile = filename:join(PrivDir, "otpCA/private/key.pem"), - [KeyEntry] = ssl_test_lib:pem_to_der(KeyFile), - Key = ssl_test_lib:public_key(public_key:pem_entry_decode(KeyEntry)), - - ServerCertFile = proplists:get_value(certfile, ServerOpts), - NewServerCertFile = filename:join(PrivDir, "server/new_cert.pem"), - [{'Certificate', ServerDerCert, _}] = ssl_test_lib:pem_to_der(ServerCertFile), - ServerOTPCert = public_key:pkix_decode_cert(ServerDerCert, otp), - ServerExtKeyUsageExt = {'Extension', ?'id-ce-extKeyUsage', true, [?'id-kp-serverAuth']}, - ServerOTPTbsCert = ServerOTPCert#'OTPCertificate'.tbsCertificate, - ServerExtensions = ServerOTPTbsCert#'OTPTBSCertificate'.extensions, - NewServerOTPTbsCert = ServerOTPTbsCert#'OTPTBSCertificate'{extensions = - [ServerExtKeyUsageExt | - ServerExtensions]}, - NewServerDerCert = public_key:pkix_sign(NewServerOTPTbsCert, Key), - ssl_test_lib:der_to_pem(NewServerCertFile, [{'Certificate', NewServerDerCert, not_encrypted}]), - NewServerOpts = [{certfile, NewServerCertFile} | proplists:delete(certfile, ServerOpts)], - - ClientCertFile = proplists:get_value(certfile, ClientOpts), - NewClientCertFile = filename:join(PrivDir, "client/new_cert.pem"), - [{'Certificate', ClientDerCert, _}] = ssl_test_lib:pem_to_der(ClientCertFile), - ClientOTPCert = public_key:pkix_decode_cert(ClientDerCert, otp), - ClientExtKeyUsageExt = {'Extension', ?'id-ce-extKeyUsage', true, [?'id-kp-clientAuth']}, - ClientOTPTbsCert = ClientOTPCert#'OTPCertificate'.tbsCertificate, - ClientExtensions = ClientOTPTbsCert#'OTPTBSCertificate'.extensions, - NewClientOTPTbsCert = ClientOTPTbsCert#'OTPTBSCertificate'{extensions = - [ClientExtKeyUsageExt | - ClientExtensions]}, - NewClientDerCert = public_key:pkix_sign(NewClientOTPTbsCert, Key), - ssl_test_lib:der_to_pem(NewClientCertFile, [{'Certificate', NewClientDerCert, not_encrypted}]), - NewClientOpts = [{certfile, NewClientCertFile} | proplists:delete(certfile, ClientOpts)], - - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send_recv_result_active, []}}, - {options, [{verify, verify_none} | NewServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, send_recv_result_active, []}}, - {options, [{verify, verify_none} | NewClientOpts]}]), - - ssl_test_lib:check_result(Server, ok, Client, ok), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). - -%%-------------------------------------------------------------------- -no_authority_key_identifier(doc) -> - ["Test cert that does not have authorityKeyIdentifier extension" - " but are present in trusted certs db."]; - -no_authority_key_identifier(suite) -> - []; -no_authority_key_identifier(Config) when is_list(Config) -> - ClientOpts = ?config(client_verification_opts, Config), ServerOpts = ?config(server_opts, Config), - PrivDir = ?config(priv_dir, Config), - - KeyFile = filename:join(PrivDir, "otpCA/private/key.pem"), - [KeyEntry] = ssl_test_lib:pem_to_der(KeyFile), - Key = ssl_test_lib:public_key(public_key:pem_entry_decode(KeyEntry)), - - CertFile = proplists:get_value(certfile, ServerOpts), - NewCertFile = filename:join(PrivDir, "server/new_cert.pem"), - [{'Certificate', DerCert, _}] = ssl_test_lib:pem_to_der(CertFile), - OTPCert = public_key:pkix_decode_cert(DerCert, otp), - OTPTbsCert = OTPCert#'OTPCertificate'.tbsCertificate, - Extensions = OTPTbsCert#'OTPTBSCertificate'.extensions, - NewExtensions = delete_authority_key_extension(Extensions, []), - NewOTPTbsCert = OTPTbsCert#'OTPTBSCertificate'{extensions = NewExtensions}, - - test_server:format("Extensions ~p~n, NewExtensions: ~p~n", [Extensions, NewExtensions]), - - NewDerCert = public_key:pkix_sign(NewOTPTbsCert, Key), - ssl_test_lib:der_to_pem(NewCertFile, [{'Certificate', NewDerCert, not_encrypted}]), - NewServerOpts = [{certfile, NewCertFile} | proplists:delete(certfile, ServerOpts)], - - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send_recv_result_active, []}}, - {options, NewServerOpts}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, send_recv_result_active, []}}, - {options, [{verify, verify_peer} | ClientOpts]}]), - - ssl_test_lib:check_result(Server, ok, Client, ok), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). - -delete_authority_key_extension([], Acc) -> - lists:reverse(Acc); -delete_authority_key_extension([#'Extension'{extnID = ?'id-ce-authorityKeyIdentifier'} | Rest], - Acc) -> - delete_authority_key_extension(Rest, Acc); -delete_authority_key_extension([Head | Rest], Acc) -> - delete_authority_key_extension(Rest, [Head | Acc]). - -%%-------------------------------------------------------------------- - -invalid_signature_server(doc) -> - ["Test server with invalid signature"]; - -invalid_signature_server(suite) -> - []; - -invalid_signature_server(Config) when is_list(Config) -> - ClientOpts = ?config(client_verification_opts, Config), - ServerOpts = ?config(server_verification_opts, Config), - PrivDir = ?config(priv_dir, Config), - - KeyFile = filename:join(PrivDir, "server/key.pem"), - [KeyEntry] = ssl_test_lib:pem_to_der(KeyFile), - Key = ssl_test_lib:public_key(public_key:pem_entry_decode(KeyEntry)), - - ServerCertFile = proplists:get_value(certfile, ServerOpts), - NewServerCertFile = filename:join(PrivDir, "server/invalid_cert.pem"), - [{'Certificate', ServerDerCert, _}] = ssl_test_lib:pem_to_der(ServerCertFile), - ServerOTPCert = public_key:pkix_decode_cert(ServerDerCert, otp), - ServerOTPTbsCert = ServerOTPCert#'OTPCertificate'.tbsCertificate, - NewServerDerCert = public_key:pkix_sign(ServerOTPTbsCert, Key), - ssl_test_lib:der_to_pem(NewServerCertFile, [{'Certificate', NewServerDerCert, not_encrypted}]), - NewServerOpts = [{certfile, NewServerCertFile} | proplists:delete(certfile, ServerOpts)], - - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - - Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0}, - {from, self()}, - {options, NewServerOpts}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {options, [{verify, verify_peer} | ClientOpts]}]), - - tcp_delivery_workaround(Server, {error, "bad certificate"}, - Client, {error,"bad certificate"}). - -%%-------------------------------------------------------------------- - -invalid_signature_client(doc) -> - ["Test server with invalid signature"]; - -invalid_signature_client(suite) -> - []; - -invalid_signature_client(Config) when is_list(Config) -> - ClientOpts = ?config(client_verification_opts, Config), - ServerOpts = ?config(server_verification_opts, Config), - PrivDir = ?config(priv_dir, Config), - - KeyFile = filename:join(PrivDir, "client/key.pem"), - [KeyEntry] = ssl_test_lib:pem_to_der(KeyFile), - Key = ssl_test_lib:public_key(public_key:pem_entry_decode(KeyEntry)), - - ClientCertFile = proplists:get_value(certfile, ClientOpts), - NewClientCertFile = filename:join(PrivDir, "client/invalid_cert.pem"), - [{'Certificate', ClientDerCert, _}] = ssl_test_lib:pem_to_der(ClientCertFile), - ClientOTPCert = public_key:pkix_decode_cert(ClientDerCert, otp), - ClientOTPTbsCert = ClientOTPCert#'OTPCertificate'.tbsCertificate, - NewClientDerCert = public_key:pkix_sign(ClientOTPTbsCert, Key), - ssl_test_lib:der_to_pem(NewClientCertFile, [{'Certificate', NewClientDerCert, not_encrypted}]), - NewClientOpts = [{certfile, NewClientCertFile} | proplists:delete(certfile, ClientOpts)], - - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - - Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0}, - {from, self()}, - {options, [{verify, verify_peer} | ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {options, NewClientOpts}]), - - tcp_delivery_workaround(Server, {error, "bad certificate"}, - Client, {error,"bad certificate"}). - -tcp_delivery_workaround(Server, ServerMsg, Client, ClientMsg) -> - receive - {Server, ServerMsg} -> - client_msg(Client, ClientMsg); - {Client, ClientMsg} -> - server_msg(Server, ServerMsg); - {Client, {error,closed}} -> - server_msg(Server, ServerMsg); - {Server, {error,closed}} -> - client_msg(Client, ClientMsg); - {Client, {error, esslconnect}} -> - server_msg(Server, ServerMsg); - {Server, {error, esslaccept}} -> - client_msg(Client, ClientMsg) - end. - -client_msg(Client, ClientMsg) -> - receive - {Client, ClientMsg} -> - ok; - {Client, {error,closed}} -> - test_server:format("client got close"), - ok; - {Client, {error, esslconnect}} -> - test_server:format("client got econnaborted"), - ok; - Unexpected -> - test_server:fail(Unexpected) - end. - -server_msg(Server, ServerMsg) -> - receive - {Server, ServerMsg} -> - ok; - {Server, {error,closed}} -> - test_server:format("server got close"), - ok; - {Server, {error, esslaccept}} -> - test_server:format("server got econnaborted"), - ok; - Unexpected -> - test_server:fail(Unexpected) - end. - -%%-------------------------------------------------------------------- -cert_expired(doc) -> - ["Test server with invalid signature"]; - -cert_expired(suite) -> - []; - -cert_expired(Config) when is_list(Config) -> - ClientOpts = ?config(client_verification_opts, Config), - ServerOpts = ?config(server_verification_opts, Config), - PrivDir = ?config(priv_dir, Config), - - KeyFile = filename:join(PrivDir, "otpCA/private/key.pem"), - [KeyEntry] = ssl_test_lib:pem_to_der(KeyFile), - Key = ssl_test_lib:public_key(public_key:pem_entry_decode(KeyEntry)), - - ServerCertFile = proplists:get_value(certfile, ServerOpts), - NewServerCertFile = filename:join(PrivDir, "server/expired_cert.pem"), - [{'Certificate', DerCert, _}] = ssl_test_lib:pem_to_der(ServerCertFile), - OTPCert = public_key:pkix_decode_cert(DerCert, otp), - OTPTbsCert = OTPCert#'OTPCertificate'.tbsCertificate, - - {Year, Month, Day} = date(), - {Hours, Min, Sec} = time(), - NotBeforeStr = lists:flatten(io_lib:format("~p~s~s~s~s~sZ",[Year-2, - two_digits_str(Month), - two_digits_str(Day), - two_digits_str(Hours), - two_digits_str(Min), - two_digits_str(Sec)])), - NotAfterStr = lists:flatten(io_lib:format("~p~s~s~s~s~sZ",[Year-1, - two_digits_str(Month), - two_digits_str(Day), - two_digits_str(Hours), - two_digits_str(Min), - two_digits_str(Sec)])), - NewValidity = {'Validity', {generalTime, NotBeforeStr}, {generalTime, NotAfterStr}}, - - test_server:format("Validity: ~p ~n NewValidity: ~p ~n", - [OTPTbsCert#'OTPTBSCertificate'.validity, NewValidity]), - - NewOTPTbsCert = OTPTbsCert#'OTPTBSCertificate'{validity = NewValidity}, - NewServerDerCert = public_key:pkix_sign(NewOTPTbsCert, Key), - ssl_test_lib:der_to_pem(NewServerCertFile, [{'Certificate', NewServerDerCert, not_encrypted}]), - NewServerOpts = [{certfile, NewServerCertFile} | proplists:delete(certfile, ServerOpts)], - - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - - Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0}, - {from, self()}, - {options, NewServerOpts}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {options, [{verify, verify_peer} | ClientOpts]}]), - - ssl_test_lib:check_result(Server, {error, "certificate expired"}, - Client, {error, "certificate expired"}). - -two_digits_str(N) when N < 10 -> - lists:flatten(io_lib:format("0~p", [N])); -two_digits_str(N) -> - lists:flatten(io_lib:format("~p", [N])). - -%%-------------------------------------------------------------------- - -client_with_cert_cipher_suites_handshake(doc) -> - ["Test that client with a certificate without keyEncipherment usage " - " extension can connect to a server with restricted cipher suites "]; - -client_with_cert_cipher_suites_handshake(suite) -> - []; - -client_with_cert_cipher_suites_handshake(Config) when is_list(Config) -> - ClientOpts = ?config(client_verification_opts_digital_signature_only, Config), - ServerOpts = ?config(server_verification_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, - send_recv_result_active, []}}, - {options, [{active, true}, - {ciphers, ssl_test_lib:rsa_non_signed_suites()} - | ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, - send_recv_result_active, []}}, - {options, [{active, true} - | ClientOpts]}]), - - ssl_test_lib:check_result(Server, ok, Client, ok), - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). - -%%-------------------------------------------------------------------- -verify_fun_always_run_client(doc) -> - ["Verify that user verify_fun is always run (for valid and valid_peer not only unknown_extension)"]; -verify_fun_always_run_client(suite) -> - []; -verify_fun_always_run_client(Config) when is_list(Config) -> - ClientOpts = ?config(client_verification_opts, Config), - ServerOpts = ?config(server_verification_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, {ssl_test_lib, - no_result, []}}, - {options, ServerOpts}]), - Port = ssl_test_lib:inet_port(Server), - - %% If user verify fun is called correctly we fail the connection. - %% otherwise we can not tell this case apart form where we miss - %% to call users verify fun - FunAndState = {fun(_,{extension, _}, UserState) -> - {unknown, UserState}; - (_, valid, [ChainLen]) -> - {valid, [ChainLen + 1]}; - (_, valid_peer, [2]) -> - {fail, "verify_fun_was_always_run"}; - (_, valid_peer, UserState) -> - {valid, UserState} - end, [0]}, - - Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {ssl_test_lib, - no_result, []}}, - {options, - [{verify, verify_peer}, - {verify_fun, FunAndState} - | ClientOpts]}]), - %% Server error may be esslaccept or closed depending on timing - %% this is not a bug it is a circumstance of how tcp works! - receive - {Server, ServerError} -> - test_server:format("Server Error ~p~n", [ServerError]) - end, - - ssl_test_lib:check_result(Client, {error, esslconnect}). - -%%-------------------------------------------------------------------- -verify_fun_always_run_server(doc) -> - ["Verify that user verify_fun is always run (for valid and valid_peer not only unknown_extension)"]; -verify_fun_always_run_server(suite) -> - []; -verify_fun_always_run_server(Config) when is_list(Config) -> - ClientOpts = ?config(client_verification_opts, Config), - ServerOpts = ?config(server_verification_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - - %% If user verify fun is called correctly we fail the connection. - %% otherwise we can not tell this case apart form where we miss - %% to call users verify fun - FunAndState = {fun(_,{extension, _}, UserState) -> - {unknown, UserState}; - (_, valid, [ChainLen]) -> - {valid, [ChainLen + 1]}; - (_, valid_peer, [2]) -> - {fail, "verify_fun_was_always_run"}; - (_, valid_peer, UserState) -> - {valid, UserState} - end, [0]}, - - Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, {ssl_test_lib, - no_result, []}}, - {options, - [{verify, verify_peer}, - {verify_fun, FunAndState} | - ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - - Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {ssl_test_lib, - no_result, []}}, - {options, - [{verify, verify_peer} - | ClientOpts]}]), - - %% Client error may be esslconnect or closed depending on timing - %% this is not a bug it is a circumstance of how tcp works! - receive - {Client, ClientError} -> - test_server:format("Client Error ~p~n", [ClientError]) - end, - - ssl_test_lib:check_result(Server, {error, esslaccept}). - -%%-------------------------------------------------------------------- -unknown_server_ca_fail(doc) -> - ["Test that the client fails if the ca is unknown in verify_peer mode"]; -unknown_server_ca_fail(suite) -> - []; -unknown_server_ca_fail(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, {ssl_test_lib, - no_result, []}}, - {options, ServerOpts}]), - Port = ssl_test_lib:inet_port(Server), - - FunAndState = {fun(_,{bad_cert, unknown_ca} = Reason, _) -> - {fail, Reason}; - (_,{extension, _}, UserState) -> - {unknown, UserState}; - (_, valid, UserState) -> - {valid, [test_to_update_user_state | UserState]}; - (_, valid_peer, UserState) -> - {valid, UserState} - end, []}, - - Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {ssl_test_lib, - no_result, []}}, - {options, - [{verify, verify_peer}, - {verify_fun, FunAndState} - | ClientOpts]}]), - - ssl_test_lib:check_result(Server, {error,"unknown ca"}, - Client, {error, "unknown ca"}). - -%%-------------------------------------------------------------------- -unknown_server_ca_accept_verify_none(doc) -> - ["Test that the client succeds if the ca is unknown in verify_none mode"]; -unknown_server_ca_accept_verify_none(suite) -> - []; -unknown_server_ca_accept_verify_none(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, - send_recv_result_active, []}}, - {options, ServerOpts}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, - send_recv_result_active, []}}, - {options, - [{verify, verify_none}| ClientOpts]}]), + ClientOpts = ?config(client_opts, Config), - ssl_test_lib:check_result(Server, ok, Client, ok), - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). -%%-------------------------------------------------------------------- -unknown_server_ca_accept_verify_peer(doc) -> - ["Test that the client succeds if the ca is unknown in verify_peer mode" - " with a verify_fun that accepts the unknown ca error"]; -unknown_server_ca_accept_verify_peer(suite) -> - []; -unknown_server_ca_accept_verify_peer(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, - send_recv_result_active, []}}, - {options, ServerOpts}]), - Port = ssl_test_lib:inet_port(Server), - - FunAndState = {fun(_,{bad_cert, unknown_ca}, UserState) -> - {valid, UserState}; - (_,{bad_cert, _} = Reason, _) -> - {fail, Reason}; - (_,{extension, _}, UserState) -> - {unknown, UserState}; - (_, valid, UserState) -> - {valid, UserState}; - (_, valid_peer, UserState) -> - {valid, UserState} - end, []}, - - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, - send_recv_result_active, []}}, - {options, - [{verify, verify_peer}, - {verify_fun, FunAndState}| ClientOpts]}]), - ssl_test_lib:check_result(Server, ok, Client, ok), - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). + Data = "From erlang to erlang", + N = 10, -%%-------------------------------------------------------------------- -unknown_server_ca_accept_backwardscompatibility(doc) -> - ["Test that old style verify_funs will work"]; -unknown_server_ca_accept_backwardscompatibility(suite) -> - []; -unknown_server_ca_accept_backwardscompatibility(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, {from, self()}, - {mfa, {?MODULE, - send_recv_result_active, []}}, - {options, ServerOpts}]), - Port = ssl_test_lib:inet_port(Server), - - AcceptBadCa = fun({bad_cert,unknown_ca}, Acc) -> Acc; - (Other, Acc) -> [Other | Acc] - end, - VerifyFun = - fun(ErrorList) -> - case lists:foldl(AcceptBadCa, [], ErrorList) of - [] -> true; - [_|_] -> false - end - end, + {mfa, {ssl_test_lib, + trigger_renegotiate, [[Data, N+2]]}}, + {options, [{renegotiate_at, N} | ServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, {from, self()}, - {mfa, {?MODULE, - send_recv_result_active, []}}, - {options, - [{verify, verify_peer}, - {verify_fun, VerifyFun}| ClientOpts]}]), + {mfa, {ssl_test_lib, no_result, []}}, + {options, [{reuse_sessions, false} | ClientOpts]}]), - ssl_test_lib:check_result(Server, ok, Client, ok), + ssl_test_lib:check_result(Server, ok), ssl_test_lib:close(Server), ssl_test_lib:close(Client). %%-------------------------------------------------------------------- -der_input(doc) -> - ["Test to input certs and key as der"]; - -der_input(suite) -> - []; +der_input() -> + [{doc,"Test to input certs and key as der"}]. der_input(Config) when is_list(Config) -> DataDir = ?config(data_dir, Config), @@ -3556,19 +2017,19 @@ der_input(Config) when is_list(Config) -> {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, {from, self()}, - {mfa, {?MODULE, send_recv_result, []}}, + {mfa, {ssl_test_lib, send_recv_result, []}}, {options, [{active, false} | ServerOpts]}]), Port = ssl_test_lib:inet_port(Server), Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, {from, self()}, - {mfa, {?MODULE, send_recv_result, []}}, + {mfa, {ssl_test_lib, send_recv_result, []}}, {options, [{active, false} | ClientOpts]}]), ssl_test_lib:check_result(Server, ok, Client, ok), ssl_test_lib:close(Server), ssl_test_lib:close(Client). - +%%-------------------------------------------------------------------- der_input_opts(Opts) -> Certfile = proplists:get_value(certfile, Opts), CaCertsfile = proplists:get_value(cacertfile, Opts), @@ -3585,12 +2046,9 @@ der_input_opts(Opts) -> {Cert, {Asn1Type, Key}, CaCerts, DHParams}. %%-------------------------------------------------------------------- -%% different_ca_peer_sign(doc) -> +%% different_ca_peer_sign() -> %% ["Check that a CA can have a different signature algorithm than the peer cert."]; -%% different_ca_peer_sign(suite) -> -%% []; - %% different_ca_peer_sign(Config) when is_list(Config) -> %% ClientOpts = ?config(client_mix_opts, Config), %% ServerOpts = ?config(server_mix_verify_opts, Config), @@ -3598,7 +2056,7 @@ der_input_opts(Opts) -> %% {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), %% Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, %% {from, self()}, -%% {mfa, {?MODULE, send_recv_result_active_once, []}}, +%% {mfa, {ssl_test_lib, send_recv_result_active_once, []}}, %% {options, [{active, once}, %% {verify, verify_peer} | ServerOpts]}]), %% Port = ssl_test_lib:inet_port(Server), @@ -3606,7 +2064,7 @@ der_input_opts(Opts) -> %% Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, %% {host, Hostname}, %% {from, self()}, -%% {mfa, {?MODULE, +%% {mfa, {ssl_test_lib, %% send_recv_result_active_once, %% []}}, %% {options, [{active, once}, @@ -3619,12 +2077,8 @@ der_input_opts(Opts) -> %%-------------------------------------------------------------------- -no_reuses_session_server_restart_new_cert(doc) -> - ["Check that a session is not reused if the server is restarted with a new cert."]; - -no_reuses_session_server_restart_new_cert(suite) -> - []; - +no_reuses_session_server_restart_new_cert() -> + [{doc,"Check that a session is not reused if the server is restarted with a new cert."}]. no_reuses_session_server_restart_new_cert(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -3650,7 +2104,7 @@ no_reuses_session_server_restart_new_cert(Config) when is_list(Config) -> end, %% Make sure session is registered - test_server:sleep(?SLEEP), + ct:sleep(?SLEEP), Monitor = erlang:monitor(process, Server), ssl_test_lib:close(Server), ssl_test_lib:close(Client0), @@ -3672,7 +2126,7 @@ no_reuses_session_server_restart_new_cert(Config) when is_list(Config) -> {from, self()}, {options, ClientOpts}]), receive {Client1, SessionInfo} -> - test_server:fail(session_reused_when_server_has_new_cert); + ct:fail(session_reused_when_server_has_new_cert); {Client1, _Other} -> ok end, @@ -3680,12 +2134,9 @@ no_reuses_session_server_restart_new_cert(Config) when is_list(Config) -> ssl_test_lib:close(Client1). %%-------------------------------------------------------------------- -no_reuses_session_server_restart_new_cert_file(doc) -> - ["Check that a session is not reused if a server is restarted with a new " - "cert contained in a file with the same name as the old cert."]; - -no_reuses_session_server_restart_new_cert_file(suite) -> - []; +no_reuses_session_server_restart_new_cert_file() -> + [{doc,"Check that a session is not reused if a server is restarted with a new " + "cert contained in a file with the same name as the old cert."}]. no_reuses_session_server_restart_new_cert_file(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -3715,7 +2166,7 @@ no_reuses_session_server_restart_new_cert_file(Config) when is_list(Config) -> %% Make sure session is registered and we get %% new file time stamp when calling new_config! - test_server:sleep(?SLEEP* 2), + ct:sleep(?SLEEP* 2), ssl_test_lib:close(Server), ssl_test_lib:close(Client0), @@ -3735,7 +2186,7 @@ no_reuses_session_server_restart_new_cert_file(Config) when is_list(Config) -> {from, self()}, {options, ClientOpts}]), receive {Client1, SessionInfo} -> - test_server:fail(session_reused_when_server_has_new_cert); + ct:fail(session_reused_when_server_has_new_cert); {Client1, _Other} -> ok end, @@ -3743,11 +2194,8 @@ no_reuses_session_server_restart_new_cert_file(Config) when is_list(Config) -> ssl_test_lib:close(Client1). %%-------------------------------------------------------------------- -reuseaddr(doc) -> - [""]; - -reuseaddr(suite) -> - []; +reuseaddr() -> + [{doc,"Test reuseaddr option"}]. reuseaddr(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -3765,24 +2213,19 @@ reuseaddr(Config) when is_list(Config) -> {from, self()}, {mfa, {ssl_test_lib, no_result, []}}, {options, [{active, false} | ClientOpts]}]), - Monitor = erlang:monitor(process, Server), ssl_test_lib:close(Server), ssl_test_lib:close(Client), - receive - {'DOWN', Monitor, _, _, _} -> - ok - end, Server1 = ssl_test_lib:start_server([{node, ServerNode}, {port, Port}, {from, self()}, - {mfa, {?MODULE, send_recv_result, []}}, + {mfa, {ssl_test_lib, send_recv_result, []}}, {options, [{active, false} | ServerOpts]}]), Client1 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, {from, self()}, - {mfa, {?MODULE, send_recv_result, []}}, + {mfa, {ssl_test_lib, send_recv_result, []}}, {options, [{active, false} | ClientOpts]}]), ssl_test_lib:check_result(Server1, ok, Client1, ok), @@ -3790,14 +2233,51 @@ reuseaddr(Config) when is_list(Config) -> ssl_test_lib:close(Client1). %%-------------------------------------------------------------------- +tcp_reuseaddr() -> + [{doc, "Reference test case."}]. +tcp_reuseaddr(Config) when is_list(Config) -> + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + Server = + ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {transport, gen_tcp}, + {mfa, {ssl_test_lib, no_result, []}}, + {options, [{active, false}, {reuseaddr, true}]}]), + Port = ssl_test_lib:inet_port(Server), + Client = + ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {transport, gen_tcp}, + {from, self()}, + {mfa, {ssl_test_lib, no_result, []}}, + {options, [{active, false}]}]), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client), + + Server1 = + ssl_test_lib:start_server([{node, ServerNode}, {port, Port}, + {from, self()}, + {transport, gen_tcp}, + {mfa, {?MODULE, tcp_send_recv_result, []}}, + {options, [{active, false}, {reuseaddr, true}]}]), + Client1 = + ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {transport, gen_tcp}, + {mfa, {?MODULE, tcp_send_recv_result, []}}, + {options, [{active, false}]}]), + + ssl_test_lib:check_result(Server1, ok, Client1, ok), + ssl_test_lib:close(Server1), + ssl_test_lib:close(Client1). -hibernate(doc) -> - ["Check that an SSL connection that is started with option " - "{hibernate_after, 1000} indeed hibernates after 1000ms of " - "inactivity"]; +%%-------------------------------------------------------------------- -hibernate(suite) -> - []; +hibernate() -> + [{doc,"Check that an SSL connection that is started with option " + "{hibernate_after, 1000} indeed hibernates after 1000ms of " + "inactivity"}]. hibernate(Config) -> ClientOpts = ?config(client_opts, Config), @@ -3807,14 +2287,14 @@ hibernate(Config) -> Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, {from, self()}, - {mfa, {?MODULE, send_recv_result_active, []}}, + {mfa, {ssl_test_lib, send_recv_result_active, []}}, {options, ServerOpts}]), Port = ssl_test_lib:inet_port(Server), {Client, #sslsocket{pid=Pid}} = ssl_test_lib:start_client([return_socket, {node, ClientNode}, {port, Port}, {host, Hostname}, {from, self()}, - {mfa, {?MODULE, send_recv_result_active, []}}, + {mfa, {ssl_test_lib, send_recv_result_active, []}}, {options, [{hibernate_after, 1000}|ClientOpts]}]), {current_function, _} = process_info(Pid, current_function), @@ -3828,11 +2308,8 @@ hibernate(Config) -> ssl_test_lib:close(Client). %%-------------------------------------------------------------------- -listen_socket(doc) -> - ["Check error handling and inet compliance when calling API functions with listen sockets."]; - -listen_socket(suite) -> - []; +listen_socket() -> + [{doc,"Check error handling and inet compliance when calling API functions with listen sockets."}]. listen_socket(Config) -> ServerOpts = ?config(server_opts, Config), @@ -3856,10 +2333,9 @@ listen_socket(Config) -> ok = ssl:close(ListenSocket). %%-------------------------------------------------------------------- -ssl_accept_timeout(doc) -> - ["Test ssl:ssl_accept timeout"]; -ssl_accept_timeout(suite) -> - []; +ssl_accept_timeout() -> + [{doc,"Test ssl:ssl_accept timeout"}]. + ssl_accept_timeout(Config) -> process_flag(trap_exit, true), ServerOpts = ?config(server_opts, Config), @@ -3883,10 +2359,9 @@ ssl_accept_timeout(Config) -> end. %%-------------------------------------------------------------------- -ssl_recv_timeout(doc) -> - ["Test ssl:ssl_accept timeout"]; -ssl_recv_timeout(suite) -> - []; +ssl_recv_timeout() -> + [{doc,"Test ssl:ssl_accept timeout"}]. + ssl_recv_timeout(Config) -> ServerOpts = ?config(server_opts, Config), ClientOpts = ?config(client_opts, Config), @@ -3912,11 +2387,8 @@ ssl_recv_timeout(Config) -> ssl_test_lib:close(Client). %%-------------------------------------------------------------------- - -connect_twice(doc) -> - [""]; -connect_twice(suite) -> - []; +connect_twice() -> + [{doc,""}]. connect_twice(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -3926,7 +2398,7 @@ connect_twice(Config) when is_list(Config) -> Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, {from, self()}, - {mfa, {?MODULE, send_recv_result, []}}, + {mfa, {ssl_test_lib, send_recv_result, []}}, {options, [{keepalive, true},{active, false} | ServerOpts]}]), Port = ssl_test_lib:inet_port(Server), @@ -3934,7 +2406,7 @@ connect_twice(Config) when is_list(Config) -> ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, {host, Hostname}, {from, self()}, - {mfa, {?MODULE, send_recv_result, []}}, + {mfa, {ssl_test_lib, send_recv_result, []}}, {options, [{keepalive, true},{active, false} | ClientOpts]}]), Server ! listen, @@ -3944,11 +2416,11 @@ connect_twice(Config) when is_list(Config) -> {node, ClientNode}, {port, Port}, {host, Hostname}, {from, self()}, - {mfa, {?MODULE, send_recv_result, []}}, + {mfa, {ssl_test_lib, send_recv_result, []}}, {options, [{keepalive, true},{active, false} | ClientOpts]}]), - test_server:format("Testcase ~p, Client ~p Server ~p ~n", + ct:print("Testcase ~p, Client ~p Server ~p ~n", [self(), Client, Server]), ssl_test_lib:check_result(Server, ok, Client, ok), @@ -3959,13 +2431,9 @@ connect_twice(Config) when is_list(Config) -> ssl_test_lib:close(Client1). %%-------------------------------------------------------------------- -renegotiate_dos_mitigate_active(doc) -> - ["Mitigate DOS computational attack by not allowing client to renegotiate many times in a row", - "immediately after each other"]; - -renegotiate_dos_mitigate_active(suite) -> - []; - +renegotiate_dos_mitigate_active() -> + [{doc, "Mitigate DOS computational attack by not allowing client to renegotiate many times in a row", + "immediately after each other"}]. renegotiate_dos_mitigate_active(Config) when is_list(Config) -> ServerOpts = ?config(server_opts, Config), ClientOpts = ?config(client_opts, Config), @@ -3975,7 +2443,7 @@ renegotiate_dos_mitigate_active(Config) when is_list(Config) -> Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, {from, self()}, - {mfa, {?MODULE, send_recv_result_active, []}}, + {mfa, {ssl_test_lib, send_recv_result_active, []}}, {options, [ServerOpts]}]), Port = ssl_test_lib:inet_port(Server), @@ -3991,13 +2459,9 @@ renegotiate_dos_mitigate_active(Config) when is_list(Config) -> ssl_test_lib:close(Client). %%-------------------------------------------------------------------- -renegotiate_dos_mitigate_passive(doc) -> - ["Mitigate DOS computational attack by not allowing client to renegotiate many times in a row", - "immediately after each other"]; - -renegotiate_dos_mitigate_passive(suite) -> - []; - +renegotiate_dos_mitigate_passive() -> + [{doc, "Mitigate DOS computational attack by not allowing client to renegotiate many times in a row", + "immediately after each other"}]. renegotiate_dos_mitigate_passive(Config) when is_list(Config) -> ServerOpts = ?config(server_opts, Config), ClientOpts = ?config(client_opts, Config), @@ -4007,7 +2471,7 @@ renegotiate_dos_mitigate_passive(Config) when is_list(Config) -> Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, {from, self()}, - {mfa, {?MODULE, send_recv_result, []}}, + {mfa, {ssl_test_lib, send_recv_result, []}}, {options, [{active, false} | ServerOpts]}]), Port = ssl_test_lib:inet_port(Server), @@ -4023,8 +2487,8 @@ renegotiate_dos_mitigate_passive(Config) when is_list(Config) -> ssl_test_lib:close(Client). %%-------------------------------------------------------------------- -tcp_error_propagation_in_active_mode(doc) -> - ["Test that process recives {ssl_error, Socket, closed} when tcp error ocurres"]; +tcp_error_propagation_in_active_mode() -> + [{doc,"Test that process recives {ssl_error, Socket, closed} when tcp error ocurres"}]. tcp_error_propagation_in_active_mode(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -4053,11 +2517,9 @@ tcp_error_propagation_in_active_mode(Config) when is_list(Config) -> ssl_test_lib:check_result(Client, {ssl_closed, SslSocket}). - %%-------------------------------------------------------------------- - -recv_error_handling(doc) -> - ["Special case of call error handling"]; +recv_error_handling() -> + [{doc,"Special case of call error handling"}]. recv_error_handling(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -4077,11 +2539,11 @@ recv_error_handling(Config) when is_list(Config) -> ssl:close(SslSocket), ssl_test_lib:check_result(Server, ok). - %%-------------------------------------------------------------------- -rizzo(doc) -> ["Test that there is a 1/n-1-split for non RC4 in 'TLS < 1.1' as it is - vunrable to Rizzo/Dungon attack"]; +rizzo() -> + [{doc, "Test that there is a 1/n-1-split for non RC4 in 'TLS < 1.1' as it is + vunrable to Rizzo/Dungon attack"}]. rizzo(Config) when is_list(Config) -> Ciphers = [X || X ={_,Y,_} <- ssl:cipher_suites(), Y =/= rc4_128], @@ -4090,8 +2552,8 @@ rizzo(Config) when is_list(Config) -> run_send_recv_rizzo(Ciphers, Config, Version, {?MODULE, send_recv_result_active_rizzo, []}). %%-------------------------------------------------------------------- -no_rizzo_rc4(doc) -> - ["Test that there is no 1/n-1-split for RC4 as it is not vunrable to Rizzo/Dungon attack"]; +no_rizzo_rc4() -> + [{doc,"Test that there is no 1/n-1-split for RC4 as it is not vunrable to Rizzo/Dungon attack"}]. no_rizzo_rc4(Config) when is_list(Config) -> Ciphers = [X || X ={_,Y,_} <- ssl:cipher_suites(),Y == rc4_128], @@ -4101,59 +2563,9 @@ no_rizzo_rc4(Config) when is_list(Config) -> {?MODULE, send_recv_result_active_no_rizzo, []}). %%-------------------------------------------------------------------- -run_send_recv_rizzo(Ciphers, Config, Version, Mfa) -> - Result = lists:map(fun(Cipher) -> - rizzo_test(Cipher, Config, Version, Mfa) end, - Ciphers), - case lists:flatten(Result) of - [] -> - ok; - Error -> - test_server:format("Cipher suite errors: ~p~n", [Error]), - test_server:fail(cipher_suite_failed_see_test_case_log) - end. - -rizzo_test(Cipher, Config, Version, Mfa) -> - {ClientOpts, ServerOpts} = client_server_opts(Cipher, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, - {from, self()}, - {mfa, Mfa}, - {options, [{active, true}, {ciphers, [Cipher]}, - {versions, [Version]} - | ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, Mfa}, - {options, [{active, true} | ClientOpts]}]), - - Result = ssl_test_lib:check_result(Server, ok, Client, ok), - ssl_test_lib:close(Server), - ssl_test_lib:close(Client), - case Result of - ok -> - []; - Error -> - [{Cipher, Error}] - end. - -client_server_opts({KeyAlgo,_,_}, Config) when KeyAlgo == rsa orelse KeyAlgo == dhe_rsa -> - {?config(client_opts, Config), - ?config(server_opts, Config)}; -client_server_opts({KeyAlgo,_,_}, Config) when KeyAlgo == dss orelse KeyAlgo == dhe_dss -> - {?config(client_dsa_opts, Config), - ?config(server_dsa_opts, Config)}. - - -%%-------------------------------------------------------------------- - -new_server_wants_peer_cert(doc) -> - ["Test that server configured to do client certification does" - " not reuse session without a client certificate."]; -new_server_wants_peer_cert(suite) -> - []; +new_server_wants_peer_cert() -> + [{doc, "Test that server configured to do client certification does" + " not reuse session without a client certificate."}]. new_server_wants_peer_cert(Config) when is_list(Config) -> ServerOpts = ?config(server_opts, Config), VServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true} @@ -4206,14 +2618,50 @@ new_server_wants_peer_cert(Config) when is_list(Config) -> ssl_test_lib:close(Client), ssl_test_lib:close(Client1). +%%-------------------------------------------------------------------- +session_cache_process_list() -> + [{doc,"Test reuse of sessions (short handshake)"}]. +session_cache_process_list(Config) when is_list(Config) -> + session_cache_process(list,Config). +%%-------------------------------------------------------------------- +session_cache_process_mnesia() -> + [{doc,"Test reuse of sessions (short handshake)"}]. +session_cache_process_mnesia(Config) when is_list(Config) -> + session_cache_process(mnesia,Config). %%-------------------------------------------------------------------- -%%% Internal functions +%% Internal functions ------------------------------------------------ %%-------------------------------------------------------------------- send_recv_result(Socket) -> ssl:send(Socket, "Hello world"), {ok,"Hello world"} = ssl:recv(Socket, 11), ok. +tcp_send_recv_result(Socket) -> + gen_tcp:send(Socket, "Hello world"), + {ok,"Hello world"} = gen_tcp:recv(Socket, 11), + ok. + +basic_test(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, send_recv_result_active, []}}, + {options, ServerOpts}]), + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {ssl_test_lib, send_recv_result_active, []}}, + {options, ClientOpts}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). send_recv_result_timeout_client(Socket) -> {error, timeout} = ssl:recv(Socket, 11, 500), @@ -4241,17 +2689,6 @@ recv_close(Socket) -> ok end. -send_recv_result_active(Socket) -> - ssl:send(Socket, "Hello world"), - receive - {ssl, Socket, "H"} -> - receive - {ssl, Socket, "ello world"} -> - ok - end; - {ssl, Socket, "Hello world"} -> - ok - end. send_recv_result_active_rizzo(Socket) -> ssl:send(Socket, "Hello world"), @@ -4270,26 +2707,13 @@ send_recv_result_active_no_rizzo(Socket) -> ok end. -send_recv_result_active_once(Socket) -> - ssl:send(Socket, "Hello world"), - receive - {ssl, Socket, "H"} -> - ssl:setopts(Socket, [{active, once}]), - receive - {ssl, Socket, "ello world"} -> - ok - end; - {ssl, Socket, "Hello world"} -> - ok - end. - result_ok(_Socket) -> ok. renegotiate(Socket, Data) -> - test_server:format("Renegotiating ~n", []), + ct:print("Renegotiating ~n", []), Result = ssl:renegotiate(Socket), - test_server:format("Result ~p~n", [Result]), + ct:print("Result ~p~n", [Result]), ssl:send(Socket, Data), case Result of ok -> @@ -4300,7 +2724,7 @@ renegotiate(Socket, Data) -> renegotiate_reuse_session(Socket, Data) -> %% Make sure session is registered - test_server:sleep(?SLEEP), + ct:sleep(?SLEEP), renegotiate(Socket, Data). renegotiate_immediately(Socket) -> @@ -4316,9 +2740,9 @@ renegotiate_immediately(Socket) -> end, ok = ssl:renegotiate(Socket), {error, renegotiation_rejected} = ssl:renegotiate(Socket), - test_server:sleep(?RENEGOTIATION_DISABLE_TIME +1), + ct:sleep(?RENEGOTIATION_DISABLE_TIME +1), ok = ssl:renegotiate(Socket), - test_server:format("Renegotiated again"), + ct:print("Renegotiated again"), ssl:send(Socket, "Hello world"), ok. @@ -4337,27 +2761,11 @@ new_config(PrivDir, ServerOpts0) -> ServerOpts = proplists:delete(keyfile, ServerOpts2), {ok, PEM} = file:read_file(NewCaCertFile), - test_server:format("CA file content: ~p~n", [public_key:pem_decode(PEM)]), + ct:print("CA file content: ~p~n", [public_key:pem_decode(PEM)]), [{cacertfile, NewCaCertFile}, {certfile, NewCertFile}, {keyfile, NewKeyFile} | ServerOpts]. -session_cache_process_list(doc) -> - ["Test reuse of sessions (short handshake)"]; - -session_cache_process_list(suite) -> - []; -session_cache_process_list(Config) when is_list(Config) -> - session_cache_process(list,Config). - -session_cache_process_mnesia(doc) -> - ["Test reuse of sessions (short handshake)"]; - -session_cache_process_mnesia(suite) -> - []; -session_cache_process_mnesia(Config) when is_list(Config) -> - session_cache_process(mnesia,Config). - session_cache_process(_Type,Config) when is_list(Config) -> reuse_session(Config). @@ -4499,9 +2907,9 @@ erlang_ssl_receive(Socket, Data) -> io:format("Received ~p~n",[Byte]), erlang_ssl_receive(Socket, tl(Data)); Other -> - test_server:fail({unexpected_message, Other}) + ct:fail({unexpected_message, Other}) after ?SLEEP * 3 -> - test_server:fail({did_not_get, Data}) + ct:fail({did_not_get, Data}) end. receive_msg(_) -> @@ -4509,3 +2917,222 @@ receive_msg(_) -> Msg -> Msg end. + +controlling_process_result(Socket, Pid, Msg) -> + ok = ssl:controlling_process(Socket, Pid), + %% Make sure other side has evaluated controlling_process + %% before message is sent + ct:sleep(?SLEEP), + ssl:send(Socket, Msg), + no_result_msg. + +receive_s_rizzo_duong_beast() -> + receive + {ssl, _, "erver hello"} -> + receive + {ssl, _, "C"} -> + receive + {ssl, _, "lient hello"} -> + ok + end + end + end. +receive_c_rizzo_duong_beast() -> + receive + {ssl, _, "lient hello"} -> + receive + {ssl, _, "S"} -> + receive + {ssl, _, "erver hello"} -> + ok + end + end + end. + +controller_dies_result(_Socket, _Pid, _Msg) -> + receive Result -> Result end. + +get_close(Pid, Where) -> + receive + {'EXIT', Pid, _Reason} -> + receive + {_, {ssl_closed, Socket}} -> + ct:print("Socket closed ~p~n",[Socket]); + Unexpected -> + ct:print("Unexpected ~p~n",[Unexpected]), + ct:fail({line, ?LINE-1}) + after 5000 -> + ct:fail({timeout, {line, ?LINE, Where}}) + end; + Unexpected -> + ct:print("Unexpected ~p~n",[Unexpected]), + ct:fail({line, ?LINE-1}) + after 5000 -> + ct:fail({timeout, {line, ?LINE, Where}}) + end. + +run_send_recv_rizzo(Ciphers, Config, Version, Mfa) -> + Result = lists:map(fun(Cipher) -> + rizzo_test(Cipher, Config, Version, Mfa) end, + Ciphers), + case lists:flatten(Result) of + [] -> + ok; + Error -> + ct:print("Cipher suite errors: ~p~n", [Error]), + ct:fail(cipher_suite_failed_see_test_case_log) + end. + +rizzo_test(Cipher, Config, Version, Mfa) -> + {ClientOpts, ServerOpts} = client_server_opts(Cipher, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, Mfa}, + {options, [{active, true}, {ciphers, [Cipher]}, + {versions, [Version]} + | ServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, Mfa}, + {options, [{active, true} | ClientOpts]}]), + + Result = ssl_test_lib:check_result(Server, ok, Client, ok), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client), + case Result of + ok -> + []; + Error -> + [{Cipher, Error}] + end. + +client_server_opts({KeyAlgo,_,_}, Config) when KeyAlgo == rsa orelse KeyAlgo == dhe_rsa -> + {?config(client_opts, Config), + ?config(server_opts, Config)}; +client_server_opts({KeyAlgo,_,_}, Config) when KeyAlgo == dss orelse KeyAlgo == dhe_dss -> + {?config(client_dsa_opts, Config), + ?config(server_dsa_opts, Config)}. + +run_suites(Ciphers, Version, Config, Type) -> + {ClientOpts, ServerOpts} = + case Type of + rsa -> + {?config(client_opts, Config), + ?config(server_opts, Config)}; + dsa -> + {?config(client_opts, Config), + ?config(server_dsa_opts, Config)}; + anonymous -> + %% No certs in opts! + {?config(client_opts, Config), + ?config(server_anon, Config)} + end, + + Result = lists:map(fun(Cipher) -> + cipher(Cipher, Version, Config, ClientOpts, ServerOpts) end, + Ciphers), + case lists:flatten(Result) of + [] -> + ok; + Error -> + ct:print("Cipher suite errors: ~p~n", [Error]), + ct:fail(cipher_suite_failed_see_test_case_log) + end. + +erlang_cipher_suite(Suite) when is_list(Suite)-> + ssl:suite_definition(ssl_cipher:openssl_suite(Suite)); +erlang_cipher_suite(Suite) -> + Suite. + +cipher(CipherSuite, Version, Config, ClientOpts, ServerOpts) -> + %% process_flag(trap_exit, true), + ct:print("Testing CipherSuite ~p~n", [CipherSuite]), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + ErlangCipherSuite = erlang_cipher_suite(CipherSuite), + + ConnectionInfo = {ok, {Version, ErlangCipherSuite}}, + + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, cipher_result, [ConnectionInfo]}}, + {options, ServerOpts}]), + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {ssl_test_lib, cipher_result, [ConnectionInfo]}}, + {options, + [{ciphers,[CipherSuite]} | + ClientOpts]}]), + + Result = ssl_test_lib:wait_for_result(Server, ok, Client, ok), + + ssl_test_lib:close(Server), + ssl_test_lib:close(Client), + + case Result of + ok -> + []; + Error -> + [{ErlangCipherSuite, Error}] + end. + +connection_info_result(Socket) -> + ssl:connection_info(Socket). + +connect_dist_s(S) -> + Msg = term_to_binary({erlang,term}), + ok = ssl:send(S, Msg). + +connect_dist_c(S) -> + Test = binary_to_list(term_to_binary({erlang,term})), + {ok, Test} = ssl:recv(S, 0, 10000), + ok. + + %% First two clauses handles 1/n-1 splitting countermeasure Rizzo/Duong-Beast +treashold(N, {3,0}) -> + (N div 2) + 1; +treashold(N, {3,1}) -> + (N div 2) + 1; +treashold(N, _) -> + N + 1. + +get_invalid_inet_option(Socket) -> + {error, {eoptions, {inet_option, foo, _}}} = ssl:getopts(Socket, [foo]), + ok. + +shutdown_result(Socket, server) -> + ssl:send(Socket, "Hej"), + ssl:shutdown(Socket, write), + {ok, "Hej hopp"} = ssl:recv(Socket, 8), + ok; + +shutdown_result(Socket, client) -> + {ok, "Hej"} = ssl:recv(Socket, 3), + ssl:send(Socket, "Hej hopp"), + ssl:shutdown(Socket, write), + ok. + +shutdown_write_result(Socket, server) -> + ct:sleep(?SLEEP), + ssl:shutdown(Socket, write); +shutdown_write_result(Socket, client) -> + ssl:recv(Socket, 0). + +dummy(_Socket) -> + %% Should not happen as the ssl connection will not be established + %% due to fatal handshake failiure + exit(kill). + +shutdown_both_result(Socket, server) -> + ct:sleep(?SLEEP), + ssl:shutdown(Socket, read_write); +shutdown_both_result(Socket, client) -> + ssl:recv(Socket, 0). + +peername_result(S) -> + ssl:peername(S). diff --git a/lib/ssl/test/ssl_certificate_verify_SUITE.erl b/lib/ssl/test/ssl_certificate_verify_SUITE.erl new file mode 100644 index 0000000000..9677d98c1b --- /dev/null +++ b/lib/ssl/test/ssl_certificate_verify_SUITE.erl @@ -0,0 +1,982 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2012-2013. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/.2 +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +-module(ssl_certificate_verify_SUITE). + +%% Note: This directive should only be used in test suites. +-compile(export_all). + +-include_lib("common_test/include/ct.hrl"). +-include_lib("public_key/include/public_key.hrl"). + +-include("ssl_internal.hrl"). +-include("ssl_alert.hrl"). +-include("ssl_internal.hrl"). +-include("ssl_record.hrl"). +-include("ssl_handshake.hrl"). + +-define(LONG_TIMEOUT, 600000). + +%%-------------------------------------------------------------------- +%% Common Test interface functions ----------------------------------- +%%-------------------------------------------------------------------- + +suite() -> [{ct_hooks,[ts_install_cth]}]. + +all() -> + [{group, active}, + {group, passive}, + {group, active_once}, + {group, error_handling}]. + + +groups() -> + [{active, [], tests()}, + {active_once, [], tests()}, + {passive, [], tests()}, + {error_handling, [],error_handling_tests()}]. + +tests() -> + [server_verify_peer, + server_verify_none, + server_require_peer_cert_ok, + server_require_peer_cert_fail, + verify_fun_always_run_client, + verify_fun_always_run_server, + cert_expired, + invalid_signature_client, + invalid_signature_server, + extended_key_usage_verify_peer, + extended_key_usage_verify_none]. + +error_handling_tests()-> + [client_with_cert_cipher_suites_handshake, + server_verify_no_cacerts, + unknown_server_ca_fail, + unknown_server_ca_accept_verify_none, + unknown_server_ca_accept_verify_peer, + unknown_server_ca_accept_backwardscompatibility, + no_authority_key_identifier]. + +init_per_suite(Config0) -> + Dog = ct:timetrap(?LONG_TIMEOUT *2), + catch crypto:stop(), + try crypto:start() of + ok -> + application:start(public_key), + application:start(ssl), + %% make rsa certs using oppenssl + Result = + (catch make_certs:all(?config(data_dir, Config0), + ?config(priv_dir, Config0))), + ct:print("Make certs ~p~n", [Result]), + + Config1 = ssl_test_lib:make_dsa_cert(Config0), + Config = ssl_test_lib:cert_options(Config1), + [{watchdog, Dog} | Config] + catch _:_ -> + {skip, "Crypto did not start"} + end. + +end_per_suite(_Config) -> + ssl:stop(), + application:stop(crypto). + +init_per_group(active, Config) -> + [{active, true}, {receive_function, send_recv_result_active} | Config]; +init_per_group(active_once, Config) -> + [{active, once}, {receive_function, send_recv_result_active_once} | Config]; +init_per_group(passive, Config) -> + [{active, false}, {receive_function, send_recv_result} | Config]; +init_per_group(_, Config) -> + Config. + +end_per_group(_GroupName, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Test Cases -------------------------------------------------------- +%%-------------------------------------------------------------------- + +server_verify_peer() -> + [{doc,"Test server option verify_peer"}]. +server_verify_peer(Config) when is_list(Config) -> + ClientOpts = ?config(client_verification_opts, Config), + ServerOpts = ?config(server_verification_opts, Config), + Active = ?config(active, Config), + ReceiveFunction = ?config(receive_function, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, ReceiveFunction, []}}, + {options, [{active, Active}, {verify, verify_peer} + | ServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {ssl_test_lib, ReceiveFunction, []}}, + {options, [{active, Active} | ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + +%%-------------------------------------------------------------------- +server_verify_none() -> + [{doc,"Test server option verify_none"}]. + +server_verify_none(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + Active = ?config(active, Config), + ReceiveFunction = ?config(receive_function, Config), + + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, ReceiveFunction, []}}, + {options, [{active, Active}, {verify, verify_none} + | ServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {ssl_test_lib, ReceiveFunction, []}}, + {options, [{active, Active} | ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + +%%-------------------------------------------------------------------- + +server_verify_client_once() -> + [{doc,"Test server option verify_client_once"}]. + +server_verify_client_once(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_verification_opts, Config), + Active = ?config(active, Config), + ReceiveFunction = ?config(receive_function, Config), + + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, ReceiveFunction, []}}, + {options, [{active, Active}, {verify, verify_peer}, + {verify_client_once, true} + | ServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), + Client0 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {ssl_test_lib, ReceiveFunction, []}}, + {options, [{active, Active} | ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client0, ok), + Server ! {listen, {mfa, {ssl_test_lib, no_result, []}}}, + ssl_test_lib:close(Client0), + Client1 = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, result_ok, []}}, + {options, [{active, Active} | ClientOpts]}]), + + ssl_test_lib:check_result(Client1, ok), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client1). + +%%-------------------------------------------------------------------- + +server_require_peer_cert_ok() -> + [{doc,"Test server option fail_if_no_peer_cert when peer sends cert"}]. + +server_require_peer_cert_ok(Config) when is_list(Config) -> + ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true} + | ?config(server_verification_opts, Config)], + ClientOpts = ?config(client_verification_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib,send_recv_result, []}}, + {options, [{active, false} | ServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {ssl_test_lib, send_recv_result, []}}, + {options, [{active, false} | ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + +%%-------------------------------------------------------------------- + +server_require_peer_cert_fail() -> + [{doc,"Test server option fail_if_no_peer_cert when peer doesn't send cert"}]. + +server_require_peer_cert_fail(Config) when is_list(Config) -> + ServerOpts = [{verify, verify_peer}, {fail_if_no_peer_cert, true} + | ?config(server_verification_opts, Config)], + BadClientOpts = ?config(client_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0}, + {from, self()}, + {options, [{active, false} | ServerOpts]}]), + + Port = ssl_test_lib:inet_port(Server), + + Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {options, [{active, false} | BadClientOpts]}]), + + ssl_test_lib:check_result(Server, {error, esslaccept}, + Client, {error, esslconnect}). + + +%%-------------------------------------------------------------------- +verify_fun_always_run_client() -> + [{doc,"Verify that user verify_fun is always run (for valid and valid_peer not only unknown_extension)"}]. + +verify_fun_always_run_client(Config) when is_list(Config) -> + ClientOpts = ?config(client_verification_opts, Config), + ServerOpts = ?config(server_verification_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, + no_result, []}}, + {options, ServerOpts}]), + Port = ssl_test_lib:inet_port(Server), + + %% If user verify fun is called correctly we fail the connection. + %% otherwise we can not tell this case apart form where we miss + %% to call users verify fun + FunAndState = {fun(_,{extension, _}, UserState) -> + {unknown, UserState}; + (_, valid, [ChainLen]) -> + {valid, [ChainLen + 1]}; + (_, valid_peer, [2]) -> + {fail, "verify_fun_was_always_run"}; + (_, valid_peer, UserState) -> + {valid, UserState} + end, [0]}, + + Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {ssl_test_lib, + no_result, []}}, + {options, + [{verify, verify_peer}, + {verify_fun, FunAndState} + | ClientOpts]}]), + %% Server error may be esslaccept or closed depending on timing + %% this is not a bug it is a circumstance of how tcp works! + receive + {Server, ServerError} -> + ct:print("Server Error ~p~n", [ServerError]) + end, + + ssl_test_lib:check_result(Client, {error, esslconnect}). + +%%-------------------------------------------------------------------- +verify_fun_always_run_server() -> + [{doc,"Verify that user verify_fun is always run (for valid and valid_peer not only unknown_extension)"}]. +verify_fun_always_run_server(Config) when is_list(Config) -> + ClientOpts = ?config(client_verification_opts, Config), + ServerOpts = ?config(server_verification_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + %% If user verify fun is called correctly we fail the connection. + %% otherwise we can not tell this case apart form where we miss + %% to call users verify fun + FunAndState = {fun(_,{extension, _}, UserState) -> + {unknown, UserState}; + (_, valid, [ChainLen]) -> + {valid, [ChainLen + 1]}; + (_, valid_peer, [2]) -> + {fail, "verify_fun_was_always_run"}; + (_, valid_peer, UserState) -> + {valid, UserState} + end, [0]}, + + Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, + no_result, []}}, + {options, + [{verify, verify_peer}, + {verify_fun, FunAndState} | + ServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), + + Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {ssl_test_lib, + no_result, []}}, + {options, + [{verify, verify_peer} + | ClientOpts]}]), + + %% Client error may be esslconnect or closed depending on timing + %% this is not a bug it is a circumstance of how tcp works! + receive + {Client, ClientError} -> + ct:print("Client Error ~p~n", [ClientError]) + end, + + ssl_test_lib:check_result(Server, {error, esslaccept}). + +%%-------------------------------------------------------------------- + +client_verify_none_passive() -> + [{doc,"Test client option verify_none"}]. + +client_verify_none_passive(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, send_recv_result, []}}, + {options, [{active, false} + | ServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), + + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {ssl_test_lib, send_recv_result, []}}, + {options, [{active, false}, + {verify, verify_none} + | ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). +%%-------------------------------------------------------------------- +cert_expired() -> + [{doc,"Test server with invalid signature"}]. + +cert_expired(Config) when is_list(Config) -> + ClientOpts = ?config(client_verification_opts, Config), + ServerOpts = ?config(server_verification_opts, Config), + PrivDir = ?config(priv_dir, Config), + + KeyFile = filename:join(PrivDir, "otpCA/private/key.pem"), + [KeyEntry] = ssl_test_lib:pem_to_der(KeyFile), + Key = ssl_test_lib:public_key(public_key:pem_entry_decode(KeyEntry)), + + ServerCertFile = proplists:get_value(certfile, ServerOpts), + NewServerCertFile = filename:join(PrivDir, "server/expired_cert.pem"), + [{'Certificate', DerCert, _}] = ssl_test_lib:pem_to_der(ServerCertFile), + OTPCert = public_key:pkix_decode_cert(DerCert, otp), + OTPTbsCert = OTPCert#'OTPCertificate'.tbsCertificate, + + {Year, Month, Day} = date(), + {Hours, Min, Sec} = time(), + NotBeforeStr = lists:flatten(io_lib:format("~p~s~s~s~s~sZ",[Year-2, + two_digits_str(Month), + two_digits_str(Day), + two_digits_str(Hours), + two_digits_str(Min), + two_digits_str(Sec)])), + NotAfterStr = lists:flatten(io_lib:format("~p~s~s~s~s~sZ",[Year-1, + two_digits_str(Month), + two_digits_str(Day), + two_digits_str(Hours), + two_digits_str(Min), + two_digits_str(Sec)])), + NewValidity = {'Validity', {generalTime, NotBeforeStr}, {generalTime, NotAfterStr}}, + + ct:print("Validity: ~p ~n NewValidity: ~p ~n", + [OTPTbsCert#'OTPTBSCertificate'.validity, NewValidity]), + + NewOTPTbsCert = OTPTbsCert#'OTPTBSCertificate'{validity = NewValidity}, + NewServerDerCert = public_key:pkix_sign(NewOTPTbsCert, Key), + ssl_test_lib:der_to_pem(NewServerCertFile, [{'Certificate', NewServerDerCert, not_encrypted}]), + NewServerOpts = [{certfile, NewServerCertFile} | proplists:delete(certfile, ServerOpts)], + + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0}, + {from, self()}, + {options, NewServerOpts}]), + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {options, [{verify, verify_peer} | ClientOpts]}]), + + ssl_test_lib:check_result(Server, {error, "certificate expired"}, + Client, {error, "certificate expired"}). + +two_digits_str(N) when N < 10 -> + lists:flatten(io_lib:format("0~p", [N])); +two_digits_str(N) -> + lists:flatten(io_lib:format("~p", [N])). + +%%-------------------------------------------------------------------- + +client_verify_none_active() -> + [{doc,"Test client option verify_none"}]. + +client_verify_none_active(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, + send_recv_result_active, []}}, + {options, [{active, true} + | ServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {ssl_test_lib, + send_recv_result_active, []}}, + {options, [{active, true}, + {verify, verify_none} + | ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + +%%-------------------------------------------------------------------- +client_verify_none_active_once() -> + [{doc,"Test client option verify_none"}]. + +client_verify_none_active_once(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, send_recv_result_active, []}}, + {options, [{active, once} | ServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), + + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {ssl_test_lib, + send_recv_result_active_once, + []}}, + {options, [{active, once}, + {verify, verify_none} + | ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + +%%-------------------------------------------------------------------- +extended_key_usage_verify_peer() -> + [{doc,"Test cert that has a critical extended_key_usage extension in verify_peer mode"}]. + +extended_key_usage_verify_peer(Config) when is_list(Config) -> + ClientOpts = ?config(client_verification_opts, Config), + ServerOpts = ?config(server_verification_opts, Config), + PrivDir = ?config(priv_dir, Config), + Active = ?config(active, Config), + ReceiveFunction = ?config(receive_function, Config), + + KeyFile = filename:join(PrivDir, "otpCA/private/key.pem"), + [KeyEntry] = ssl_test_lib:pem_to_der(KeyFile), + Key = ssl_test_lib:public_key(public_key:pem_entry_decode(KeyEntry)), + + ServerCertFile = proplists:get_value(certfile, ServerOpts), + NewServerCertFile = filename:join(PrivDir, "server/new_cert.pem"), + [{'Certificate', ServerDerCert, _}] = ssl_test_lib:pem_to_der(ServerCertFile), + ServerOTPCert = public_key:pkix_decode_cert(ServerDerCert, otp), + ServerExtKeyUsageExt = {'Extension', ?'id-ce-extKeyUsage', true, [?'id-kp-serverAuth']}, + ServerOTPTbsCert = ServerOTPCert#'OTPCertificate'.tbsCertificate, + ServerExtensions = ServerOTPTbsCert#'OTPTBSCertificate'.extensions, + NewServerOTPTbsCert = ServerOTPTbsCert#'OTPTBSCertificate'{extensions = + [ServerExtKeyUsageExt | + ServerExtensions]}, + NewServerDerCert = public_key:pkix_sign(NewServerOTPTbsCert, Key), + ssl_test_lib:der_to_pem(NewServerCertFile, [{'Certificate', NewServerDerCert, not_encrypted}]), + NewServerOpts = [{certfile, NewServerCertFile} | proplists:delete(certfile, ServerOpts)], + + ClientCertFile = proplists:get_value(certfile, ClientOpts), + NewClientCertFile = filename:join(PrivDir, "client/new_cert.pem"), + [{'Certificate', ClientDerCert, _}] = ssl_test_lib:pem_to_der(ClientCertFile), + ClientOTPCert = public_key:pkix_decode_cert(ClientDerCert, otp), + ClientExtKeyUsageExt = {'Extension', ?'id-ce-extKeyUsage', true, [?'id-kp-clientAuth']}, + ClientOTPTbsCert = ClientOTPCert#'OTPCertificate'.tbsCertificate, + ClientExtensions = ClientOTPTbsCert#'OTPTBSCertificate'.extensions, + NewClientOTPTbsCert = ClientOTPTbsCert#'OTPTBSCertificate'{extensions = + [ClientExtKeyUsageExt | + ClientExtensions]}, + NewClientDerCert = public_key:pkix_sign(NewClientOTPTbsCert, Key), + ssl_test_lib:der_to_pem(NewClientCertFile, [{'Certificate', NewClientDerCert, not_encrypted}]), + NewClientOpts = [{certfile, NewClientCertFile} | proplists:delete(certfile, ClientOpts)], + + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, ReceiveFunction, []}}, + {options, [{verify, verify_peer}, {active, Active} | NewServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {ssl_test_lib, ReceiveFunction, []}}, + {options, [{verify, verify_peer}, {active, Active} | + NewClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + +%%-------------------------------------------------------------------- +extended_key_usage_verify_none() -> + [{doc,"Test cert that has a critical extended_key_usage extension in verify_none mode"}]. + +extended_key_usage_verify_none(Config) when is_list(Config) -> + ClientOpts = ?config(client_verification_opts, Config), + ServerOpts = ?config(server_verification_opts, Config), + PrivDir = ?config(priv_dir, Config), + Active = ?config(active, Config), + ReceiveFunction = ?config(receive_function, Config), + + KeyFile = filename:join(PrivDir, "otpCA/private/key.pem"), + [KeyEntry] = ssl_test_lib:pem_to_der(KeyFile), + Key = ssl_test_lib:public_key(public_key:pem_entry_decode(KeyEntry)), + + ServerCertFile = proplists:get_value(certfile, ServerOpts), + NewServerCertFile = filename:join(PrivDir, "server/new_cert.pem"), + [{'Certificate', ServerDerCert, _}] = ssl_test_lib:pem_to_der(ServerCertFile), + ServerOTPCert = public_key:pkix_decode_cert(ServerDerCert, otp), + ServerExtKeyUsageExt = {'Extension', ?'id-ce-extKeyUsage', true, [?'id-kp-serverAuth']}, + ServerOTPTbsCert = ServerOTPCert#'OTPCertificate'.tbsCertificate, + ServerExtensions = ServerOTPTbsCert#'OTPTBSCertificate'.extensions, + NewServerOTPTbsCert = ServerOTPTbsCert#'OTPTBSCertificate'{extensions = + [ServerExtKeyUsageExt | + ServerExtensions]}, + NewServerDerCert = public_key:pkix_sign(NewServerOTPTbsCert, Key), + ssl_test_lib:der_to_pem(NewServerCertFile, [{'Certificate', NewServerDerCert, not_encrypted}]), + NewServerOpts = [{certfile, NewServerCertFile} | proplists:delete(certfile, ServerOpts)], + + ClientCertFile = proplists:get_value(certfile, ClientOpts), + NewClientCertFile = filename:join(PrivDir, "client/new_cert.pem"), + [{'Certificate', ClientDerCert, _}] = ssl_test_lib:pem_to_der(ClientCertFile), + ClientOTPCert = public_key:pkix_decode_cert(ClientDerCert, otp), + ClientExtKeyUsageExt = {'Extension', ?'id-ce-extKeyUsage', true, [?'id-kp-clientAuth']}, + ClientOTPTbsCert = ClientOTPCert#'OTPCertificate'.tbsCertificate, + ClientExtensions = ClientOTPTbsCert#'OTPTBSCertificate'.extensions, + NewClientOTPTbsCert = ClientOTPTbsCert#'OTPTBSCertificate'{extensions = + [ClientExtKeyUsageExt | + ClientExtensions]}, + NewClientDerCert = public_key:pkix_sign(NewClientOTPTbsCert, Key), + ssl_test_lib:der_to_pem(NewClientCertFile, [{'Certificate', NewClientDerCert, not_encrypted}]), + NewClientOpts = [{certfile, NewClientCertFile} | proplists:delete(certfile, ClientOpts)], + + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, ReceiveFunction, []}}, + {options, [{verify, verify_none}, {active, Active} | NewServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {ssl_test_lib, ReceiveFunction, []}}, + {options, [{verify, verify_none}, {active, Active} | NewClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + +%%-------------------------------------------------------------------- +no_authority_key_identifier() -> + [{doc, "Test cert that does not have authorityKeyIdentifier extension" + " but are present in trusted certs db."}]. + +no_authority_key_identifier(Config) when is_list(Config) -> + ClientOpts = ?config(client_verification_opts, Config), + ServerOpts = ?config(server_opts, Config), + PrivDir = ?config(priv_dir, Config), + + KeyFile = filename:join(PrivDir, "otpCA/private/key.pem"), + [KeyEntry] = ssl_test_lib:pem_to_der(KeyFile), + Key = ssl_test_lib:public_key(public_key:pem_entry_decode(KeyEntry)), + + CertFile = proplists:get_value(certfile, ServerOpts), + NewCertFile = filename:join(PrivDir, "server/new_cert.pem"), + [{'Certificate', DerCert, _}] = ssl_test_lib:pem_to_der(CertFile), + OTPCert = public_key:pkix_decode_cert(DerCert, otp), + OTPTbsCert = OTPCert#'OTPCertificate'.tbsCertificate, + Extensions = OTPTbsCert#'OTPTBSCertificate'.extensions, + NewExtensions = delete_authority_key_extension(Extensions, []), + NewOTPTbsCert = OTPTbsCert#'OTPTBSCertificate'{extensions = NewExtensions}, + + ct:print("Extensions ~p~n, NewExtensions: ~p~n", [Extensions, NewExtensions]), + + NewDerCert = public_key:pkix_sign(NewOTPTbsCert, Key), + ssl_test_lib:der_to_pem(NewCertFile, [{'Certificate', NewDerCert, not_encrypted}]), + NewServerOpts = [{certfile, NewCertFile} | proplists:delete(certfile, ServerOpts)], + + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, send_recv_result_active, []}}, + {options, NewServerOpts}]), + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {ssl_test_lib, send_recv_result_active, []}}, + {options, [{verify, verify_peer} | ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + +delete_authority_key_extension([], Acc) -> + lists:reverse(Acc); +delete_authority_key_extension([#'Extension'{extnID = ?'id-ce-authorityKeyIdentifier'} | Rest], + Acc) -> + delete_authority_key_extension(Rest, Acc); +delete_authority_key_extension([Head | Rest], Acc) -> + delete_authority_key_extension(Rest, [Head | Acc]). + +%%-------------------------------------------------------------------- + +invalid_signature_server() -> + [{doc,"Test server with invalid signature"}]. + +invalid_signature_server(Config) when is_list(Config) -> + ClientOpts = ?config(client_verification_opts, Config), + ServerOpts = ?config(server_verification_opts, Config), + PrivDir = ?config(priv_dir, Config), + + KeyFile = filename:join(PrivDir, "server/key.pem"), + [KeyEntry] = ssl_test_lib:pem_to_der(KeyFile), + Key = ssl_test_lib:public_key(public_key:pem_entry_decode(KeyEntry)), + + ServerCertFile = proplists:get_value(certfile, ServerOpts), + NewServerCertFile = filename:join(PrivDir, "server/invalid_cert.pem"), + [{'Certificate', ServerDerCert, _}] = ssl_test_lib:pem_to_der(ServerCertFile), + ServerOTPCert = public_key:pkix_decode_cert(ServerDerCert, otp), + ServerOTPTbsCert = ServerOTPCert#'OTPCertificate'.tbsCertificate, + NewServerDerCert = public_key:pkix_sign(ServerOTPTbsCert, Key), + ssl_test_lib:der_to_pem(NewServerCertFile, [{'Certificate', NewServerDerCert, not_encrypted}]), + NewServerOpts = [{certfile, NewServerCertFile} | proplists:delete(certfile, ServerOpts)], + + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0}, + {from, self()}, + {options, NewServerOpts}]), + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {options, [{verify, verify_peer} | ClientOpts]}]), + + tcp_delivery_workaround(Server, {error, "bad certificate"}, + Client, {error,"bad certificate"}). + +%%-------------------------------------------------------------------- + +invalid_signature_client() -> + [{doc,"Test server with invalid signature"}]. + +invalid_signature_client(Config) when is_list(Config) -> + ClientOpts = ?config(client_verification_opts, Config), + ServerOpts = ?config(server_verification_opts, Config), + PrivDir = ?config(priv_dir, Config), + + KeyFile = filename:join(PrivDir, "client/key.pem"), + [KeyEntry] = ssl_test_lib:pem_to_der(KeyFile), + Key = ssl_test_lib:public_key(public_key:pem_entry_decode(KeyEntry)), + + ClientCertFile = proplists:get_value(certfile, ClientOpts), + NewClientCertFile = filename:join(PrivDir, "client/invalid_cert.pem"), + [{'Certificate', ClientDerCert, _}] = ssl_test_lib:pem_to_der(ClientCertFile), + ClientOTPCert = public_key:pkix_decode_cert(ClientDerCert, otp), + ClientOTPTbsCert = ClientOTPCert#'OTPCertificate'.tbsCertificate, + NewClientDerCert = public_key:pkix_sign(ClientOTPTbsCert, Key), + ssl_test_lib:der_to_pem(NewClientCertFile, [{'Certificate', NewClientDerCert, not_encrypted}]), + NewClientOpts = [{certfile, NewClientCertFile} | proplists:delete(certfile, ClientOpts)], + + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0}, + {from, self()}, + {options, [{verify, verify_peer} | ServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {options, NewClientOpts}]), + + tcp_delivery_workaround(Server, {error, "bad certificate"}, + Client, {error,"bad certificate"}). + + +%%-------------------------------------------------------------------- + +client_with_cert_cipher_suites_handshake() -> + [{doc, "Test that client with a certificate without keyEncipherment usage " + " extension can connect to a server with restricted cipher suites "}]. +client_with_cert_cipher_suites_handshake(Config) when is_list(Config) -> + ClientOpts = ?config(client_verification_opts_digital_signature_only, Config), + ServerOpts = ?config(server_verification_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, + send_recv_result_active, []}}, + {options, [{active, true}, + {ciphers, ssl_test_lib:rsa_non_signed_suites()} + | ServerOpts]}]), + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {ssl_test_lib, + send_recv_result_active, []}}, + {options, [{active, true} + | ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + +%%-------------------------------------------------------------------- + +server_verify_no_cacerts() -> + [{doc,"Test server must have cacerts if it wants to verify client"}]. +server_verify_no_cacerts(Config) when is_list(Config) -> + ServerOpts = ?config(server_opts, Config), + {_, ServerNode, _} = ssl_test_lib:run_where(Config), + Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0}, + {from, self()}, + {options, [{verify, verify_peer} + | ServerOpts]}]), + + ssl_test_lib:check_result(Server, {error, {eoptions, {cacertfile, ""}}}). + + +%%-------------------------------------------------------------------- +unknown_server_ca_fail() -> + [{doc,"Test that the client fails if the ca is unknown in verify_peer mode"}]. +unknown_server_ca_fail(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, + no_result, []}}, + {options, ServerOpts}]), + Port = ssl_test_lib:inet_port(Server), + + FunAndState = {fun(_,{bad_cert, unknown_ca} = Reason, _) -> + {fail, Reason}; + (_,{extension, _}, UserState) -> + {unknown, UserState}; + (_, valid, UserState) -> + {valid, [test_to_update_user_state | UserState]}; + (_, valid_peer, UserState) -> + {valid, UserState} + end, []}, + + Client = ssl_test_lib:start_client_error([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {ssl_test_lib, + no_result, []}}, + {options, + [{verify, verify_peer}, + {verify_fun, FunAndState} + | ClientOpts]}]), + + ssl_test_lib:check_result(Server, {error,"unknown ca"}, + Client, {error, "unknown ca"}). + +%%-------------------------------------------------------------------- +unknown_server_ca_accept_verify_none() -> + [{doc,"Test that the client succeds if the ca is unknown in verify_none mode"}]. +unknown_server_ca_accept_verify_none(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, + send_recv_result_active, []}}, + {options, ServerOpts}]), + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {ssl_test_lib, + send_recv_result_active, []}}, + {options, + [{verify, verify_none}| ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). +%%-------------------------------------------------------------------- +unknown_server_ca_accept_verify_peer() -> + [{doc, "Test that the client succeds if the ca is unknown in verify_peer mode" + " with a verify_fun that accepts the unknown ca error"}]. +unknown_server_ca_accept_verify_peer(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, + send_recv_result_active, []}}, + {options, ServerOpts}]), + Port = ssl_test_lib:inet_port(Server), + + FunAndState = {fun(_,{bad_cert, unknown_ca}, UserState) -> + {valid, UserState}; + (_,{bad_cert, _} = Reason, _) -> + {fail, Reason}; + (_,{extension, _}, UserState) -> + {unknown, UserState}; + (_, valid, UserState) -> + {valid, UserState}; + (_, valid_peer, UserState) -> + {valid, UserState} + end, []}, + + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {ssl_test_lib, + send_recv_result_active, []}}, + {options, + [{verify, verify_peer}, + {verify_fun, FunAndState}| ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + +%%-------------------------------------------------------------------- +unknown_server_ca_accept_backwardscompatibility() -> + [{doc,"Test that old style verify_funs will work"}]. +unknown_server_ca_accept_backwardscompatibility(Config) when is_list(Config) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0}, + {from, self()}, + {mfa, {ssl_test_lib, + send_recv_result_active, []}}, + {options, ServerOpts}]), + Port = ssl_test_lib:inet_port(Server), + + AcceptBadCa = fun({bad_cert,unknown_ca}, Acc) -> Acc; + (Other, Acc) -> [Other | Acc] + end, + VerifyFun = + fun(ErrorList) -> + case lists:foldl(AcceptBadCa, [], ErrorList) of + [] -> true; + [_|_] -> false + end + end, + + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {ssl_test_lib, + send_recv_result_active, []}}, + {options, + [{verify, verify_peer}, + {verify_fun, VerifyFun}| ClientOpts]}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). + +%%-------------------------------------------------------------------- +%% Internal functions ------------------------------------------------ +%%-------------------------------------------------------------------- + +tcp_delivery_workaround(Server, ServerMsg, Client, ClientMsg) -> + receive + {Server, ServerMsg} -> + client_msg(Client, ClientMsg); + {Client, ClientMsg} -> + server_msg(Server, ServerMsg); + {Client, {error,closed}} -> + server_msg(Server, ServerMsg); + {Server, {error,closed}} -> + client_msg(Client, ClientMsg); + {Client, {error, esslconnect}} -> + server_msg(Server, ServerMsg); + {Server, {error, esslaccept}} -> + client_msg(Client, ClientMsg) + end. + +client_msg(Client, ClientMsg) -> + receive + {Client, ClientMsg} -> + ok; + {Client, {error,closed}} -> + ct:print("client got close"), + ok; + {Client, {error, esslconnect}} -> + ct:print("client got econnaborted"), + ok; + Unexpected -> + ct:fail(Unexpected) + end. +server_msg(Server, ServerMsg) -> + receive + {Server, ServerMsg} -> + ok; + {Server, {error,closed}} -> + ct:print("server got close"), + ok; + {Server, {error, esslaccept}} -> + ct:print("server got econnaborted"), + ok; + Unexpected -> + ct:fail(Unexpected) + end. diff --git a/lib/ssl/test/ssl_cipher_SUITE.erl b/lib/ssl/test/ssl_cipher_SUITE.erl index ea1d9dc90c..9869812e6e 100644 --- a/lib/ssl/test/ssl_cipher_SUITE.erl +++ b/lib/ssl/test/ssl_cipher_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2012. All Rights Reserved. +%% Copyright Ericsson AB 2008-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -31,16 +31,18 @@ -define(TIMEOUT, 600000). -%% Test server callback functions %%-------------------------------------------------------------------- -%% Function: init_per_suite(Config) -> Config -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% Description: Initialization before the whole suite -%% -%% Note: This function is free to add any key/value pairs to the Config -%% variable, but should NOT alter/remove any existing entries. +%% Common Test interface functions ----------------------------------- %%-------------------------------------------------------------------- + +suite() -> [{ct_hooks,[ts_install_cth]}]. + +all() -> + [aes_decipher_good, aes_decipher_good_tls11, aes_decipher_fail, aes_decipher_fail_tls11]. + +groups() -> + []. + init_per_suite(Config) -> try crypto:start() of ok -> @@ -48,81 +50,30 @@ init_per_suite(Config) -> catch _:_ -> {skip, "Crypto did not start"} end. -%%-------------------------------------------------------------------- -%% Function: end_per_suite(Config) -> _ -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% Description: Cleanup after the whole suite -%%-------------------------------------------------------------------- + end_per_suite(_Config) -> ssl:stop(), application:stop(crypto). -%%-------------------------------------------------------------------- -%% Function: init_per_testcase(TestCase, Config) -> Config -%% Case - atom() -%% Name of the test case that is about to be run. -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% -%% Description: Initialization before each test case -%% -%% Note: This function is free to add any key/value pairs to the Config -%% variable, but should NOT alter/remove any existing entries. -%% Description: Initialization before each test case -%%-------------------------------------------------------------------- -init_per_testcase(_TestCase, Config0) -> - Config = lists:keydelete(watchdog, 1, Config0), - Dog = ssl_test_lib:timetrap(?TIMEOUT), - [{watchdog, Dog} | Config]. - -%%-------------------------------------------------------------------- -%% Function: end_per_testcase(TestCase, Config) -> _ -%% Case - atom() -%% Name of the test case that is about to be run. -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% Description: Cleanup after each test case -%%-------------------------------------------------------------------- -end_per_testcase(_TestCase, Config) -> - Dog = ?config(watchdog, Config), - case Dog of - undefined -> - ok; - _ -> - test_server:timetrap_cancel(Dog) - end. - -%%-------------------------------------------------------------------- -%% Function: all(Clause) -> TestCases -%% Clause - atom() - suite | doc -%% TestCases - [Case] -%% Case - atom() -%% Name of a test case. -%% Description: Returns a list of all test cases in this test suite -%%-------------------------------------------------------------------- -suite() -> [{ct_hooks,[ts_install_cth]}]. - -all() -> - [aes_decipher_good, aes_decipher_good_tls11, aes_decipher_fail, aes_decipher_fail_tls11]. - -groups() -> - []. - init_per_group(_GroupName, Config) -> Config. end_per_group(_GroupName, Config) -> Config. +init_per_testcase(_TestCase, Config0) -> + Config = lists:keydelete(watchdog, 1, Config0), + Dog = ct:timetrap(?TIMEOUT), + [{watchdog, Dog} | Config]. -%% Test cases starts here. -%%-------------------------------------------------------------------- -aes_decipher_good(doc) -> - ["Decipher a known cryptotext."]; +end_per_testcase(_TestCase, Config) -> + Config. -aes_decipher_good(suite) -> - []; +%%-------------------------------------------------------------------- +%% Test Cases -------------------------------------------------------- +%%-------------------------------------------------------------------- +aes_decipher_good() -> + [{doc,"Decipher a known cryptotext."}]. aes_decipher_good(Config) when is_list(Config) -> HashSz = 32, @@ -142,11 +93,8 @@ aes_decipher_good(Config) when is_list(Config) -> %%-------------------------------------------------------------------- -aes_decipher_good_tls11(doc) -> - ["Decipher a known TLS 1.1 cryptotext."]; - -aes_decipher_good_tls11(suite) -> - []; +aes_decipher_good_tls11() -> + [{doc,"Decipher a known TLS 1.1 cryptotext."}]. %% the fragment is actuall a TLS 1.1 record, with %% Version = TLS 1.1, we get the correct NextIV in #cipher_state @@ -169,11 +117,8 @@ aes_decipher_good_tls11(Config) when is_list(Config) -> %%-------------------------------------------------------------------- -aes_decipher_fail(doc) -> - ["Decipher a known cryptotext."]; - -aes_decipher_fail(suite) -> - []; +aes_decipher_fail() -> + [{doc,"Decipher a known cryptotext."}]. %% same as above, last byte of key replaced aes_decipher_fail(Config) when is_list(Config) -> @@ -196,11 +141,8 @@ aes_decipher_fail(Config) when is_list(Config) -> %%-------------------------------------------------------------------- -aes_decipher_fail_tls11(doc) -> - ["Decipher a known TLS 1.1 cryptotext."]; - -aes_decipher_fail_tls11(suite) -> - []; +aes_decipher_fail_tls11() -> + [{doc,"Decipher a known TLS 1.1 cryptotext."}]. %% same as above, last byte of key replaced %% stricter padding checks in TLS 1.1 mean we get an alert instead @@ -213,9 +155,11 @@ aes_decipher_fail_tls11(Config) when is_list(Config) -> 198,181,81,19,98,162,213,228,74,224,253,168,156,59,195,122, 108,101,107,242,20,15,169,150,163,107,101,94,93,104,241,165>>, Version = {3,2}, - #alert{level = ?FATAL, description = ?BAD_RECORD_MAC} = ssl_cipher:decipher(?AES, HashSz, CipherState, Fragment, Version), + #alert{level = ?FATAL, description = ?BAD_RECORD_MAC} = + ssl_cipher:decipher(?AES, HashSz, CipherState, Fragment, Version), Version1 = {3,3}, - #alert{level = ?FATAL, description = ?BAD_RECORD_MAC} = ssl_cipher:decipher(?AES, HashSz, CipherState, Fragment, Version1), + #alert{level = ?FATAL, description = ?BAD_RECORD_MAC} = + ssl_cipher:decipher(?AES, HashSz, CipherState, Fragment, Version1), ok. %%-------------------------------------------------------------------- diff --git a/lib/ssl/test/ssl_dist_SUITE.erl b/lib/ssl/test/ssl_dist_SUITE.erl index 818f7f1897..7bfd678f4b 100644 --- a/lib/ssl/test/ssl_dist_SUITE.erl +++ b/lib/ssl/test/ssl_dist_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2012. All Rights Reserved. +%% Copyright Ericsson AB 2007-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,7 +19,7 @@ -module(ssl_dist_SUITE). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). %% Note: This directive should only be used in test suites. -compile(export_all). @@ -35,7 +35,10 @@ nodename} ). -%% Test server callback functions +%%-------------------------------------------------------------------- +%% Common Test interface functions ----------------------------------- +%%-------------------------------------------------------------------- + suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -54,6 +57,7 @@ end_per_group(_GroupName, Config) -> init_per_suite(Config0) -> try crypto:start() of ok -> + %% Currently no ct function avilable for is_cover! case test_server:is_cover() of false -> Config = add_ssl_opts_config(Config0), @@ -98,11 +102,13 @@ common_end(_, Config) -> Dog = ?config(watchdog, Config), ?t:timetrap_cancel(Dog), ok. + %%-------------------------------------------------------------------- -%% Test cases starts here. +%% Test Cases -------------------------------------------------------- %%-------------------------------------------------------------------- -basic(doc) -> - ["Test that two nodes can connect via ssl distribution"]; + +basic() -> + [{doc,"Test that two nodes can connect via ssl distribution"}]. basic(Config) when is_list(Config) -> NH1 = start_ssl_node(Config), Node1 = NH1#node_handle.nodename, @@ -162,8 +168,8 @@ basic(Config) when is_list(Config) -> success(Config). %%-------------------------------------------------------------------- -payload(doc) -> - ["Test that send a lot of data between the ssl distributed noes"]; +payload() -> + [{doc,"Test that send a lot of data between the ssl distributed noes"}]. payload(Config) when is_list(Config) -> NH1 = start_ssl_node(Config), Node1 = NH1#node_handle.nodename, @@ -204,8 +210,8 @@ payload(Config) when is_list(Config) -> stop_ssl_node(NH2), success(Config). %%-------------------------------------------------------------------- -plain_options(doc) -> - ["Test specifying additional options"]; +plain_options() -> + [{doc,"Test specifying additional options"}]. plain_options(Config) when is_list(Config) -> DistOpts = "-ssl_dist_opt server_secure_renegotiate true " "client_secure_renegotiate true " @@ -228,8 +234,8 @@ plain_options(Config) when is_list(Config) -> stop_ssl_node(NH2), success(Config). %%-------------------------------------------------------------------- -plain_verify_options(doc) -> - ["Test specifying additional options"]; +plain_verify_options() -> + [{doc,"Test specifying additional options"}]. plain_verify_options(Config) when is_list(Config) -> DistOpts = "-ssl_dist_opt server_secure_renegotiate true " "client_secure_renegotiate true " @@ -251,7 +257,7 @@ plain_verify_options(Config) when is_list(Config) -> success(Config). %%-------------------------------------------------------------------- -%%% Internal functions +%%% Internal functions ----------------------------------------------- %%-------------------------------------------------------------------- %% ssl_node side api diff --git a/lib/ssl/test/ssl_handshake_SUITE.erl b/lib/ssl/test/ssl_handshake_SUITE.erl index 363a0be594..aff0e0fbbc 100644 --- a/lib/ssl/test/ssl_handshake_SUITE.erl +++ b/lib/ssl/test/ssl_handshake_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2012. All Rights Reserved. +%% Copyright Ericsson AB 2008-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -27,6 +27,9 @@ -include("ssl_internal.hrl"). -include("ssl_handshake.hrl"). +%%-------------------------------------------------------------------- +%% Common Test interface functions ----------------------------------- +%%-------------------------------------------------------------------- suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [ @@ -34,6 +37,9 @@ all() -> [ decode_single_hello_extension_correctly, decode_unknown_hello_extension_correctly]. +%%-------------------------------------------------------------------- +%% Test Cases -------------------------------------------------------- +%%-------------------------------------------------------------------- decode_hello_handshake(_Config) -> HelloPacket = <<16#02, 16#00, 16#00, 16#44, 16#03, 16#03, 16#4e, 16#7f, 16#c1, 16#03, 16#35, diff --git a/lib/ssl/test/ssl_npn_handshake_SUITE.erl b/lib/ssl/test/ssl_npn_handshake_SUITE.erl index 8597aa6740..4e848095a5 100644 --- a/lib/ssl/test/ssl_npn_handshake_SUITE.erl +++ b/lib/ssl/test/ssl_npn_handshake_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2012. All Rights Reserved. +%% Copyright Ericsson AB 2008-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -24,6 +24,10 @@ -compile(export_all). -include_lib("common_test/include/ct.hrl"). +%%-------------------------------------------------------------------- +%% Common Test interface functions ----------------------------------- +%%-------------------------------------------------------------------- + suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> @@ -68,7 +72,7 @@ init_per_suite(Config) -> Result = (catch make_certs:all(?config(data_dir, Config), ?config(priv_dir, Config))), - test_server:format("Make certs ~p~n", [Result]), + ct:print("Make certs ~p~n", [Result]), ssl_test_lib:cert_options(Config) catch _:_ -> {skip, "Crypto did not start"} @@ -94,12 +98,11 @@ init_per_group(GroupName, Config) -> Config end. - end_per_group(_GroupName, Config) -> Config. - -%% Test cases starts here. +%%-------------------------------------------------------------------- +%% Test Cases -------------------------------------------------------- %%-------------------------------------------------------------------- validate_empty_protocols_are_not_allowed(Config) when is_list(Config) -> @@ -229,9 +232,8 @@ npn_not_supported_server(Config) when is_list(Config)-> {error, {eoptions, {not_supported_in_sslv3, AdvProtocols}}} = ssl:listen(0, ServerOpts). %%-------------------------------------------------------------------- -%%% Internal functions +%% Internal functions ------------------------------------------------ %%-------------------------------------------------------------------- - run_npn_handshake(Config, ClientExtraOpts, ServerExtraOpts, ExpectedProtocol) -> Data = "hello world", @@ -257,13 +259,13 @@ run_npn_handshake(Config, ClientExtraOpts, ServerExtraOpts, ExpectedProtocol) -> assert_npn(Socket, Protocol) -> - test_server:format("Negotiated Protocol ~p, Expecting: ~p ~n", + ct:print("Negotiated Protocol ~p, Expecting: ~p ~n", [ssl:negotiated_next_protocol(Socket), Protocol]), Protocol = ssl:negotiated_next_protocol(Socket). assert_npn_and_renegotiate_and_send_data(Socket, Protocol, Data) -> assert_npn(Socket, Protocol), - test_server:format("Renegotiating ~n", []), + ct:print("Renegotiating ~n", []), ok = ssl:renegotiate(Socket), ssl:send(Socket, Data), assert_npn(Socket, Protocol), @@ -278,7 +280,7 @@ ssl_receive_and_assert_npn(Socket, Protocol, Data) -> ssl_receive(Socket, Data). ssl_send(Socket, Data) -> - test_server:format("Connection info: ~p~n", + ct:print("Connection info: ~p~n", [ssl:connection_info(Socket)]), ssl:send(Socket, Data). @@ -286,11 +288,11 @@ ssl_receive(Socket, Data) -> ssl_receive(Socket, Data, []). ssl_receive(Socket, Data, Buffer) -> - test_server:format("Connection info: ~p~n", + ct:print("Connection info: ~p~n", [ssl:connection_info(Socket)]), receive {ssl, Socket, MoreData} -> - test_server:format("Received ~p~n",[MoreData]), + ct:print("Received ~p~n",[MoreData]), NewBuffer = Buffer ++ MoreData, case NewBuffer of Data -> @@ -300,9 +302,9 @@ ssl_receive(Socket, Data, Buffer) -> ssl_receive(Socket, Data, NewBuffer) end; Other -> - test_server:fail({unexpected_message, Other}) + ct:fail({unexpected_message, Other}) after 4000 -> - test_server:fail({did_not_get, Data}) + ct:fail({did_not_get, Data}) end. diff --git a/lib/ssl/test/ssl_npn_hello_SUITE.erl b/lib/ssl/test/ssl_npn_hello_SUITE.erl index 5102c74e87..72768bcb55 100644 --- a/lib/ssl/test/ssl_npn_hello_SUITE.erl +++ b/lib/ssl/test/ssl_npn_hello_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2012. All Rights Reserved. +%% Copyright Ericsson AB 2008-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -27,6 +27,10 @@ -include("ssl_record.hrl"). -include_lib("common_test/include/ct.hrl"). +%%-------------------------------------------------------------------- +%% Common Test interface functions ----------------------------------- +%%-------------------------------------------------------------------- + suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> @@ -37,44 +41,26 @@ all() -> create_server_hello_with_advertised_protocols_test, create_server_hello_with_no_advertised_protocols_test]. - -create_client_handshake(Npn) -> - ssl_handshake:encode_handshake(#client_hello{ - client_version = {1, 2}, - random = <<1:256>>, - session_id = <<>>, - cipher_suites = "", - compression_methods = "", - next_protocol_negotiation = Npn, - renegotiation_info = #renegotiation_info{} - }, vsn). - +%%-------------------------------------------------------------------- +%% Test Cases -------------------------------------------------------- +%%-------------------------------------------------------------------- encode_and_decode_client_hello_test(_Config) -> HandShakeData = create_client_handshake(undefined), Version = ssl_record:protocol_version(ssl_record:highest_protocol_version([])), - {[{DecodedHandshakeMessage, _Raw}], _} = ssl_handshake:get_tls_handshake(Version, list_to_binary(HandShakeData), <<>>), + {[{DecodedHandshakeMessage, _Raw}], _} = + ssl_handshake:get_tls_handshake(Version, list_to_binary(HandShakeData), <<>>), NextProtocolNegotiation = DecodedHandshakeMessage#client_hello.next_protocol_negotiation, NextProtocolNegotiation = undefined. - +%%-------------------------------------------------------------------- encode_and_decode_npn_client_hello_test(_Config) -> HandShakeData = create_client_handshake(#next_protocol_negotiation{extension_data = <<>>}), Version = ssl_record:protocol_version(ssl_record:highest_protocol_version([])), - {[{DecodedHandshakeMessage, _Raw}], _} = ssl_handshake:get_tls_handshake(Version, list_to_binary(HandShakeData), <<>>), + {[{DecodedHandshakeMessage, _Raw}], _} = + ssl_handshake:get_tls_handshake(Version, list_to_binary(HandShakeData), <<>>), NextProtocolNegotiation = DecodedHandshakeMessage#client_hello.next_protocol_negotiation, NextProtocolNegotiation = #next_protocol_negotiation{extension_data = <<>>}. - -create_server_handshake(Npn) -> - ssl_handshake:encode_handshake(#server_hello{ - server_version = {1, 2}, - random = <<1:256>>, - session_id = <<>>, - cipher_suite = <<1,2>>, - compression_method = 1, - next_protocol_negotiation = Npn, - renegotiation_info = #renegotiation_info{} - }, vsn). - +%%-------------------------------------------------------------------- encode_and_decode_server_hello_test(_Config) -> HandShakeData = create_server_handshake(undefined), Version = ssl_record:protocol_version(ssl_record:highest_protocol_version([])), @@ -82,15 +68,51 @@ encode_and_decode_server_hello_test(_Config) -> ssl_handshake:get_tls_handshake(Version, list_to_binary(HandShakeData), <<>>), NextProtocolNegotiation = DecodedHandshakeMessage#server_hello.next_protocol_negotiation, NextProtocolNegotiation = undefined. - +%%-------------------------------------------------------------------- encode_and_decode_npn_server_hello_test(_Config) -> HandShakeData = create_server_handshake(#next_protocol_negotiation{extension_data = <<6, "spdy/2">>}), Version = ssl_record:protocol_version(ssl_record:highest_protocol_version([])), - {[{DecodedHandshakeMessage, _Raw}], _} = ssl_handshake:get_tls_handshake(Version, list_to_binary(HandShakeData), <<>>), + {[{DecodedHandshakeMessage, _Raw}], _} = + ssl_handshake:get_tls_handshake(Version, list_to_binary(HandShakeData), <<>>), NextProtocolNegotiation = DecodedHandshakeMessage#server_hello.next_protocol_negotiation, ct:print("~p ~n", [NextProtocolNegotiation]), NextProtocolNegotiation = #next_protocol_negotiation{extension_data = <<6, "spdy/2">>}. +%%-------------------------------------------------------------------- +create_server_hello_with_no_advertised_protocols_test(_Config) -> + Hello = ssl_handshake:server_hello(<<>>, {3, 0}, create_connection_states(), false, undefined), + undefined = Hello#server_hello.next_protocol_negotiation. +%%-------------------------------------------------------------------- +create_server_hello_with_advertised_protocols_test(_Config) -> + Hello = ssl_handshake:server_hello(<<>>, {3, 0}, create_connection_states(), + false, [<<"spdy/1">>, <<"http/1.0">>, <<"http/1.1">>]), + #next_protocol_negotiation{extension_data = <<6, "spdy/1", 8, "http/1.0", 8, "http/1.1">>} = + Hello#server_hello.next_protocol_negotiation. +%%-------------------------------------------------------------------- +%% Internal functions ------------------------------------------------ +%%-------------------------------------------------------------------- +create_client_handshake(Npn) -> + ssl_handshake:encode_handshake(#client_hello{ + client_version = {1, 2}, + random = <<1:256>>, + session_id = <<>>, + cipher_suites = "", + compression_methods = "", + next_protocol_negotiation = Npn, + renegotiation_info = #renegotiation_info{} + }, vsn). + +create_server_handshake(Npn) -> + ssl_handshake:encode_handshake(#server_hello{ + server_version = {1, 2}, + random = <<1:256>>, + session_id = <<>>, + cipher_suite = <<1,2>>, + compression_method = 1, + next_protocol_negotiation = Npn, + renegotiation_info = #renegotiation_info{} + }, vsn). + create_connection_states() -> #connection_states{ pending_read = #connection_state{ @@ -105,13 +127,3 @@ create_connection_states() -> secure_renegotiation = false } }. - -create_server_hello_with_no_advertised_protocols_test(_Config) -> - Hello = ssl_handshake:server_hello(<<>>, {3, 0}, create_connection_states(), false, undefined), - undefined = Hello#server_hello.next_protocol_negotiation. - -create_server_hello_with_advertised_protocols_test(_Config) -> - Hello = ssl_handshake:server_hello(<<>>, {3, 0}, create_connection_states(), - false, [<<"spdy/1">>, <<"http/1.0">>, <<"http/1.1">>]), - #next_protocol_negotiation{extension_data = <<6, "spdy/1", 8, "http/1.0", 8, "http/1.1">>} = - Hello#server_hello.next_protocol_negotiation. diff --git a/lib/ssl/test/ssl_packet_SUITE.erl b/lib/ssl/test/ssl_packet_SUITE.erl index 8ce80cb725..158c40e372 100644 --- a/lib/ssl/test/ssl_packet_SUITE.erl +++ b/lib/ssl/test/ssl_packet_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2012. All Rights Reserved. +%% Copyright Ericsson AB 2008-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -41,84 +41,10 @@ -define(MANY, 1000). -define(SOME, 50). - -%% Test server callback functions %%-------------------------------------------------------------------- -%% Function: init_per_suite(Config) -> Config -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% Description: Initialization before the whole suite -%% -%% Note: This function is free to add any key/value pairs to the Config -%% variable, but should NOT alter/remove any existing entries. +%% Common Test interface functions ----------------------------------- %%-------------------------------------------------------------------- -init_per_suite(Config) -> - catch crypto:stop(), - try crypto:start() of - ok -> - application:start(public_key), - ssl:start(), - Result = - (catch make_certs:all(?config(data_dir, Config), - ?config(priv_dir, Config))), - test_server:format("Make certs ~p~n", [Result]), - ssl_test_lib:cert_options(Config) - catch _:_ -> - {skip, "Crypto did not start"} - end. -%%-------------------------------------------------------------------- -%% Function: end_per_suite(Config) -> _ -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% Description: Cleanup after the whole suite -%%-------------------------------------------------------------------- -end_per_suite(_Config) -> - ssl:stop(), - application:stop(crypto). -%%-------------------------------------------------------------------- -%% Function: init_per_testcase(TestCase, Config) -> Config -%% Case - atom() -%% Name of the test case that is about to be run. -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% -%% Description: Initialization before each test case -%% -%% Note: This function is free to add any key/value pairs to the Config -%% variable, but should NOT alter/remove any existing entries. -%% Description: Initialization before each test case -%%-------------------------------------------------------------------- -init_per_testcase(_TestCase, Config0) -> - Config = lists:keydelete(watchdog, 1, Config0), - Dog = ssl_test_lib:timetrap(?TIMEOUT), - [{watchdog, Dog} | Config]. - -%%-------------------------------------------------------------------- -%% Function: end_per_testcase(TestCase, Config) -> _ -%% Case - atom() -%% Name of the test case that is about to be run. -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% Description: Cleanup after each test case -%%-------------------------------------------------------------------- -end_per_testcase(_TestCase, Config) -> - Dog = ?config(watchdog, Config), - case Dog of - undefined -> - ok; - _ -> - test_server:timetrap_cancel(Dog) - end. - -%%-------------------------------------------------------------------- -%% Function: all(Clause) -> TestCases -%% Clause - atom() - suite | doc -%% TestCases - [Case] -%% Case - atom() -%% Name of a test case. -%% Description: Returns a list of all test cases in this test suite -%%-------------------------------------------------------------------- suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> @@ -129,12 +55,6 @@ all() -> {group, 'sslv3'} ]. -groups() -> - [{'tlsv1.2', [], packet_tests()}, - {'tlsv1.1', [], packet_tests()}, - {'tlsv1', [], packet_tests()}, - {'sslv3', [], packet_tests()}]. - packet_tests() -> active_packet_tests() ++ active_once_packet_tests() ++ passive_packet_tests() ++ [packet_send_to_large, @@ -208,6 +128,24 @@ active_packet_tests() -> header_decode_two_bytes_one_sent_active ]. +init_per_suite(Config) -> + catch crypto:stop(), + try crypto:start() of + ok -> + application:start(public_key), + ssl:start(), + Result = + (catch make_certs:all(?config(data_dir, Config), + ?config(priv_dir, Config))), + ct:print("Make certs ~p~n", [Result]), + ssl_test_lib:cert_options(Config) + catch _:_ -> + {skip, "Crypto did not start"} + end. + +end_per_suite(_Config) -> + ssl:stop(), + application:stop(crypto). init_per_group(GroupName, Config) -> case ssl_test_lib:is_tls_version(GroupName) of @@ -228,1032 +166,262 @@ init_per_group(GroupName, Config) -> end_per_group(_GroupName, Config) -> Config. +init_per_testcase(_TestCase, Config0) -> + Config = lists:keydelete(watchdog, 1, Config0), + Dog = ct:timetrap(?TIMEOUT), + [{watchdog, Dog} | Config]. -%% Test cases starts here. -%%-------------------------------------------------------------------- -packet_raw_passive_many_small(doc) -> - ["Test packet option {packet, raw} in passive mode."]; - -packet_raw_passive_many_small(suite) -> - []; -packet_raw_passive_many_small(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - - Data = "Packet option is {packet, raw}", +end_per_testcase(_TestCase, Config) -> + Config. - Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send_raw ,[Data, ?MANY]}}, - {options, ServerOpts}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, passive_raw, [Data, ?MANY]}}, - {options, - [{active, false}, - {packet, raw} | - ClientOpts]}]), +%%-------------------------------------------------------------------- +%% Test Cases -------------------------------------------------------- +%%-------------------------------------------------------------------- - ssl_test_lib:check_result(Client, ok), +packet_raw_passive_many_small() -> + [{doc,"Test packet option {packet, raw} in passive mode."}]. - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). +packet_raw_passive_many_small(Config) when is_list(Config) -> + Data = "Packet option is {packet, raw}", + packet(Config, Data, send, passive_recv_packet, ?MANY, raw, false). %%-------------------------------------------------------------------- -packet_raw_passive_some_big(doc) -> - ["Test packet option {packet, raw} in passive mode."]; - -packet_raw_passive_some_big(suite) -> - []; - -packet_raw_passive_some_big(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), +packet_raw_passive_some_big() -> + [{doc,"Test packet option {packet, raw} in passive mode."}]. +packet_raw_passive_some_big(Config) when is_list(Config) -> Data = lists:append(lists:duplicate(100, "1234567890")), - - Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send_raw ,[Data, ?SOME]}}, - {options, ServerOpts}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, passive_raw, [Data, ?SOME]}}, - {options, - [{active, false}, - {packet, raw} | - ClientOpts]}]), - - ssl_test_lib:check_result(Client, ok), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). - + packet(Config, Data, send, passive_recv_packet, ?SOME, raw, false). %%-------------------------------------------------------------------- -packet_0_passive_many_small(doc) -> - ["Test packet option {packet, 0} in passive mode."]; - -packet_0_passive_many_small(suite) -> - []; - -packet_0_passive_many_small(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), +packet_0_passive_many_small() -> + [{doc,"Test packet option {packet, 0} in passive mode."}]. +packet_0_passive_many_small(Config) when is_list(Config) -> Data = "Packet option is {packet, 0}, equivalent to packet raw.", - - Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send_raw ,[Data, ?MANY]}}, - {options, ServerOpts}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, passive_raw, [Data, ?MANY]}}, - {options, [{active, false}, - {packet, 0} | - ClientOpts]}]), - - ssl_test_lib:check_result(Client, ok), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). + packet(Config, Data, send, passive_recv_packet, ?MANY, 0, false). %%-------------------------------------------------------------------- -packet_0_passive_some_big(doc) -> - ["Test packet option {packet, 0} in passive mode."]; - -packet_0_passive_some_big(suite) -> - []; - -packet_0_passive_some_big(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), +packet_0_passive_some_big() -> + [{doc,"Test packet option {packet, 0} in passive mode."}]. +packet_0_passive_some_big(Config) when is_list(Config) -> Data = lists:append(lists:duplicate(100, "1234567890")), - - Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send_raw ,[Data, ?SOME]}}, - {options, ServerOpts}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, passive_raw, [Data, ?SOME]}}, - {options, [{active, false}, - {packet, 0} | - ClientOpts]}]), - - ssl_test_lib:check_result(Client, ok), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). + packet(Config, Data, send, passive_recv_packet, ?SOME, 0, false). %%-------------------------------------------------------------------- -packet_1_passive_many_small(doc) -> - ["Test packet option {packet, 1} in passive mode."]; - -packet_1_passive_many_small(suite) -> - []; - -packet_1_passive_many_small(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), +packet_1_passive_many_small() -> + [{doc,"Test packet option {packet, 1} in passive mode."}]. +packet_1_passive_many_small(Config) when is_list(Config) -> Data = "Packet option is {packet, 1}", - - Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send, [Data, ?MANY]}}, - {options, [{packet, 1}|ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, passive_recv_packet, - [Data, ?MANY]}}, - {options, [{active, false}, - {packet, 1} | - ClientOpts]}]), - - ssl_test_lib:check_result(Client, ok), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). + packet(Config, Data, send, passive_recv_packet, ?MANY, 1, false). %%-------------------------------------------------------------------- -packet_1_passive_some_big(doc) -> - ["Test packet option {packet, 1} in passive mode."]; - -packet_1_passive_some_big(suite) -> - []; - -packet_1_passive_some_big(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), +packet_1_passive_some_big() -> + [{doc,"Test packet option {packet, 1} in passive mode."}]. +packet_1_passive_some_big(Config) when is_list(Config) -> Data = lists:append(lists:duplicate(255, "1")), - - Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send, [Data, ?SOME]}}, - {options, [{packet, 1}|ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, passive_recv_packet, - [Data, ?SOME]}}, - {options, [{active, false}, - {packet, 1} | - ClientOpts]}]), - - ssl_test_lib:check_result(Client, ok), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). + packet(Config, Data, send, passive_recv_packet, ?SOME, 1, false). %%-------------------------------------------------------------------- -packet_2_passive_many_small(doc) -> - ["Test packet option {packet, 2} in passive mode"]; - -packet_2_passive_many_small(suite) -> - []; - -packet_2_passive_many_small(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), +packet_2_passive_many_small() -> + [{doc,"Test packet option {packet, 2} in passive mode"}]. +packet_2_passive_many_small(Config) when is_list(Config) -> Data = "Packet option is {packet, 2}", - - Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send, [Data, ?MANY]}}, - {options, [{packet, 2}|ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, passive_recv_packet, - [Data, ?MANY]}}, - {options, [{active, false}, - {packet, 2} | - ClientOpts]}]), - - ssl_test_lib:check_result(Client, ok), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). + packet(Config, Data, send, passive_recv_packet, ?MANY, 2, false). %%-------------------------------------------------------------------- -packet_2_passive_some_big(doc) -> - ["Test packet option {packet, 2} in passive mode"]; - -packet_2_passive_some_big(suite) -> - []; - -packet_2_passive_some_big(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), +packet_2_passive_some_big() -> + [{doc,"Test packet option {packet, 2} in passive mode"}]. +packet_2_passive_some_big(Config) when is_list(Config) -> Data = lists:append(lists:duplicate(100, "1234567890")), - - Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send, [Data, ?SOME]}}, - {options, [{packet, 2}|ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, passive_recv_packet, - [Data, ?SOME]}}, - {options, [{active, false}, - {packet, 2} | - ClientOpts]}]), - - ssl_test_lib:check_result(Client, ok), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). + packet(Config, Data, send, passive_recv_packet, ?SOME, 2, false). %%-------------------------------------------------------------------- -packet_4_passive_many_small(doc) -> - ["Test packet option {packet, 4} in passive mode"]; - -packet_4_passive_many_small(suite) -> - []; - -packet_4_passive_many_small(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), +packet_4_passive_many_small() -> + [{doc,"Test packet option {packet, 4} in passive mode"}]. +packet_4_passive_many_small(Config) when is_list(Config) -> Data = "Packet option is {packet, 4}", - - Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, - {from, self()}, - {mfa, - {?MODULE, send, [Data, ?MANY]}}, - {options, [{packet, 4}|ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, passive_recv_packet, - [Data, ?MANY]}}, - {options, [{active, false}, - {packet, 4} | - ClientOpts]}]), - - ssl_test_lib:check_result(Client, ok), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). + packet(Config, Data, send, passive_recv_packet, ?MANY, 4, false). %%-------------------------------------------------------------------- -packet_4_passive_some_big(doc) -> - ["Test packet option {packet, 4} in passive mode"]; - -packet_4_passive_some_big(suite) -> - []; - -packet_4_passive_some_big(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), +packet_4_passive_some_big() -> + [{doc,"Test packet option {packet, 4} in passive mode"}]. +packet_4_passive_some_big(Config) when is_list(Config) -> Data = lists:append(lists:duplicate(100, "1234567890")), - - Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send, [Data, ?SOME]}}, - {options, [{packet, 4}|ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, passive_recv_packet, - [Data, ?SOME]}}, - {options, [{active, false}, - {packet, 4} | - ClientOpts]}]), - - ssl_test_lib:check_result(Client, ok), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). - + packet(Config, Data, send, passive_recv_packet, ?SOME, 4, false). %%-------------------------------------------------------------------- -packet_raw_active_once_many_small(doc) -> - ["Test packet option {packet, raw} in active once mode."]; - -packet_raw_active_once_many_small(suite) -> - []; - -packet_raw_active_once_many_small(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), +packet_raw_active_once_many_small() -> + [{doc,"Test packet option {packet, raw} in active once mode."}]. +packet_raw_active_once_many_small(Config) when is_list(Config) -> Data = "Packet option is {packet, raw}", - - Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send_raw ,[Data, ?MANY]}}, - {options, ServerOpts}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, active_once_raw, - [Data, ?MANY]}}, - {options, [{active, once}, - {packet, raw} | - ClientOpts]}]), - - ssl_test_lib:check_result(Client, ok), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). + packet(Config, Data, send_raw, active_once_raw, ?MANY, raw, once). %%-------------------------------------------------------------------- -packet_raw_active_once_some_big(doc) -> - ["Test packet option {packet, raw} in active once mode."]; - -packet_raw_active_once_some_big(suite) -> - []; - -packet_raw_active_once_some_big(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), +packet_raw_active_once_some_big() -> + [{doc,"Test packet option {packet, raw} in active once mode."}]. +packet_raw_active_once_some_big(Config) when is_list(Config) -> Data = lists:append(lists:duplicate(100, "1234567890")), - - Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send_raw ,[Data, ?SOME]}}, - {options, ServerOpts}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, active_once_raw, - [Data, ?SOME]}}, - {options, [{active, once}, - {packet, raw} | - ClientOpts]}]), - - ssl_test_lib:check_result(Client, ok), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). + packet(Config, Data, send_raw, active_once_raw, ?SOME, raw, once). %%-------------------------------------------------------------------- -packet_0_active_once_many_small(doc) -> - ["Test packet option {packet, 0} in active once mode."]; - -packet_0_active_once_many_small(suite) -> - []; - -packet_0_active_once_many_small(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), +packet_0_active_once_many_small() -> + [{doc,"Test packet option {packet, 0} in active once mode."}]. +packet_0_active_once_many_small(Config) when is_list(Config) -> Data = "Packet option is {packet, 0}", - - Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send_raw ,[Data, ?MANY]}}, - {options, ServerOpts}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, - {?MODULE, active_once_raw, - [Data, ?MANY]}}, - {options, [{active, once}, - {packet, 0} | - ClientOpts]}]), - - ssl_test_lib:check_result(Client, ok), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). - + packet(Config, Data, send_raw, active_once_raw, ?MANY, 0, once). %%-------------------------------------------------------------------- -packet_0_active_once_some_big(doc) -> - ["Test packet option {packet, 0} in active once mode."]; - -packet_0_active_once_some_big(suite) -> - []; - -packet_0_active_once_some_big(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), +packet_0_active_once_some_big() -> + [{doc,"Test packet option {packet, 0} in active once mode."}]. +packet_0_active_once_some_big(Config) when is_list(Config) -> Data = lists:append(lists:duplicate(100, "1234567890")), - - Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send_raw , - [Data, ?SOME]}}, - {options, ServerOpts}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, - {?MODULE, active_once_raw, - [Data, ?SOME]}}, - {options, [{active, once}, - {packet, 0} | - ClientOpts]}]), - - ssl_test_lib:check_result(Client, ok), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). + packet(Config, Data, send_raw, active_once_raw, ?SOME, 0, once). %%-------------------------------------------------------------------- -packet_1_active_once_many_small(doc) -> - ["Test packet option {packet, 1} in active once mode."]; - -packet_1_active_once_many_small(suite) -> - []; - -packet_1_active_once_many_small(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), +packet_1_active_once_many_small() -> + [{doc,"Test packet option {packet, 1} in active once mode."}]. +packet_1_active_once_many_small(Config) when is_list(Config) -> Data = "Packet option is {packet, 1}", - - Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send, [Data, ?MANY]}}, - {options, [{packet, 1}|ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, - {?MODULE, - active_once_packet, - [Data, ?MANY]}}, - {options, [{active, once}, - {packet, 1} | - ClientOpts]}]), - - ssl_test_lib:check_result(Client, ok), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). + packet(Config, Data, send_raw, active_once_raw, ?MANY, 1, once). %%-------------------------------------------------------------------- -packet_1_active_once_some_big(doc) -> - ["Test packet option {packet, 1} in active once mode."]; - -packet_1_active_once_some_big(suite) -> - []; - -packet_1_active_once_some_big(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), +packet_1_active_once_some_big() -> + [{doc,"Test packet option {packet, 1} in active once mode."}]. +packet_1_active_once_some_big(Config) when is_list(Config) -> Data = lists:append(lists:duplicate(255, "1")), + packet(Config, Data, send_raw, active_once_raw, ?SOME, 1, once). - Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send, [Data, ?SOME]}}, - {options, [{packet, 1}|ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, - {?MODULE, - active_once_packet, - [Data, ?SOME]}}, - {options, [{active, once}, - {packet, 1} | - ClientOpts]}]), - - ssl_test_lib:check_result(Client, ok), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). %%-------------------------------------------------------------------- -packet_2_active_once_many_small(doc) -> - ["Test packet option {packet, 2} in active once mode"]; - -packet_2_active_once_many_small(suite) -> - []; - -packet_2_active_once_many_small(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), +packet_2_active_once_many_small() -> + [{doc,"Test packet option {packet, 2} in active once mode"}]. +packet_2_active_once_many_small(Config) when is_list(Config) -> Data = "Packet option is {packet, 2}", - - Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send, [Data, ?MANY]}}, - {options, [{packet, 2}|ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, - {?MODULE, - active_once_packet, - [Data, ?MANY]}}, - {options, [{active, once}, - {packet, 2} | - ClientOpts]}]), - - ssl_test_lib:check_result(Client, ok), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). - + packet(Config, Data, send_raw, active_once_raw, ?MANY, 2, once). %%-------------------------------------------------------------------- -packet_2_active_once_some_big(doc) -> - ["Test packet option {packet, 2} in active once mode"]; - -packet_2_active_once_some_big(suite) -> - []; - -packet_2_active_once_some_big(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), +packet_2_active_once_some_big() -> + [{doc,"Test packet option {packet, 2} in active once mode"}]. +packet_2_active_once_some_big(Config) when is_list(Config) -> Data = lists:append(lists:duplicate(100, "1234567890")), - - Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send, [Data, ?SOME]}}, - {options, [{packet, 2}|ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, - {?MODULE, - active_once_packet, - [Data, ?SOME]}}, - {options, [{active, once}, - {packet, 2} | - ClientOpts]}]), - - ssl_test_lib:check_result(Client, ok), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). + packet(Config, Data, send_raw, active_once_raw, ?SOME, 2, once). %%-------------------------------------------------------------------- -packet_4_active_once_many_small(doc) -> - ["Test packet option {packet, 4} in active once mode"]; - -packet_4_active_once_many_small(suite) -> - []; - -packet_4_active_once_many_small(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), +packet_4_active_once_many_small() -> + [{doc,"Test packet option {packet, 4} in active once mode"}]. +packet_4_active_once_many_small(Config) when is_list(Config) -> Data = "Packet option is {packet, 4}", - - Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send, [Data, ?MANY]}}, - {options, [{packet, 4}|ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, - {?MODULE, - active_once_packet, - [Data, ?MANY]}}, - {options, [{active, once}, - {packet, 4} | - ClientOpts]}]), - - ssl_test_lib:check_result(Client, ok), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). + packet(Config, Data, send_raw, active_once_raw, ?MANY, 4, once). %%-------------------------------------------------------------------- -packet_4_active_once_some_big(doc) -> - ["Test packet option {packet, 4} in active once mode"]; - -packet_4_active_once_some_big(suite) -> - []; - -packet_4_active_once_some_big(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), +packet_4_active_once_some_big() -> + [{doc,"Test packet option {packet, 4} in active once mode"}]. +packet_4_active_once_some_big(Config) when is_list(Config) -> Data = lists:append(lists:duplicate(100, "1234567890")), - - Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send, [Data, ?SOME]}}, - {options, [{packet, 4}|ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, - {?MODULE, - active_once_packet, - [Data, ?SOME]}}, - {options, [{active, once}, - {packet, 4} | - ClientOpts]}]), - - ssl_test_lib:check_result(Client, ok), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). + packet(Config, Data, send_raw, active_once_raw, ?SOME, 4, once). %%-------------------------------------------------------------------- -packet_raw_active_many_small(doc) -> - ["Test packet option {packet, raw} in active mode."]; - -packet_raw_active_many_small(suite) -> - []; +packet_raw_active_many_small() -> + [{doc,"Test packet option {packet, raw} in active mode."}]. packet_raw_active_many_small(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Data = "Packet option is {packet, raw}", - - Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send_raw ,[Data, ?MANY]}}, - {options, ServerOpts}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, active_raw, - [Data, ?MANY]}}, - {options, [{active, true}, - {packet, raw} | - ClientOpts]}]), - - ssl_test_lib:check_result(Client, ok), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). - + packet(Config, Data, send_raw, active_raw, ?MANY, raw, active). %%-------------------------------------------------------------------- -packet_raw_active_some_big(doc) -> - ["Test packet option {packet, raw} in active mode."]; - -packet_raw_active_some_big(suite) -> - []; +packet_raw_active_some_big() -> + [{doc,"Test packet option {packet, raw} in active mode."}]. packet_raw_active_some_big(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), - Data = lists:append(lists:duplicate(100, "1234567890")), - - Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send_raw ,[Data, ?SOME]}}, - {options, ServerOpts}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {?MODULE, active_raw, [Data, ?SOME]}}, - {options, [{active, true}, - {packet, raw} | - ClientOpts]}]), - - ssl_test_lib:check_result(Client, ok), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). + packet(Config, Data, send_raw, active_raw, ?SOME, raw, active). %%-------------------------------------------------------------------- -packet_0_active_many_small(doc) -> - ["Test packet option {packet, 0} in active mode."]; - -packet_0_active_many_small(suite) -> - []; - -packet_0_active_many_small(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), +packet_0_active_many_small() -> + [{doc,"Test packet option {packet, 0} in active mode."}]. +packet_0_active_many_small(Config) when is_list(Config) -> Data = "Packet option is {packet, 0}", - - Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send_raw ,[Data, ?MANY]}}, - {options, ServerOpts}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, - {?MODULE, active_raw, - [Data, ?MANY]}}, - {options, [{active, true}, - {packet, 0} | - ClientOpts]}]), - - ssl_test_lib:check_result(Client, ok), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). + packet(Config, Data, send_raw, active_raw, ?MANY, 0, active). %%-------------------------------------------------------------------- -packet_0_active_some_big(doc) -> - ["Test packet option {packet, 0} in active mode."]; - -packet_0_active_some_big(suite) -> - []; - -packet_0_active_some_big(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), +packet_0_active_some_big() -> + [{doc,"Test packet option {packet, 0} in active mode."}]. +packet_0_active_some_big(Config) when is_list(Config) -> Data = lists:append(lists:duplicate(100, "1234567890")), - - Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send_raw ,[Data, ?SOME]}}, - {options, ServerOpts}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, - {?MODULE, active_raw, - [Data, ?SOME]}}, - {options, [{active, true}, - {packet, 0} | - ClientOpts]}]), - - ssl_test_lib:check_result(Client, ok), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). - + packet(Config, Data, send_raw, active_raw, ?SOME, 0, active). %%-------------------------------------------------------------------- -packet_1_active_many_small(doc) -> - ["Test packet option {packet, 1} in active mode."]; - -packet_1_active_many_small(suite) -> - []; - -packet_1_active_many_small(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), +packet_1_active_many_small() -> + [{doc,"Test packet option {packet, 1} in active mode."}]. +packet_1_active_many_small(Config) when is_list(Config) -> Data = "Packet option is {packet, 1}", - - Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send, [Data, ?MANY]}}, - {options, [{packet, 1}|ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, - {?MODULE, - active_packet, [Data, ?MANY]}}, - {options, [{active, true}, - {packet, 1} | - ClientOpts]}]), - - ssl_test_lib:check_result(Client, ok), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). + packet(Config, Data, send_raw, active_raw, ?MANY, 1, active). %%-------------------------------------------------------------------- -packet_1_active_some_big(doc) -> - ["Test packet option {packet, 1} in active mode."]; - -packet_1_active_some_big(suite) -> - []; - -packet_1_active_some_big(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), +packet_1_active_some_big() -> + [{doc,"Test packet option {packet, 1} in active mode."}]. +packet_1_active_some_big(Config) when is_list(Config) -> Data = lists:append(lists:duplicate(255, "1")), - - Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send, [Data, ?SOME]}}, - {options, [{packet, 1}|ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, - {?MODULE, - active_packet, [Data, ?SOME]}}, - {options, [{active, true}, - {packet, 1} | - ClientOpts]}]), - - ssl_test_lib:check_result(Client, ok), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). + packet(Config, Data, send_raw, active_raw, ?SOME, 1, active). %%-------------------------------------------------------------------- -packet_2_active_many_small(doc) -> - ["Test packet option {packet, 2} in active mode"]; - -packet_2_active_many_small(suite) -> - []; - -packet_2_active_many_small(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), +packet_2_active_many_small() -> + [{doc,"Test packet option {packet, 2} in active mode"}]. +packet_2_active_many_small(Config) when is_list(Config) -> Data = "Packet option is {packet, 2}", - - Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send, [Data, ?MANY]}}, - {options, [{packet, 2}|ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, - {?MODULE, - active_packet, [Data, ?MANY]}}, - {options, [{active, true}, - {packet, 2} | - ClientOpts]}]), - - ssl_test_lib:check_result(Client, ok), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). + packet(Config, Data, send_raw, active_raw, ?MANY, 2, active). %%-------------------------------------------------------------------- -packet_2_active_some_big(doc) -> - ["Test packet option {packet, 2} in active mode"]; - -packet_2_active_some_big(suite) -> - []; - -packet_2_active_some_big(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), +packet_2_active_some_big() -> + [{doc,"Test packet option {packet, 2} in active mode"}]. +packet_2_active_some_big(Config) when is_list(Config) -> Data = lists:append(lists:duplicate(100, "1234567890")), - - Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send, [Data, ?SOME]}}, - {options, [{packet, 2}|ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, - {?MODULE, - active_packet, [Data, ?SOME]}}, - {options, [{active, true}, - {packet, 2} | - ClientOpts]}]), - - ssl_test_lib:check_result(Client, ok), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). + packet(Config, Data, send_raw, active_raw, ?SOME, 2, active). %%-------------------------------------------------------------------- -packet_4_active_many_small(doc) -> - ["Test packet option {packet, 4} in active mode"]; - -packet_4_active_many_small(suite) -> - []; - -packet_4_active_many_small(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), +packet_4_active_many_small() -> + [{doc,"Test packet option {packet, 4} in active mode"}]. +packet_4_active_many_small(Config) when is_list(Config) -> Data = "Packet option is {packet, 4}", - - Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send, [Data, ?MANY]}}, - {options, [{packet, 4}|ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, - {?MODULE, - active_packet, [Data, ?MANY]}}, - {options, [{active, true}, - {packet, 4} | - ClientOpts]}]), - - ssl_test_lib:check_result(Client, ok), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). - + packet(Config, Data, send_raw, active_raw, ?MANY, 4, active). %%-------------------------------------------------------------------- -packet_4_active_some_big(doc) -> - ["Test packet option {packet, 4} in active mode"]; - -packet_4_active_some_big(suite) -> - []; - -packet_4_active_some_big(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), - ServerOpts = ?config(server_opts, Config), - {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), +packet_4_active_some_big() -> + [{doc,"Test packet option {packet, 4} in active mode"}]. +packet_4_active_some_big(Config) when is_list(Config) -> Data = lists:append(lists:duplicate(100, "1234567890")), - - Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, - {from, self()}, - {mfa, {?MODULE, send, [Data, ?SOME]}}, - {options, [{packet, 4} | ServerOpts]}]), - Port = ssl_test_lib:inet_port(Server), - Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, - {?MODULE, - active_packet, [Data, ?SOME]}}, - {options, [{active, true}, - {packet, 4} | - ClientOpts]}]), - - ssl_test_lib:check_result(Client, ok), - - ssl_test_lib:close(Server), - ssl_test_lib:close(Client). - + packet(Config, Data, send_raw, active_raw, ?SOME, 4, active). %%-------------------------------------------------------------------- -packet_send_to_large(doc) -> - ["Test setting the packet option {packet, 2} on the send side"]; - -packet_send_to_large(suite) -> []; +packet_send_to_large() -> + [{doc,"Test setting the packet option {packet, 2} on the send side"}]. packet_send_to_large(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -1279,16 +447,9 @@ packet_send_to_large(Config) when is_list(Config) -> ssl_test_lib:close(Server), ssl_test_lib:close(Client). - - - - %%-------------------------------------------------------------------- -packet_wait_active(doc) -> - ["Test waiting when complete packages have not arrived"]; - -packet_wait_active(suite) -> - []; +packet_wait_active() -> + [{doc,"Test waiting when complete packages have not arrived"}]. packet_wait_active(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -1320,11 +481,8 @@ packet_wait_active(Config) when is_list(Config) -> %%-------------------------------------------------------------------- -packet_wait_passive(doc) -> - ["Test waiting when complete packages have not arrived"]; - -packet_wait_passive(suite) -> - []; +packet_wait_passive() -> + [{doc,"Test waiting when complete packages have not arrived"}]. packet_wait_passive(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -1353,10 +511,8 @@ packet_wait_passive(Config) when is_list(Config) -> ssl_test_lib:close(Server), ssl_test_lib:close(Client). %%-------------------------------------------------------------------- -packet_baddata_active(doc) -> - ["Test that if a bad packet arrives error msg is sent and socket is closed"]; -packet_baddata_active(suite) -> - []; +packet_baddata_active() -> + [{doc,"Test that if a bad packet arrives error msg is sent and socket is closed"}]. packet_baddata_active(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -1381,18 +537,15 @@ packet_baddata_active(Config) when is_list(Config) -> {Client, {other, {ssl_error, _Socket, {invalid_packet, _}},{error,closed},1}} -> ok; Unexpected -> - test_server:fail({unexpected, Unexpected}) + ct:fail({unexpected, Unexpected}) end, ssl_test_lib:close(Server), ssl_test_lib:close(Client). %%-------------------------------------------------------------------- -packet_baddata_passive(doc) -> - ["Test that if a bad packet arrives error msg is sent and socket is closed"]; - -packet_baddata_passive(suite) -> - []; +packet_baddata_passive() -> + [{doc,"Test that if a bad packet arrives error msg is sent and socket is closed"}]. packet_baddata_passive(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -1418,19 +571,16 @@ packet_baddata_passive(Config) when is_list(Config) -> receive {Client, {other, {error, {invalid_packet, _}},{error,closed}, 1}} -> ok; Unexpected -> - test_server:fail({unexpected, Unexpected}) + ct:fail({unexpected, Unexpected}) end, ssl_test_lib:close(Server), ssl_test_lib:close(Client). %%-------------------------------------------------------------------- -packet_size_active(doc) -> - ["Test that if a packet of size larger than - packet_size arrives error msg is sent and socket is closed"]; - -packet_size_active(suite) -> - []; +packet_size_active() -> + [{doc,"Test that if a packet of size larger than + packet_size arrives error msg is sent and socket is closed"}]. packet_size_active(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -1455,17 +605,16 @@ packet_size_active(Config) when is_list(Config) -> {Client, {other, {ssl_error, _Socket, {invalid_packet, _}},{error,closed},1}} -> ok; Unexpected -> - test_server:fail({unexpected, Unexpected}) + ct:fail({unexpected, Unexpected}) end, ssl_test_lib:close(Server), ssl_test_lib:close(Client). %%-------------------------------------------------------------------- -packet_size_passive(doc) -> - ["Test that if a packet of size larger - than packet_size arrives error msg is sent and socket is closed"]; -packet_size_passive(suite) -> []; +packet_size_passive() -> + [{doc, "Test that if a packet of size larger + than packet_size arrives error msg is sent and socket is closed"}]. packet_size_passive(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -1490,17 +639,15 @@ packet_size_passive(Config) when is_list(Config) -> receive {Client, {other, {error, {invalid_packet, _}},{error,closed},1}} -> ok; Unexpected -> - test_server:fail({unexpected, Unexpected}) + ct:fail({unexpected, Unexpected}) end, ssl_test_lib:close(Server), ssl_test_lib:close(Client). %%-------------------------------------------------------------------- -packet_cdr_decode(doc) -> - ["Test setting the packet option {packet, cdr}, {mode, binary}"]; -packet_cdr_decode(suite) -> - []; +packet_cdr_decode() -> + [{doc,"Test setting the packet option {packet, cdr}, {mode, binary}"}]. packet_cdr_decode(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -1532,10 +679,8 @@ packet_cdr_decode(Config) when is_list(Config) -> ssl_test_lib:close(Client). %%-------------------------------------------------------------------- -packet_cdr_decode_list(doc) -> - ["Test setting the packet option {packet, cdr} {mode, list}"]; -packet_cdr_decode_list(suite) -> - []; +packet_cdr_decode_list() -> + [{doc,"Test setting the packet option {packet, cdr} {mode, list}"}]. packet_cdr_decode_list(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -1567,11 +712,9 @@ packet_cdr_decode_list(Config) when is_list(Config) -> ssl_test_lib:close(Client). %%-------------------------------------------------------------------- -packet_http_decode(doc) -> - ["Test setting the packet option {packet, http} {mode, binary} " - "(Body will be binary http strings are lists)"]; -packet_http_decode(suite) -> - []; +packet_http_decode() -> + [{doc, "Test setting the packet option {packet, http} {mode, binary} " + "(Body will be binary http strings are lists)"}]. packet_http_decode(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -1652,11 +795,9 @@ client_http_decode(Socket, HttpRequest) -> ok. %%-------------------------------------------------------------------- -packet_http_decode_list(doc) -> - ["Test setting the packet option {packet, http}, {mode, list}" - "(Body will be list too)"]; -packet_http_decode_list(suite) -> - []; +packet_http_decode_list() -> + [{doc, "Test setting the packet option {packet, http}, {mode, list}" + "(Body will be list too)"}]. packet_http_decode_list(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -1712,11 +853,8 @@ client_http_decode_list(Socket, HttpRequest) -> ok. %%-------------------------------------------------------------------- -packet_http_bin_decode_multi(doc) -> - ["Test setting the packet option {packet, http_bin} with multiple requests"]; -packet_http_bin_decode_multi(suite) -> - []; - +packet_http_bin_decode_multi() -> + [{doc,"Test setting the packet option {packet, http_bin} with multiple requests"}]. packet_http_bin_decode_multi(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -1803,11 +941,10 @@ client_http_bin_decode(_, _, _) -> ok. %%-------------------------------------------------------------------- -packet_http_error_passive(doc) -> - ["Test setting the packet option {packet, http}, {active, false}" - " with a incorrect http header." ]; -packet_http_error_passive(suite) -> - []; +packet_http_error_passive() -> + [{doc,"Test setting the packet option {packet, http}, {active, false}" + " with a incorrect http header."}]. + packet_http_error_passive(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -1865,10 +1002,9 @@ server_http_decode_error(Socket, HttpResponse) -> ok = ssl:send(Socket, HttpResponse), ok. %%-------------------------------------------------------------------- -packet_httph_active(doc) -> - ["Test setting the packet option {packet, httph}"]; -packet_httph_active(suite) -> - []; +packet_httph_active() -> + [{doc,"Test setting the packet option {packet, httph}"}]. + packet_httph_active(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -1922,10 +1058,8 @@ client_http_decode_trailer_active(Socket) -> ok. %%-------------------------------------------------------------------- -packet_httph_bin_active(doc) -> - ["Test setting the packet option {packet, httph_bin}"]; -packet_httph_bin_active(suite) -> - []; +packet_httph_bin_active() -> + [{doc,"Test setting the packet option {packet, httph_bin}"}]. packet_httph_bin_active(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -1973,10 +1107,9 @@ client_http_decode_trailer_bin_active(Socket) -> end, ok. %%-------------------------------------------------------------------- -packet_httph_active_once(doc) -> - ["Test setting the packet option {packet, httph}"]; -packet_httph_active_once(suite) -> - []; +packet_httph_active_once() -> + [{doc,"Test setting the packet option {packet, httph}"}]. + packet_httph_active_once(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -2027,10 +1160,9 @@ client_http_decode_trailer_active_once(Socket) -> end, ok. %%-------------------------------------------------------------------- -packet_httph_bin_active_once(doc) -> - ["Test setting the packet option {packet, httph_bin}"]; -packet_httph_bin_active_once(suite) -> - []; +packet_httph_bin_active_once() -> + [{doc,"Test setting the packet option {packet, httph_bin}"}]. + packet_httph_bin_active_once(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -2082,10 +1214,9 @@ client_http_decode_trailer_bin_active_once(Socket) -> %%-------------------------------------------------------------------- -packet_httph_passive(doc) -> - ["Test setting the packet option {packet, httph}"]; -packet_httph_passive(suite) -> - []; +packet_httph_passive() -> + [{doc,"Test setting the packet option {packet, httph}"}]. + packet_httph_passive(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -2123,10 +1254,9 @@ client_http_decode_trailer_passive(Socket) -> ok. %%-------------------------------------------------------------------- -packet_httph_bin_passive(doc) -> - ["Test setting the packet option {packet, httph_bin}"]; -packet_httph_bin_passive(suite) -> - []; +packet_httph_bin_passive() -> + [{doc,"Test setting the packet option {packet, httph_bin}"}]. + packet_httph_bin_passive(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -2164,10 +1294,9 @@ client_http_decode_trailer_bin_passive(Socket) -> ok. %%-------------------------------------------------------------------- -packet_line_decode(doc) -> - ["Test setting the packet option {packet, line}, {mode, binary}"]; -packet_line_decode(suite) -> - []; +packet_line_decode() -> + [{doc,"Test setting the packet option {packet, line}, {mode, binary}"}]. + packet_line_decode(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -2201,10 +1330,9 @@ packet_line_decode(Config) when is_list(Config) -> %%-------------------------------------------------------------------- -packet_line_decode_list(doc) -> - ["Test setting the packet option {packet, line}, {mode, list}"]; -packet_line_decode_list(suite) -> - []; +packet_line_decode_list() -> + [{doc,"Test setting the packet option {packet, line}, {mode, list}"}]. + packet_line_decode_list(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -2240,10 +1368,9 @@ packet_line_decode_list(Config) when is_list(Config) -> %%-------------------------------------------------------------------- -packet_asn1_decode(doc) -> - ["Test setting the packet option {packet, asn1}"]; -packet_asn1_decode(suite) -> - []; +packet_asn1_decode() -> + [{doc,"Test setting the packet option {packet, asn1}"}]. + packet_asn1_decode(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -2276,10 +1403,9 @@ packet_asn1_decode(Config) when is_list(Config) -> ssl_test_lib:close(Client). %%-------------------------------------------------------------------- -packet_asn1_decode_list(doc) -> - ["Test setting the packet option {packet, asn1}"]; -packet_asn1_decode_list(suite) -> - []; +packet_asn1_decode_list() -> + [{doc,"Test setting the packet option {packet, asn1}"}]. + packet_asn1_decode_list(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -2314,10 +1440,9 @@ packet_asn1_decode_list(Config) when is_list(Config) -> ssl_test_lib:close(Client). %%-------------------------------------------------------------------- -packet_tpkt_decode(doc) -> - ["Test setting the packet option {packet, tpkt}"]; -packet_tpkt_decode(suite) -> - []; +packet_tpkt_decode() -> + [{doc,"Test setting the packet option {packet, tpkt}"}]. + packet_tpkt_decode(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -2347,10 +1472,9 @@ packet_tpkt_decode(Config) when is_list(Config) -> ssl_test_lib:close(Server), ssl_test_lib:close(Client). %%-------------------------------------------------------------------- -packet_tpkt_decode_list(doc) -> - ["Test setting the packet option {packet, tpkt}"]; -packet_tpkt_decode_list(suite) -> - []; +packet_tpkt_decode_list() -> + [{doc,"Test setting the packet option {packet, tpkt}"}]. + packet_tpkt_decode_list(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -2381,10 +1505,9 @@ packet_tpkt_decode_list(Config) when is_list(Config) -> %%-------------------------------------------------------------------- -%% packet_fcgi_decode(doc) -> -%% ["Test setting the packet option {packet, fcgi}"]; -%% packet_fcgi_decode(suite) -> -%% []; +%% packet_fcgi_decode() -> +%% [{doc,"Test setting the packet option {packet, fcgi}"}]. + %% packet_fcgi_decode(Config) when is_list(Config) -> %% ClientOpts = ?config(client_opts, Config), %% ServerOpts = ?config(server_opts, Config), @@ -2416,10 +1539,8 @@ packet_tpkt_decode_list(Config) when is_list(Config) -> %%-------------------------------------------------------------------- -packet_sunrm_decode(doc) -> - ["Test setting the packet option {packet, sunrm}"]; -packet_sunrm_decode(suite) -> - []; +packet_sunrm_decode() -> + [{doc,"Test setting the packet option {packet, sunrm}"}]. packet_sunrm_decode(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -2449,10 +1570,9 @@ packet_sunrm_decode(Config) when is_list(Config) -> ssl_test_lib:close(Client). %%-------------------------------------------------------------------- -packet_sunrm_decode_list(doc) -> - ["Test setting the packet option {packet, sunrm}"]; -packet_sunrm_decode_list(suite) -> - []; +packet_sunrm_decode_list() -> + [{doc,"Test setting the packet option {packet, sunrm}"}]. + packet_sunrm_decode_list(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -2482,10 +1602,9 @@ packet_sunrm_decode_list(Config) when is_list(Config) -> ssl_test_lib:close(Client). %%-------------------------------------------------------------------- -header_decode_one_byte_active(doc) -> - ["Test setting the packet option {header, 1}"]; -header_decode_one_byte_active(suite) -> - []; +header_decode_one_byte_active() -> + [{doc,"Test setting the packet option {header, 1}"}]. + header_decode_one_byte_active(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -2516,10 +1635,9 @@ header_decode_one_byte_active(Config) when is_list(Config) -> %%-------------------------------------------------------------------- -header_decode_two_bytes_active(doc) -> - ["Test setting the packet option {header, 2}"]; -header_decode_two_bytes_active(suite) -> - []; +header_decode_two_bytes_active() -> + [{doc,"Test setting the packet option {header, 2}"}]. + header_decode_two_bytes_active(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -2551,10 +1669,9 @@ header_decode_two_bytes_active(Config) when is_list(Config) -> %%-------------------------------------------------------------------- -header_decode_two_bytes_two_sent_active(doc) -> - ["Test setting the packet option {header, 2} and sending two byte"]; -header_decode_two_bytes_two_sent_active(suite) -> - []; +header_decode_two_bytes_two_sent_active() -> + [{doc,"Test setting the packet option {header, 2} and sending two byte"}]. + header_decode_two_bytes_two_sent_active(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -2586,10 +1703,9 @@ header_decode_two_bytes_two_sent_active(Config) when is_list(Config) -> %%-------------------------------------------------------------------- -header_decode_two_bytes_one_sent_active(doc) -> - ["Test setting the packet option {header, 2} and sending one byte"]; -header_decode_two_bytes_one_sent_active(suite) -> - []; +header_decode_two_bytes_one_sent_active() -> + [{doc,"Test setting the packet option {header, 2} and sending one byte"}]. + header_decode_two_bytes_one_sent_active(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -2620,10 +1736,9 @@ header_decode_two_bytes_one_sent_active(Config) when is_list(Config) -> %%-------------------------------------------------------------------- -header_decode_one_byte_passive(doc) -> - ["Test setting the packet option {header, 1}"]; -header_decode_one_byte_passive(suite) -> - []; +header_decode_one_byte_passive() -> + [{doc,"Test setting the packet option {header, 1}"}]. + header_decode_one_byte_passive(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -2654,10 +1769,9 @@ header_decode_one_byte_passive(Config) when is_list(Config) -> %%-------------------------------------------------------------------- -header_decode_two_bytes_passive(doc) -> - ["Test setting the packet option {header, 2}"]; -header_decode_two_bytes_passive(suite) -> - []; +header_decode_two_bytes_passive() -> + [{doc,"Test setting the packet option {header, 2}"}]. + header_decode_two_bytes_passive(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -2689,10 +1803,9 @@ header_decode_two_bytes_passive(Config) when is_list(Config) -> %%-------------------------------------------------------------------- -header_decode_two_bytes_two_sent_passive(doc) -> - ["Test setting the packet option {header, 2} and sending two byte"]; -header_decode_two_bytes_two_sent_passive(suite) -> - []; +header_decode_two_bytes_two_sent_passive() -> + [{doc,"Test setting the packet option {header, 2} and sending two byte"}]. + header_decode_two_bytes_two_sent_passive(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -2724,10 +1837,9 @@ header_decode_two_bytes_two_sent_passive(Config) when is_list(Config) -> %%-------------------------------------------------------------------- -header_decode_two_bytes_one_sent_passive(doc) -> - ["Test setting the packet option {header, 2} and sending one byte"]; -header_decode_two_bytes_one_sent_passive(suite) -> - []; +header_decode_two_bytes_one_sent_passive() -> + [{doc,"Test setting the packet option {header, 2} and sending one byte"}]. + header_decode_two_bytes_one_sent_passive(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -2757,7 +1869,30 @@ header_decode_two_bytes_one_sent_passive(Config) when is_list(Config) -> ssl_test_lib:close(Client). %%-------------------------------------------------------------------- -%% Internal functions +%% Internal functions ------------------------------------------------ +%%-------------------------------------------------------------------- +packet(Config, Data, Send, Recv, Quantity, Packet, Active) -> + ClientOpts = ?config(client_opts, Config), + ServerOpts = ?config(server_opts, Config), + {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Server = ssl_test_lib:start_server([{node, ClientNode}, {port, 0}, + {from, self()}, + {mfa, {?MODULE, Send ,[Data, Quantity]}}, + {options, ServerOpts}]), + Port = ssl_test_lib:inet_port(Server), + Client = ssl_test_lib:start_client([{node, ServerNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {?MODULE, Recv, [Data, Quantity]}}, + {options, [{active, Active}, + {packet, Packet} | + ClientOpts]}]), + + ssl_test_lib:check_result(Client, ok), + + ssl_test_lib:close(Server), + ssl_test_lib:close(Client). send_raw(Socket,_, 0) -> ssl:send(Socket, <<>>), @@ -2928,7 +2063,7 @@ client_packet_decode(Socket, [Head | Tail] = Packet) -> client_packet_decode(Socket, [Head], Tail, Packet). client_packet_decode(Socket, P1, P2, Packet) -> - test_server:format("Packet: ~p ~n", [Packet]), + ct:print("Packet: ~p ~n", [Packet]), ok = ssl:send(Socket, P1), ok = ssl:send(Socket, P2), receive diff --git a/lib/ssl/test/ssl_payload_SUITE.erl b/lib/ssl/test/ssl_payload_SUITE.erl index c97f97e70b..77ad546420 100644 --- a/lib/ssl/test/ssl_payload_SUITE.erl +++ b/lib/ssl/test/ssl_payload_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2012. All Rights Reserved. +%% Copyright Ericsson AB 2008-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -26,79 +26,8 @@ -define(TIMEOUT, 600000). -%% Test server callback functions %%-------------------------------------------------------------------- -%% Function: init_per_suite(Config) -> Config -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% Description: Initialization before the whole suite -%% -%% Note: This function is free to add any key/value pairs to the Config -%% variable, but should NOT alter/remove any existing entries. -%%-------------------------------------------------------------------- -init_per_suite(Config) -> - catch crypto:stop(), - try crypto:start() of - ok -> - application:start(public_key), - ssl:start(), - make_certs:all(?config(data_dir, Config), ?config(priv_dir, Config)), - ssl_test_lib:cert_options(Config) - catch _:_ -> - {skip, "Crypto did not start"} - end. -%%-------------------------------------------------------------------- -%% Function: end_per_suite(Config) -> _ -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% Description: Cleanup after the whole suite -%%-------------------------------------------------------------------- -end_per_suite(_Config) -> - ssl:stop(), - application:stop(crypto). - -%%-------------------------------------------------------------------- -%% Function: init_per_testcase(TestCase, Config) -> Config -%% Case - atom() -%% Name of the test case that is about to be run. -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% -%% Description: Initialization before each test case -%% -%% Note: This function is free to add any key/value pairs to the Config -%% variable, but should NOT alter/remove any existing entries. -%% Description: Initialization before each test case -%%-------------------------------------------------------------------- -init_per_testcase(_TestCase, Config0) -> - Config = lists:keydelete(watchdog, 1, Config0), - Dog = ssl_test_lib:timetrap(?TIMEOUT), - [{watchdog, Dog} | Config]. - -%%-------------------------------------------------------------------- -%% Function: end_per_testcase(TestCase, Config) -> _ -%% Case - atom() -%% Name of the test case that is about to be run. -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% Description: Cleanup after each test case -%%-------------------------------------------------------------------- -end_per_testcase(_TestCase, Config) -> - Dog = ?config(watchdog, Config), - case Dog of - undefined -> - ok; - _ -> - test_server:timetrap_cancel(Dog) - end. - -%%-------------------------------------------------------------------- -%% Function: all(Clause) -> TestCases -%% Clause - atom() - suite | doc -%% TestCases - [Case] -%% Case - atom() -%% Name of a test case. -%% Description: Returns a list of all test cases in this test suite +%% Common Test interface functions ----------------------------------- %%-------------------------------------------------------------------- suite() -> [{ct_hooks,[ts_install_cth]}]. @@ -138,6 +67,21 @@ payload_tests() -> client_echos_active_once_huge, client_echos_active_huge]. +init_per_suite(Config) -> + catch crypto:stop(), + try crypto:start() of + ok -> + application:start(public_key), + ssl:start(), + make_certs:all(?config(data_dir, Config), ?config(priv_dir, Config)), + ssl_test_lib:cert_options(Config) + catch _:_ -> + {skip, "Crypto did not start"} + end. + +end_per_suite(_Config) -> + ssl:stop(), + application:stop(crypto). init_per_group(GroupName, Config) -> case ssl_test_lib:is_tls_version(GroupName) of @@ -157,15 +101,20 @@ init_per_group(GroupName, Config) -> end_per_group(_GroupName, Config) -> Config. +init_per_testcase(_TestCase, Config0) -> + Config = lists:keydelete(watchdog, 1, Config0), + Dog = ct:timetrap(?TIMEOUT), + [{watchdog, Dog} | Config]. -%% Test cases starts here. +end_per_testcase(_TestCase, Config) -> + Config. +%%-------------------------------------------------------------------- +%% Test Cases -------------------------------------------------------- %%-------------------------------------------------------------------- -server_echos_passive_small(doc) -> - ["Client sends 1000 bytes in passive mode to server, that receives them, " - "sends them back, and closes."]; -server_echos_passive_small(suite) -> - []; +server_echos_passive_small() -> + [{doc, "Client sends 1000 bytes in passive mode to server, that receives them, " + "sends them back, and closes."}]. server_echos_passive_small(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -179,12 +128,9 @@ server_echos_passive_small(Config) when is_list(Config) -> %%-------------------------------------------------------------------- -server_echos_active_once_small(doc) -> - ["Client sends 1000 bytes in active once mode to server, that receives " - " them, sends them back, and closes."]; - -server_echos_active_once_small(suite) -> - []; +server_echos_active_once_small() -> + [{doc, "Client sends 1000 bytes in active once mode to server, that receives " + " them, sends them back, and closes."}]. server_echos_active_once_small(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -198,12 +144,9 @@ server_echos_active_once_small(Config) when is_list(Config) -> %%-------------------------------------------------------------------- -server_echos_active_small(doc) -> - ["Client sends 1000 bytes in active mode to server, that receives them, " - "sends them back, and closes."]; - -server_echos_active_small(suite) -> - []; +server_echos_active_small() -> + [{doc, "Client sends 1000 bytes in active mode to server, that receives them, " + "sends them back, and closes."}]. server_echos_active_small(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -216,12 +159,9 @@ server_echos_active_small(Config) when is_list(Config) -> ClientNode, ServerNode, Hostname). %%-------------------------------------------------------------------- -client_echos_passive_small(doc) -> - ["Server sends 1000 bytes in passive mode to client, that receives them, " - "sends them back, and closes."]; - -client_echos_passive_small(suite) -> - []; +client_echos_passive_small() -> + [{doc, "Server sends 1000 bytes in passive mode to client, that receives them, " + "sends them back, and closes."}]. client_echos_passive_small(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -234,12 +174,9 @@ client_echos_passive_small(Config) when is_list(Config) -> ServerNode, Hostname). %%-------------------------------------------------------------------- -client_echos_active_once_small(doc) -> +client_echos_active_once_small() -> ["Server sends 1000 bytes in active once mode to client, that receives " - "them, sends them back, and closes."]; - -client_echos_active_once_small(suite) -> - []; + "them, sends them back, and closes."]. client_echos_active_once_small(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -252,15 +189,12 @@ client_echos_active_once_small(Config) when is_list(Config) -> ServerNode, Hostname). %%-------------------------------------------------------------------- -client_echos_active_small(doc) -> - ["Server sends 1000 bytes in active mode to client, that receives them, " - "sends them back, and closes."]; - -client_echos_active_small(suite) -> - []; +client_echos_active_small() -> + [{doc, "Server sends 1000 bytes in active mode to client, that receives them, " + "sends them back, and closes."}]. client_echos_active_small(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), + ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), @@ -271,12 +205,9 @@ client_echos_active_small(Config) when is_list(Config) -> %%-------------------------------------------------------------------- -server_echos_passive_big(doc) -> - ["Client sends 50000 bytes to server in passive mode, that receives them, " - "sends them back, and closes."]; - -server_echos_passive_big(suite) -> - []; +server_echos_passive_big() -> + [{doc, "Client sends 50000 bytes to server in passive mode, that receives them, " + "sends them back, and closes."}]. server_echos_passive_big(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -290,15 +221,12 @@ server_echos_passive_big(Config) when is_list(Config) -> %%-------------------------------------------------------------------- -server_echos_active_once_big(doc) -> - ["Client sends 50000 bytes to server in active once mode, that receives " - "them, sends them back, and closes."]; - -server_echos_active_once_big(suite) -> - []; +server_echos_active_once_big() -> + [{doc,"Client sends 50000 bytes to server in active once mode, that receives " + "them, sends them back, and closes."}]. server_echos_active_once_big(Config) when is_list(Config) -> - ClientOpts = ?config(client_opts, Config), + ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), @@ -309,12 +237,9 @@ server_echos_active_once_big(Config) when is_list(Config) -> %%-------------------------------------------------------------------- -server_echos_active_big(doc) -> - ["Client sends 50000 bytes to server in active once mode, that receives " - " them, sends them back, and closes."]; - -server_echos_active_big(suite) -> - []; +server_echos_active_big() -> + [{doc, "Client sends 50000 bytes to server in active once mode, that receives " + " them, sends them back, and closes."}]. server_echos_active_big(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -327,12 +252,9 @@ server_echos_active_big(Config) when is_list(Config) -> ServerNode, Hostname). %%-------------------------------------------------------------------- -client_echos_passive_big(doc) -> - ["Server sends 50000 bytes to client in passive mode, that receives them, " - "sends them back, and closes."]; - -client_echos_passive_big(suite) -> - []; +client_echos_passive_big() -> + [{doc, "Server sends 50000 bytes to client in passive mode, that receives them, " + "sends them back, and closes."}]. client_echos_passive_big(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -345,12 +267,9 @@ client_echos_passive_big(Config) when is_list(Config) -> ServerNode, Hostname). %%-------------------------------------------------------------------- -client_echos_active_once_big(doc) -> - ["Server sends 50000 bytes to client in active once mode, that receives" - " them, sends them back, and closes."]; - -client_echos_active_once_big(suite) -> - []; +client_echos_active_once_big() -> + [{doc, "Server sends 50000 bytes to client in active once mode, that receives" + " them, sends them back, and closes."}]. client_echos_active_once_big(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -363,12 +282,9 @@ client_echos_active_once_big(Config) when is_list(Config) -> ServerNode, Hostname). %%-------------------------------------------------------------------- -client_echos_active_big(doc) -> - ["Server sends 50000 bytes to client in active mode, that receives them, " - "sends them back, and closes."]; - -client_echos_active_big(suite) -> - []; +client_echos_active_big() -> + [{doc, "Server sends 50000 bytes to client in active mode, that receives them, " + "sends them back, and closes."}]. client_echos_active_big(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -381,12 +297,9 @@ client_echos_active_big(Config) when is_list(Config) -> ServerNode, Hostname). %%-------------------------------------------------------------------- -server_echos_passive_huge(doc) -> - ["Client sends 500000 bytes to server in passive mode, that receives " - " them, sends them back, and closes."]; - -server_echos_passive_huge(suite) -> - []; +server_echos_passive_huge() -> + [{doc, "Client sends 500000 bytes to server in passive mode, that receives " + " them, sends them back, and closes."}]. server_echos_passive_huge(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -399,12 +312,9 @@ server_echos_passive_huge(Config) when is_list(Config) -> ServerNode, Hostname). %%-------------------------------------------------------------------- -server_echos_active_once_huge(doc) -> - ["Client sends 500000 bytes to server in active once mode, that receives " - "them, sends them back, and closes."]; - -server_echos_active_once_huge(suite) -> - []; +server_echos_active_once_huge() -> + [{doc, "Client sends 500000 bytes to server in active once mode, that receives " + "them, sends them back, and closes."}]. server_echos_active_once_huge(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -417,12 +327,9 @@ server_echos_active_once_huge(Config) when is_list(Config) -> ServerNode, Hostname). %%-------------------------------------------------------------------- -server_echos_active_huge(doc) -> - ["Client sends 500000 bytes to server in active mode, that receives them, " - "sends them back, and closes."]; - -server_echos_active_huge(suite) -> - []; +server_echos_active_huge() -> + [{doc, "Client sends 500000 bytes to server in active mode, that receives them, " + "sends them back, and closes."}]. server_echos_active_huge(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -435,12 +342,9 @@ server_echos_active_huge(Config) when is_list(Config) -> ServerNode, Hostname). %%-------------------------------------------------------------------- -client_echos_passive_huge(doc) -> - ["Server sends 500000 bytes to client in passive mode, that receives " - "them, sends them back, and closes."]; - -client_echos_passive_huge(suite) -> - []; +client_echos_passive_huge() -> + [{doc, "Server sends 500000 bytes to client in passive mode, that receives " + "them, sends them back, and closes."}]. client_echos_passive_huge(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -452,12 +356,9 @@ client_echos_passive_huge(Config) when is_list(Config) -> ServerNode, Hostname). %%-------------------------------------------------------------------- -client_echos_active_once_huge(doc) -> - ["Server sends 500000 bytes to client in active once mode, that receives " - "them, sends them back, and closes."]; - -client_echos_active_once_huge(suite) -> - []; +client_echos_active_once_huge() -> + [{doc, "Server sends 500000 bytes to client in active once mode, that receives " + "them, sends them back, and closes."}]. client_echos_active_once_huge(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -469,12 +370,9 @@ client_echos_active_once_huge(Config) when is_list(Config) -> ServerNode, Hostname). %%-------------------------------------------------------------------- -client_echos_active_huge(doc) -> - ["Server sends 500000 bytes to client in active mode, that receives them, " - "sends them back, and closes."]; - -client_echos_active_huge(suite) -> - []; +client_echos_active_huge() -> + [{doc, "Server sends 500000 bytes to client in active mode, that receives them, " + "sends them back, and closes."}]. client_echos_active_huge(Config) when is_list(Config) -> ClientOpts = ?config(client_opts, Config), @@ -486,6 +384,8 @@ client_echos_active_huge(Config) when is_list(Config) -> ServerNode, Hostname). %%-------------------------------------------------------------------- +%% Internal functions ------------------------------------------------ +%%-------------------------------------------------------------------- server_echos_passive(Data, Length, ClientOpts, ServerOpts, ClientNode, ServerNode, Hostname) -> @@ -656,33 +556,33 @@ send(Socket, Data, Size, Repeate,F) -> sender(Socket, Data, Size) -> ok = send(Socket, Data, Size, 100, fun() -> do_recv(Socket, Data, Size, <<>>, false) end), - test_server:format("Sender recv: ~p~n", [ssl:getopts(Socket, [active])]), + ct:print("Sender recv: ~p~n", [ssl:getopts(Socket, [active])]), ok. sender_once(Socket, Data, Size) -> send(Socket, Data, Size, 100, fun() -> do_active_once(Socket, Data, Size, <<>>, false) end), - test_server:format("Sender active once: ~p~n", + ct:print("Sender active once: ~p~n", [ssl:getopts(Socket, [active])]), ok. sender_active(Socket, Data, Size) -> F = fun() -> do_active(Socket, Data, Size, <<>>, false) end, send(Socket, Data, Size, 100, F), - test_server:format("Sender active: ~p~n", [ssl:getopts(Socket, [active])]), + ct:print("Sender active: ~p~n", [ssl:getopts(Socket, [active])]), ok. echoer(Socket, Data, Size) -> - test_server:format("Echoer recv: ~p~n", [ssl:getopts(Socket, [active])]), + ct:print("Echoer recv: ~p~n", [ssl:getopts(Socket, [active])]), echo(fun() -> do_recv(Socket, Data, Size, <<>>, true) end, 100). echoer_once(Socket, Data, Size) -> - test_server:format("Echoer active once: ~p ~n", + ct:print("Echoer active once: ~p ~n", [ssl:getopts(Socket, [active])]), echo(fun() -> do_active_once(Socket, Data, Size, <<>>, true) end, 100). echoer_active(Socket, Data, Size) -> - test_server:format("Echoer active: ~p~n", [ssl:getopts(Socket, [active])]), + ct:print("Echoer active: ~p~n", [ssl:getopts(Socket, [active])]), echo(fun() -> do_active(Socket, Data, Size, <<>>, true) end, 100). echo(_Fun, 0) -> ok; diff --git a/lib/ssl/test/ssl_session_cache_SUITE.erl b/lib/ssl/test/ssl_session_cache_SUITE.erl index 1d71efd40c..fd9a0a594c 100644 --- a/lib/ssl/test/ssl_session_cache_SUITE.erl +++ b/lib/ssl/test/ssl_session_cache_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2012. All Rights Reserved. +%% Copyright Ericsson AB 2010-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -37,18 +37,22 @@ -export([init/1, terminate/1, lookup/2, update/3, delete/2, foldl/3, select_session/2]). -%% Test server callback functions %%-------------------------------------------------------------------- -%% Function: init_per_suite(Config) -> Config -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% Description: Initialization before the whole suite -%% -%% Note: This function is free to add any key/value pairs to the Config -%% variable, but should NOT alter/remove any existing entries. +%% Common Test interface functions ----------------------------------- %%-------------------------------------------------------------------- + +suite() -> [{ct_hooks,[ts_install_cth]}]. + +all() -> + [session_cleanup, + session_cache_process_list, + session_cache_process_mnesia]. + +groups() -> + []. + init_per_suite(Config0) -> - Dog = ssl_test_lib:timetrap(?LONG_TIMEOUT *2), + Dog = ct:timetrap(?LONG_TIMEOUT *2), catch crypto:stop(), try crypto:start() of ok -> @@ -59,7 +63,7 @@ init_per_suite(Config0) -> Result = (catch make_certs:all(?config(data_dir, Config0), ?config(priv_dir, Config0))), - test_server:format("Make certs ~p~n", [Result]), + ct:print("Make certs ~p~n", [Result]), Config1 = ssl_test_lib:make_dsa_cert(Config0), Config = ssl_test_lib:cert_options(Config1), @@ -68,29 +72,16 @@ init_per_suite(Config0) -> {skip, "Crypto did not start"} end. -%%-------------------------------------------------------------------- -%% Function: end_per_suite(Config) -> _ -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% Description: Cleanup after the whole suite -%%-------------------------------------------------------------------- end_per_suite(_Config) -> ssl:stop(), application:stop(crypto). -%%-------------------------------------------------------------------- -%% Function: init_per_testcase(TestCase, Config) -> Config -%% Case - atom() -%% Name of the test case that is about to be run. -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% -%% Description: Initialization before each test case -%% -%% Note: This function is free to add any key/value pairs to the Config -%% variable, but should NOT alter/remove any existing entries. -%% Description: Initialization before each test case -%%-------------------------------------------------------------------- +init_per_group(_GroupName, Config) -> + Config. + +end_per_group(_GroupName, Config) -> + Config. + init_per_testcase(session_cache_process_list, Config) -> init_customized_session_cache(list, Config); @@ -100,7 +91,7 @@ init_per_testcase(session_cache_process_mnesia, Config) -> init_per_testcase(session_cleanup, Config0) -> Config = lists:keydelete(watchdog, 1, Config0), - Dog = test_server:timetrap(?TIMEOUT), + Dog = ct:timetrap(?TIMEOUT), ssl:stop(), application:load(ssl), application:set_env(ssl, session_lifetime, 5), @@ -110,12 +101,12 @@ init_per_testcase(session_cleanup, Config0) -> init_per_testcase(_TestCase, Config0) -> Config = lists:keydelete(watchdog, 1, Config0), - Dog = test_server:timetrap(?TIMEOUT), + Dog = ct:timetrap(?TIMEOUT), [{watchdog, Dog} | Config]. init_customized_session_cache(Type, Config0) -> Config = lists:keydelete(watchdog, 1, Config0), - Dog = test_server:timetrap(?TIMEOUT), + Dog = ct:timetrap(?TIMEOUT), ssl:stop(), application:load(ssl), application:set_env(ssl, session_cb, ?MODULE), @@ -123,14 +114,6 @@ init_customized_session_cache(Type, Config0) -> ssl:start(), [{watchdog, Dog} | Config]. -%%-------------------------------------------------------------------- -%% Function: end_per_testcase(TestCase, Config) -> _ -%% Case - atom() -%% Name of the test case that is about to be run. -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% Description: Cleanup after each test case -%%-------------------------------------------------------------------- end_per_testcase(session_cache_process_list, Config) -> application:unset_env(ssl, session_cb), end_per_testcase(default_action, Config); @@ -146,43 +129,14 @@ end_per_testcase(session_cleanup, Config) -> application:unset_env(ssl, session_lifetime), end_per_testcase(default_action, Config); end_per_testcase(_TestCase, Config) -> - Dog = ?config(watchdog, Config), - case Dog of - undefined -> - ok; - _ -> - test_server:timetrap_cancel(Dog) - end. - -%%-------------------------------------------------------------------- -%% Function: all(Clause) -> TestCases -%% Clause - atom() - suite | doc -%% TestCases - [Case] -%% Case - atom() -%% Name of a test case. -%% Description: Returns a list of all test cases in this test suite -%%-------------------------------------------------------------------- -suite() -> [{ct_hooks,[ts_install_cth]}]. - -all() -> - [session_cleanup, - session_cache_process_list, - session_cache_process_mnesia]. - -groups() -> - []. - -init_per_group(_GroupName, Config) -> Config. -end_per_group(_GroupName, Config) -> - Config. %%-------------------------------------------------------------------- -session_cleanup(doc) -> - ["Test that sessions are cleand up eventually, so that the session table " - "does not grow and grow ..."]; -session_cleanup(suite) -> - []; +%% Test Cases -------------------------------------------------------- +%%-------------------------------------------------------------------- +session_cleanup() -> + [{doc, "Test that sessions are cleand up eventually, so that the session table " + "does not grow and grow ..."}]. session_cleanup(Config)when is_list(Config) -> process_flag(trap_exit, true), ClientOpts = ?config(client_opts, Config), @@ -207,7 +161,7 @@ session_cleanup(Config)when is_list(Config) -> end, %% Make sure session is registered - test_server:sleep(?SLEEP), + ct:sleep(?SLEEP), {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)), [_, _,_, _, Prop] = StatusInfo, @@ -224,14 +178,14 @@ session_cleanup(Config)when is_list(Config) -> %% Make sure session has expired and been cleaned up check_timer(SessionTimer), - test_server:sleep(?DELAY *2), %% Delay time + some extra time + ct:sleep(?DELAY *2), %% Delay time + some extra time {ServerDelayTimer, ClientDelayTimer} = get_delay_timers(), check_timer(ServerDelayTimer), check_timer(ClientDelayTimer), - test_server:sleep(?SLEEP), %% Make sure clean has had time to run + ct:sleep(?SLEEP), %% Make sure clean has had time to run undefined = ssl_session_cache:lookup(Cache, {{Hostname, Port}, Id}), undefined = ssl_session_cache:lookup(Cache, {Port, Id}), @@ -248,7 +202,7 @@ check_timer(Timer) -> {status, _, _, _} = sys:get_status(whereis(ssl_manager)), ok; Int -> - test_server:sleep(Int), + ct:sleep(Int), check_timer(Timer) end. @@ -258,31 +212,25 @@ get_delay_timers() -> State = ssl_test_lib:state(Prop), case element(7, State) of {undefined, undefined} -> - test_server:sleep(?SLEEP), + ct:sleep(?SLEEP), get_delay_timers(); {undefined, _} -> - test_server:sleep(?SLEEP), + ct:sleep(?SLEEP), get_delay_timers(); {_, undefined} -> - test_server:sleep(?SLEEP), + ct:sleep(?SLEEP), get_delay_timers(); DelayTimers -> DelayTimers end. %%-------------------------------------------------------------------- -session_cache_process_list(doc) -> - ["Test reuse of sessions (short handshake)"]; - -session_cache_process_list(suite) -> - []; +session_cache_process_list() -> + [{doc,"Test reuse of sessions (short handshake)"}]. session_cache_process_list(Config) when is_list(Config) -> session_cache_process(list,Config). %%-------------------------------------------------------------------- -session_cache_process_mnesia(doc) -> - ["Test reuse of sessions (short handshake)"]; - -session_cache_process_mnesia(suite) -> - []; +session_cache_process_mnesia() -> + [{doc,"Test reuse of sessions (short handshake)"}]. session_cache_process_mnesia(Config) when is_list(Config) -> session_cache_process(mnesia,Config). diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl index f1f5b9ae0a..76b302b1cb 100644 --- a/lib/ssl/test/ssl_test_lib.erl +++ b/lib/ssl/test/ssl_test_lib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2012. All Rights Reserved. +%% Copyright Ericsson AB 2008-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -20,8 +20,7 @@ %% -module(ssl_test_lib). --include("test_server.hrl"). --include("test_server_line.hrl"). +-include_lib("common_test/include/ct.hrl"). -include_lib("public_key/include/public_key.hrl"). %% Note: This directive should only be used in test suites. @@ -29,12 +28,6 @@ -record(sslsocket, { fd = nil, pid = nil}). -timetrap(Time) -> - Mul = try - test_server:timetrap_scale_factor() - catch _:_ -> 1 end, - test_server:timetrap(1000+Time*Mul). - %% For now always run locally run_where(_) -> ClientNode = node(), @@ -65,8 +58,9 @@ run_server(Opts) -> Port = proplists:get_value(port, Opts), Options = proplists:get_value(options, Opts), Pid = proplists:get_value(from, Opts), - test_server:format("ssl:listen(~p, ~p)~n", [Port, Options]), - {ok, ListenSocket} = rpc:call(Node, ssl, listen, [Port, Options]), + Transport = proplists:get_value(transport, Opts, ssl), + ct:print("ssl:listen(~p, ~p)~n", [Port, Options]), + {ok, ListenSocket} = rpc:call(Node, Transport, listen, [Port, Options]), Pid ! {listen, up}, send_selected_port(Pid, Port, ListenSocket), run_server(ListenSocket, Opts). @@ -81,14 +75,15 @@ do_run_server(_, {error, timeout} = Result, Opts) -> do_run_server(ListenSocket, AcceptSocket, Opts) -> Node = proplists:get_value(node, Opts), Pid = proplists:get_value(from, Opts), + Transport = proplists:get_value(transport, Opts, ssl), {Module, Function, Args} = proplists:get_value(mfa, Opts), - test_server:format("Server: apply(~p,~p,~p)~n", + ct:print("Server: apply(~p,~p,~p)~n", [Module, Function, [AcceptSocket | Args]]), case rpc:call(Node, Module, Function, [AcceptSocket | Args]) of no_result_msg -> ok; Msg -> - test_server:format("Server Msg: ~p ~n", [Msg]), + ct:print("Server Msg: ~p ~n", [Msg]), Pid ! {self(), Msg} end, receive @@ -97,15 +92,16 @@ do_run_server(ListenSocket, AcceptSocket, Opts) -> {listen, MFA} -> run_server(ListenSocket, [MFA | proplists:delete(mfa, Opts)]); close -> - test_server:format("Server closing ~p ~n", [self()]), - Result = rpc:call(Node, ssl, close, [AcceptSocket], 500), - test_server:format("Result ~p ~n", [Result]); + ct:print("Server closing ~p ~n", [self()]), + Result = rpc:call(Node, Transport, close, [AcceptSocket], 500), + Result1 = rpc:call(Node, Transport, close, [ListenSocket], 500), + ct:print("Result ~p : ~p ~n", [Result, Result1]); {ssl_closed, _} -> ok end. %%% To enable to test with s_client -reconnect -connect(ListenSocket, Opts) -> +connect(#sslsocket{} = ListenSocket, Opts) -> Node = proplists:get_value(node, Opts), ReconnectTimes = proplists:get_value(reconnect_times, Opts, 0), Timeout = proplists:get_value(timeout, Opts, infinity), @@ -116,15 +112,21 @@ connect(ListenSocket, Opts) -> _ -> remove_close_msg(ReconnectTimes), AcceptSocket - end. - + end; +connect(ListenSocket, Opts) -> + Node = proplists:get_value(node, Opts), + ct:print("gen_tcp:accept(~p)~n", [ListenSocket]), + {ok, AcceptSocket} = rpc:call(Node, gen_tcp, accept, + [ListenSocket]), + AcceptSocket. + connect(_, _, 0, AcceptSocket, _) -> AcceptSocket; connect(ListenSocket, Node, N, _, Timeout) -> - test_server:format("ssl:transport_accept(~p)~n", [ListenSocket]), + ct:print("ssl:transport_accept(~p)~n", [ListenSocket]), {ok, AcceptSocket} = rpc:call(Node, ssl, transport_accept, [ListenSocket]), - test_server:format("ssl:ssl_accept(~p, ~p)~n", [AcceptSocket, Timeout]), + ct:print("ssl:ssl_accept(~p, ~p)~n", [AcceptSocket, Timeout]), case rpc:call(Node, ssl, ssl_accept, [AcceptSocket, Timeout]) of ok -> @@ -157,45 +159,48 @@ run_client(Opts) -> Host = proplists:get_value(host, Opts), Port = proplists:get_value(port, Opts), Pid = proplists:get_value(from, Opts), + Transport = proplists:get_value(transport, Opts, ssl), Options = proplists:get_value(options, Opts), - test_server:format("ssl:connect(~p, ~p, ~p)~n", [Host, Port, Options]), - case rpc:call(Node, ssl, connect, [Host, Port, Options]) of + ct:print("ssl:connect(~p, ~p, ~p)~n", [Host, Port, Options]), + case rpc:call(Node, Transport, connect, [Host, Port, Options]) of {ok, Socket} -> Pid ! { connected, Socket }, - test_server:format("Client: connected~n", []), + ct:print("Client: connected~n", []), %% In special cases we want to know the client port, it will %% be indicated by sending {port, 0} in options list! send_selected_port(Pid, proplists:get_value(port, Options), Socket), {Module, Function, Args} = proplists:get_value(mfa, Opts), - test_server:format("Client: apply(~p,~p,~p)~n", + ct:print("Client: apply(~p,~p,~p)~n", [Module, Function, [Socket | Args]]), case rpc:call(Node, Module, Function, [Socket | Args]) of no_result_msg -> ok; Msg -> - test_server:format("Client Msg: ~p ~n", [Msg]), + ct:print("Client Msg: ~p ~n", [Msg]), Pid ! {self(), Msg} end, receive close -> - test_server:format("Client closing~n", []), - rpc:call(Node, ssl, close, [Socket]); + ct:print("Client closing~n", []), + rpc:call(Node, Transport, close, [Socket]); {ssl_closed, Socket} -> + ok; + {gen_tcp, closed} -> ok end; {error, Reason} -> - test_server:format("Client: connection failed: ~p ~n", [Reason]), + ct:print("Client: connection failed: ~p ~n", [Reason]), Pid ! {self(), {error, Reason}} end. close(Pid) -> - test_server:format("Close ~p ~n", [Pid]), + ct:print("Close ~p ~n", [Pid]), Monitor = erlang:monitor(process, Pid), Pid ! close, receive {'DOWN', Monitor, process, Pid, Reason} -> erlang:demonitor(Monitor), - test_server:format("Pid: ~p down due to:~p ~n", [Pid, Reason]) + ct:print("Pid: ~p down due to:~p ~n", [Pid, Reason]) end. check_result(Server, ServerMsg, Client, ClientMsg) -> @@ -207,7 +212,7 @@ check_result(Server, ServerMsg, Client, ClientMsg) -> Unexpected -> Reason = {{expected, {Client, ClientMsg}}, {got, Unexpected}}, - test_server:fail(Reason) + ct:fail(Reason) end; {Client, ClientMsg} -> receive @@ -216,7 +221,7 @@ check_result(Server, ServerMsg, Client, ClientMsg) -> Unexpected -> Reason = {{expected, {Server, ClientMsg}}, {got, Unexpected}}, - test_server:fail(Reason) + ct:fail(Reason) end; {Port, {data,Debug}} when is_port(Port) -> io:format("openssl ~s~n",[Debug]), @@ -225,7 +230,7 @@ check_result(Server, ServerMsg, Client, ClientMsg) -> Unexpected -> Reason = {{expected, {Client, ClientMsg}}, {expected, {Server, ServerMsg}}, {got, Unexpected}}, - test_server:fail(Reason) + ct:fail(Reason) end. check_result(Pid, Msg) -> @@ -238,7 +243,7 @@ check_result(Pid, Msg) -> Unexpected -> Reason = {{expected, {Pid, Msg}}, {got, Unexpected}}, - test_server:fail(Reason) + ct:fail(Reason) end. wait_for_result(Server, ServerMsg, Client, ClientMsg) -> @@ -405,33 +410,33 @@ run_upgrade_server(Opts) -> SslOptions = proplists:get_value(ssl_options, Opts), Pid = proplists:get_value(from, Opts), - test_server:format("gen_tcp:listen(~p, ~p)~n", [Port, TcpOptions]), + ct:print("gen_tcp:listen(~p, ~p)~n", [Port, TcpOptions]), {ok, ListenSocket} = rpc:call(Node, gen_tcp, listen, [Port, TcpOptions]), Pid ! {listen, up}, send_selected_port(Pid, Port, ListenSocket), - test_server:format("gen_tcp:accept(~p)~n", [ListenSocket]), + ct:print("gen_tcp:accept(~p)~n", [ListenSocket]), {ok, AcceptSocket} = rpc:call(Node, gen_tcp, accept, [ListenSocket]), try {ok, SslAcceptSocket} = case TimeOut of infinity -> - test_server:format("ssl:ssl_accept(~p, ~p)~n", + ct:print("ssl:ssl_accept(~p, ~p)~n", [AcceptSocket, SslOptions]), rpc:call(Node, ssl, ssl_accept, [AcceptSocket, SslOptions]); _ -> - test_server:format("ssl:ssl_accept(~p, ~p, ~p)~n", + ct:print("ssl:ssl_accept(~p, ~p, ~p)~n", [AcceptSocket, SslOptions, TimeOut]), rpc:call(Node, ssl, ssl_accept, [AcceptSocket, SslOptions, TimeOut]) end, {Module, Function, Args} = proplists:get_value(mfa, Opts), Msg = rpc:call(Node, Module, Function, [SslAcceptSocket | Args]), - test_server:format("Upgrade Server Msg: ~p ~n", [Msg]), + ct:print("Upgrade Server Msg: ~p ~n", [Msg]), Pid ! {self(), Msg}, receive close -> - test_server:format("Upgrade Server closing~n", []), + ct:print("Upgrade Server closing~n", []), rpc:call(Node, ssl, close, [SslAcceptSocket]) end catch error:{badmatch, Error} -> @@ -449,24 +454,24 @@ run_upgrade_client(Opts) -> TcpOptions = proplists:get_value(tcp_options, Opts), SslOptions = proplists:get_value(ssl_options, Opts), - test_server:format("gen_tcp:connect(~p, ~p, ~p)~n", + ct:print("gen_tcp:connect(~p, ~p, ~p)~n", [Host, Port, TcpOptions]), {ok, Socket} = rpc:call(Node, gen_tcp, connect, [Host, Port, TcpOptions]), send_selected_port(Pid, Port, Socket), - test_server:format("ssl:connect(~p, ~p)~n", [Socket, SslOptions]), + ct:print("ssl:connect(~p, ~p)~n", [Socket, SslOptions]), {ok, SslSocket} = rpc:call(Node, ssl, connect, [Socket, SslOptions]), {Module, Function, Args} = proplists:get_value(mfa, Opts), - test_server:format("apply(~p, ~p, ~p)~n", + ct:print("apply(~p, ~p, ~p)~n", [Module, Function, [SslSocket | Args]]), Msg = rpc:call(Node, Module, Function, [SslSocket | Args]), - test_server:format("Upgrade Client Msg: ~p ~n", [Msg]), + ct:print("Upgrade Client Msg: ~p ~n", [Msg]), Pid ! {self(), Msg}, receive close -> - test_server:format("Upgrade Client closing~n", []), + ct:print("Upgrade Client closing~n", []), rpc:call(Node, ssl, close, [SslSocket]) end. @@ -485,20 +490,20 @@ run_upgrade_server_error(Opts) -> SslOptions = proplists:get_value(ssl_options, Opts), Pid = proplists:get_value(from, Opts), - test_server:format("gen_tcp:listen(~p, ~p)~n", [Port, TcpOptions]), + ct:print("gen_tcp:listen(~p, ~p)~n", [Port, TcpOptions]), {ok, ListenSocket} = rpc:call(Node, gen_tcp, listen, [Port, TcpOptions]), Pid ! {listen, up}, send_selected_port(Pid, Port, ListenSocket), - test_server:format("gen_tcp:accept(~p)~n", [ListenSocket]), + ct:print("gen_tcp:accept(~p)~n", [ListenSocket]), {ok, AcceptSocket} = rpc:call(Node, gen_tcp, accept, [ListenSocket]), Error = case TimeOut of infinity -> - test_server:format("ssl:ssl_accept(~p, ~p)~n", + ct:print("ssl:ssl_accept(~p, ~p)~n", [AcceptSocket, SslOptions]), rpc:call(Node, ssl, ssl_accept, [AcceptSocket, SslOptions]); _ -> - test_server:format("ssl:ssl_accept(~p, ~p, ~p)~n", + ct:print("ssl:ssl_accept(~p, ~p, ~p)~n", [AcceptSocket, SslOptions, TimeOut]), rpc:call(Node, ssl, ssl_accept, [AcceptSocket, SslOptions, TimeOut]) @@ -517,22 +522,31 @@ run_server_error(Opts) -> Port = proplists:get_value(port, Opts), Options = proplists:get_value(options, Opts), Pid = proplists:get_value(from, Opts), - test_server:format("ssl:listen(~p, ~p)~n", [Port, Options]), - case rpc:call(Node, ssl, listen, [Port, Options]) of - {ok, ListenSocket} -> + Transport = proplists:get_value(transport, Opts, ssl), + ct:print("ssl:listen(~p, ~p)~n", [Port, Options]), + case rpc:call(Node, Transport, listen, [Port, Options]) of + {ok, #sslsocket{} = ListenSocket} -> %% To make sure error_client will %% get {error, closed} and not {error, connection_refused} Pid ! {listen, up}, send_selected_port(Pid, Port, ListenSocket), - test_server:format("ssl:transport_accept(~p)~n", [ListenSocket]), - case rpc:call(Node, ssl, transport_accept, [ListenSocket]) of + ct:print("ssl:transport_accept(~p)~n", [ListenSocket]), + case rpc:call(Node, Transport, transport_accept, [ListenSocket]) of {error, _} = Error -> Pid ! {self(), Error}; {ok, AcceptSocket} -> - test_server:format("ssl:ssl_accept(~p)~n", [AcceptSocket]), + ct:print("ssl:ssl_accept(~p)~n", [AcceptSocket]), Error = rpc:call(Node, ssl, ssl_accept, [AcceptSocket]), Pid ! {self(), Error} end; + {ok, ListenSocket} -> + Pid ! {listen, up}, + send_selected_port(Pid, Port, ListenSocket), + ct:print("~p:accept(~p)~n", [Transport, ListenSocket]), + case rpc:call(Node, Transport, accept, [ListenSocket]) of + {error, _} = Error -> + Pid ! {self(), Error} + end; Error -> %% Not really true but as this is an error test %% this is what we want. @@ -548,9 +562,10 @@ run_client_error(Opts) -> Host = proplists:get_value(host, Opts), Port = proplists:get_value(port, Opts), Pid = proplists:get_value(from, Opts), + Transport = proplists:get_value(transport, Opts, ssl), Options = proplists:get_value(options, Opts), - test_server:format("ssl:connect(~p, ~p, ~p)~n", [Host, Port, Options]), - Error = rpc:call(Node, ssl, connect, [Host, Port, Options]), + ct:print("ssl:connect(~p, ~p, ~p)~n", [Host, Port, Options]), + Error = rpc:call(Node, Transport, connect, [Host, Port, Options]), Pid ! {self(), Error}. inet_port(Pid) when is_pid(Pid)-> @@ -577,7 +592,7 @@ trigger_renegotiate(Socket, [ErlData, N]) -> trigger_renegotiate(Socket, ErlData, N, Id). trigger_renegotiate(Socket, _, 0, Id) -> - test_server:sleep(1000), + ct:sleep(1000), case ssl:session_info(Socket) of [{session_id, Id} | _ ] -> fail_session_not_renegotiated; @@ -670,7 +685,7 @@ der_to_pem(File, Entries) -> cipher_result(Socket, Result) -> Result = ssl:connection_info(Socket), - test_server:format("Successfull connect: ~p~n", [Result]), + ct:print("Successfull connect: ~p~n", [Result]), %% Importante to send two packets here %% to properly test "cipher state" handling ssl:send(Socket, "Hello\n"), @@ -751,3 +766,33 @@ sufficient_crypto_support('tlsv1.2') -> end; sufficient_crypto_support(_) -> true. + +send_recv_result_active(Socket) -> + ssl:send(Socket, "Hello world"), + receive + {ssl, Socket, "H"} -> + receive + {ssl, Socket, "ello world"} -> + ok + end; + {ssl, Socket, "Hello world"} -> + ok + end. + +send_recv_result(Socket) -> + ssl:send(Socket, "Hello world"), + {ok,"Hello world"} = ssl:recv(Socket, 11), + ok. + +send_recv_result_active_once(Socket) -> + ssl:send(Socket, "Hello world"), + receive + {ssl, Socket, "H"} -> + ssl:setopts(Socket, [{active, once}]), + receive + {ssl, Socket, "ello world"} -> + ok + end; + {ssl, Socket, "Hello world"} -> + ok + end. diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl index 107220c335..d5e7d515fd 100644 --- a/lib/ssl/test/ssl_to_openssl_SUITE.erl +++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2012. All Rights Reserved. +%% Copyright Ericsson AB 2008-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -16,7 +16,6 @@ %% %% %CopyrightEnd% %% - %% -module(ssl_to_openssl_SUITE). @@ -34,131 +33,10 @@ -define(OPENSSL_GARBAGE, "P\n"). -define(EXPIRE, 10). -%% Test server callback functions %%-------------------------------------------------------------------- -%% Function: init_per_suite(Config) -> Config -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% Description: Initialization before the whole suite -%% -%% Note: This function is free to add any key/value pairs to the Config -%% variable, but should NOT alter/remove any existing entries. +%% Common Test interface functions ----------------------------------- %%-------------------------------------------------------------------- -init_per_suite(Config0) -> - Dog = ssl_test_lib:timetrap(?LONG_TIMEOUT *2), - case os:find_executable("openssl") of - false -> - {skip, "Openssl not found"}; - _ -> - catch crypto:stop(), - try crypto:start() of - ok -> - application:start(public_key), - ssl:start(), - Result = - (catch make_certs:all(?config(data_dir, Config0), - ?config(priv_dir, Config0))), - test_server:format("Make certs ~p~n", [Result]), - Config1 = ssl_test_lib:make_dsa_cert(Config0), - Config = ssl_test_lib:cert_options(Config1), - [{watchdog, Dog} | Config] - catch _:_ -> - {skip, "Crypto did not start"} - end - end. -%%-------------------------------------------------------------------- -%% Function: end_per_suite(Config) -> _ -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% Description: Cleanup after the whole suite -%%-------------------------------------------------------------------- -end_per_suite(_Config) -> - ssl:stop(), - application:stop(crypto). - -%%-------------------------------------------------------------------- -%% Function: init_per_testcase(TestCase, Config) -> Config -%% Case - atom() -%% Name of the test case that is about to be run. -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% -%% Description: Initialization before each test case -%% -%% Note: This function is free to add any key/value pairs to the Config -%% variable, but should NOT alter/remove any existing entries. -%% Description: Initialization before each test case -%%-------------------------------------------------------------------- -init_per_testcase(expired_session, Config0) -> - Config = lists:keydelete(watchdog, 1, Config0), - Dog = ssl_test_lib:timetrap(?EXPIRE * 1000 * 5), - ssl:stop(), - application:load(ssl), - application:set_env(ssl, session_lifetime, ?EXPIRE), - ssl:start(), - [{watchdog, Dog} | Config]; - -init_per_testcase(TestCase, Config0) -> - Config = lists:keydelete(watchdog, 1, Config0), - Dog = ssl_test_lib:timetrap(?TIMEOUT), - special_init(TestCase, [{watchdog, Dog} | Config]). - -special_init(TestCase, Config) - when TestCase == erlang_client_openssl_server_renegotiate; - TestCase == erlang_client_openssl_server_nowrap_seqnum; - TestCase == erlang_server_openssl_client_nowrap_seqnum - -> - check_sane_openssl_renegotaite(Config); - -special_init(ssl2_erlang_server_openssl_client, Config) -> - check_sane_openssl_sslv2(Config); - -special_init(TestCase, Config) - when TestCase == erlang_client_openssl_server_npn; - TestCase == erlang_server_openssl_client_npn; - TestCase == erlang_server_openssl_client_npn_renegotiate; - TestCase == erlang_client_openssl_server_npn_renegotiate; - TestCase == erlang_server_openssl_client_npn_only_server; - TestCase == erlang_server_openssl_client_npn_only_client; - TestCase == erlang_client_openssl_server_npn_only_client; - TestCase == erlang_client_openssl_server_npn_only_server -> - check_openssl_npn_support(Config); - -special_init(_, Config) -> - Config. - -%%-------------------------------------------------------------------- -%% Function: end_per_testcase(TestCase, Config) -> _ -%% Case - atom() -%% Name of the test case that is about to be run. -%% Config - [tuple()] -%% A list of key/value pairs, holding the test case configuration. -%% Description: Cleanup after each test case -%%-------------------------------------------------------------------- -end_per_testcase(reuse_session_expired, Config) -> - application:unset_env(ssl, session_lifetime), - end_per_testcase(default_action, Config); - -end_per_testcase(default_action, Config) -> - Dog = ?config(watchdog, Config), - case Dog of - undefined -> - ok; - _ -> - test_server:timetrap_cancel(Dog) - end; -end_per_testcase(_, Config) -> - end_per_testcase(default_action, Config). - -%%-------------------------------------------------------------------- -%% Function: all(Clause) -> TestCases -%% Clause - atom() - suite | doc -%% TestCases - [Case] -%% Case - atom() -%% Name of a test case. -%% Description: Returns a list of all test cases in this test suite -%%-------------------------------------------------------------------- suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> @@ -211,6 +89,34 @@ npn_tests() -> erlang_client_openssl_server_npn_only_client, erlang_client_openssl_server_npn_only_server]. + +init_per_suite(Config0) -> + Dog = ct:timetrap(?LONG_TIMEOUT *2), + case os:find_executable("openssl") of + false -> + {skip, "Openssl not found"}; + _ -> + catch crypto:stop(), + try crypto:start() of + ok -> + application:start(public_key), + ssl:start(), + Result = + (catch make_certs:all(?config(data_dir, Config0), + ?config(priv_dir, Config0))), + ct:print("Make certs ~p~n", [Result]), + Config1 = ssl_test_lib:make_dsa_cert(Config0), + Config = ssl_test_lib:cert_options(Config1), + [{watchdog, Dog} | Config] + catch _:_ -> + {skip, "Crypto did not start"} + end + end. + +end_per_suite(_Config) -> + ssl:stop(), + application:stop(crypto). + init_per_group(GroupName, Config) -> case ssl_test_lib:is_tls_version(GroupName) of true -> @@ -229,13 +135,55 @@ init_per_group(GroupName, Config) -> end_per_group(_GroupName, Config) -> Config. +init_per_testcase(expired_session, Config0) -> + Config = lists:keydelete(watchdog, 1, Config0), + Dog = ct:timetrap(?EXPIRE * 1000 * 5), + ssl:stop(), + application:load(ssl), + application:set_env(ssl, session_lifetime, ?EXPIRE), + ssl:start(), + [{watchdog, Dog} | Config]; + +init_per_testcase(TestCase, Config0) -> + Config = lists:keydelete(watchdog, 1, Config0), + Dog = ct:timetrap(?TIMEOUT), + special_init(TestCase, [{watchdog, Dog} | Config]). + +special_init(TestCase, Config) + when TestCase == erlang_client_openssl_server_renegotiate; + TestCase == erlang_client_openssl_server_nowrap_seqnum; + TestCase == erlang_server_openssl_client_nowrap_seqnum + -> + check_sane_openssl_renegotaite(Config); + +special_init(ssl2_erlang_server_openssl_client, Config) -> + check_sane_openssl_sslv2(Config); + +special_init(TestCase, Config) + when TestCase == erlang_client_openssl_server_npn; + TestCase == erlang_server_openssl_client_npn; + TestCase == erlang_server_openssl_client_npn_renegotiate; + TestCase == erlang_client_openssl_server_npn_renegotiate; + TestCase == erlang_server_openssl_client_npn_only_server; + TestCase == erlang_server_openssl_client_npn_only_client; + TestCase == erlang_client_openssl_server_npn_only_client; + TestCase == erlang_client_openssl_server_npn_only_server -> + check_openssl_npn_support(Config); + +special_init(_, Config) -> + Config. + +end_per_testcase(reuse_session_expired, Config) -> + application:unset_env(ssl, session_lifetime), + Config; +end_per_testcase(_, Config) -> + Config. -%% Test cases starts here. %%-------------------------------------------------------------------- -basic_erlang_client_openssl_server(doc) -> - ["Test erlang client with openssl server"]; -basic_erlang_client_openssl_server(suite) -> - []; +%% Test Cases -------------------------------------------------------- +%%-------------------------------------------------------------------- +basic_erlang_client_openssl_server() -> + [{doc,"Test erlang client with openssl server"}]. basic_erlang_client_openssl_server(Config) when is_list(Config) -> process_flag(trap_exit, true), ServerOpts = ?config(server_opts, Config), @@ -252,7 +200,7 @@ basic_erlang_client_openssl_server(Config) when is_list(Config) -> Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ " -cert " ++ CertFile ++ " -key " ++ KeyFile, - test_server:format("openssl cmd: ~p~n", [Cmd]), + ct:print("openssl cmd: ~p~n", [Cmd]), OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), @@ -271,14 +219,11 @@ basic_erlang_client_openssl_server(Config) when is_list(Config) -> %% Clean close down! Server needs to be closed first !! close_port(OpensslPort), ssl_test_lib:close(Client), - process_flag(trap_exit, false), - ok. + process_flag(trap_exit, false). %%-------------------------------------------------------------------- -basic_erlang_server_openssl_client(doc) -> - ["Test erlang server with openssl client"]; -basic_erlang_server_openssl_client(suite) -> - []; +basic_erlang_server_openssl_client() -> + [{doc,"Test erlang server with openssl client"}]. basic_erlang_server_openssl_client(Config) when is_list(Config) -> process_flag(trap_exit, true), ServerOpts = ?config(server_opts, Config), @@ -296,7 +241,7 @@ basic_erlang_server_openssl_client(Config) when is_list(Config) -> Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++ " -host localhost", - test_server:format("openssl cmd: ~p~n", [Cmd]), + ct:print("openssl cmd: ~p~n", [Cmd]), OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), port_command(OpenSslPort, Data), @@ -309,10 +254,8 @@ basic_erlang_server_openssl_client(Config) when is_list(Config) -> process_flag(trap_exit, false), ok. %%-------------------------------------------------------------------- -erlang_client_openssl_server(doc) -> - ["Test erlang client with openssl server"]; -erlang_client_openssl_server(suite) -> - []; +erlang_client_openssl_server() -> + [{doc,"Test erlang client with openssl server"}]. erlang_client_openssl_server(Config) when is_list(Config) -> process_flag(trap_exit, true), ServerOpts = ?config(server_opts, Config), @@ -329,7 +272,7 @@ erlang_client_openssl_server(Config) when is_list(Config) -> Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ version_flag(Version) ++ " -cert " ++ CertFile ++ " -key " ++ KeyFile, - test_server:format("openssl cmd: ~p~n", [Cmd]), + ct:print("openssl cmd: ~p~n", [Cmd]), OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), @@ -348,15 +291,11 @@ erlang_client_openssl_server(Config) when is_list(Config) -> %% Clean close down! Server needs to be closed first !! close_port(OpensslPort), ssl_test_lib:close(Client), - process_flag(trap_exit, false), - ok. - + process_flag(trap_exit, false). %%-------------------------------------------------------------------- -erlang_server_openssl_client(doc) -> - ["Test erlang server with openssl client"]; -erlang_server_openssl_client(suite) -> - []; +erlang_server_openssl_client() -> + [{doc,"Test erlang server with openssl client"}]. erlang_server_openssl_client(Config) when is_list(Config) -> process_flag(trap_exit, true), ServerOpts = ?config(server_opts, Config), @@ -375,7 +314,7 @@ erlang_server_openssl_client(Config) when is_list(Config) -> Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++ version_flag(Version) ++ " -host localhost", - test_server:format("openssl cmd: ~p~n", [Cmd]), + ct:print("openssl cmd: ~p~n", [Cmd]), OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), port_command(OpenSslPort, Data), @@ -385,15 +324,12 @@ erlang_server_openssl_client(Config) when is_list(Config) -> %% Clean close down! Server needs to be closed first !! ssl_test_lib:close(Server), close_port(OpenSslPort), - process_flag(trap_exit, false), - ok. + process_flag(trap_exit, false). %%-------------------------------------------------------------------- -erlang_client_openssl_server_dsa_cert(doc) -> - ["Test erlang server with openssl client"]; -erlang_client_openssl_server_dsa_cert(suite) -> - []; +erlang_client_openssl_server_dsa_cert() -> + [{doc,"Test erlang server with openssl client"}]. erlang_client_openssl_server_dsa_cert(Config) when is_list(Config) -> process_flag(trap_exit, true), ClientOpts = ?config(client_dsa_opts, Config), @@ -413,7 +349,7 @@ erlang_client_openssl_server_dsa_cert(Config) when is_list(Config) -> " -cert " ++ CertFile ++ " -CAfile " ++ CaCertFile ++ " -key " ++ KeyFile ++ " -Verify 2 -msg", - test_server:format("openssl cmd: ~p~n", [Cmd]), + ct:print("openssl cmd: ~p~n", [Cmd]), OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), @@ -436,10 +372,8 @@ erlang_client_openssl_server_dsa_cert(Config) when is_list(Config) -> process_flag(trap_exit, false), ok. %%-------------------------------------------------------------------- -erlang_server_openssl_client_dsa_cert(doc) -> - ["Test erlang server with openssl client"]; -erlang_server_openssl_client_dsa_cert(suite) -> - []; +erlang_server_openssl_client_dsa_cert() -> + [{doc,"Test erlang server with openssl client"}]. erlang_server_openssl_client_dsa_cert(Config) when is_list(Config) -> process_flag(trap_exit, true), ClientOpts = ?config(client_dsa_opts, Config), @@ -462,7 +396,7 @@ erlang_server_openssl_client_dsa_cert(Config) when is_list(Config) -> " -host localhost " ++ " -cert " ++ CertFile ++ " -CAfile " ++ CaCertFile ++ " -key " ++ KeyFile ++ " -msg", - test_server:format("openssl cmd: ~p~n", [Cmd]), + ct:print("openssl cmd: ~p~n", [Cmd]), OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), port_command(OpenSslPort, Data), @@ -472,16 +406,13 @@ erlang_server_openssl_client_dsa_cert(Config) when is_list(Config) -> %% Clean close down! Server needs to be closed first !! ssl_test_lib:close(Server), close_port(OpenSslPort), - process_flag(trap_exit, false), - ok. + process_flag(trap_exit, false). %%-------------------------------------------------------------------- -erlang_server_openssl_client_reuse_session(doc) -> - ["Test erlang server with openssl client that reconnects with the" - "same session id, to test reusing of sessions."]; -erlang_server_openssl_client_reuse_session(suite) -> - []; +erlang_server_openssl_client_reuse_session() -> + [{doc, "Test erlang server with openssl client that reconnects with the" + "same session id, to test reusing of sessions."}]. erlang_server_openssl_client_reuse_session(Config) when is_list(Config) -> process_flag(trap_exit, true), ServerOpts = ?config(server_opts, Config), @@ -500,7 +431,7 @@ erlang_server_openssl_client_reuse_session(Config) when is_list(Config) -> Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++ version_flag(Version) ++ " -host localhost -reconnect", - test_server:format("openssl cmd: ~p~n", [Cmd]), + ct:print("openssl cmd: ~p~n", [Cmd]), OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), @@ -516,10 +447,8 @@ erlang_server_openssl_client_reuse_session(Config) when is_list(Config) -> %%-------------------------------------------------------------------- -erlang_client_openssl_server_renegotiate(doc) -> - ["Test erlang client when openssl server issuses a renegotiate"]; -erlang_client_openssl_server_renegotiate(suite) -> - []; +erlang_client_openssl_server_renegotiate() -> + [{doc,"Test erlang client when openssl server issuses a renegotiate"}]. erlang_client_openssl_server_renegotiate(Config) when is_list(Config) -> process_flag(trap_exit, true), ServerOpts = ?config(server_opts, Config), @@ -538,7 +467,7 @@ erlang_client_openssl_server_renegotiate(Config) when is_list(Config) -> Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ version_flag(Version) ++ " -cert " ++ CertFile ++ " -key " ++ KeyFile ++ " -msg", - test_server:format("openssl cmd: ~p~n", [Cmd]), + ct:print("openssl cmd: ~p~n", [Cmd]), OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), @@ -552,7 +481,7 @@ erlang_client_openssl_server_renegotiate(Config) when is_list(Config) -> {options, ClientOpts}]), port_command(OpensslPort, ?OPENSSL_RENEGOTIATE), - test_server:sleep(?SLEEP), + ct:sleep(?SLEEP), port_command(OpensslPort, OpenSslData), ssl_test_lib:check_result(Client, ok), @@ -565,13 +494,11 @@ erlang_client_openssl_server_renegotiate(Config) when is_list(Config) -> %%-------------------------------------------------------------------- -erlang_client_openssl_server_nowrap_seqnum(doc) -> - ["Test that erlang client will renegotiate session when", +erlang_client_openssl_server_nowrap_seqnum() -> + [{doc, "Test that erlang client will renegotiate session when", "max sequence number celing is about to be reached. Although" "in the testcase we use the test option renegotiate_at" - " to lower treashold substantially."]; -erlang_client_openssl_server_nowrap_seqnum(suite) -> - []; + " to lower treashold substantially."}]. erlang_client_openssl_server_nowrap_seqnum(Config) when is_list(Config) -> process_flag(trap_exit, true), ServerOpts = ?config(server_opts, Config), @@ -589,7 +516,7 @@ erlang_client_openssl_server_nowrap_seqnum(Config) when is_list(Config) -> Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ version_flag(Version) ++ " -cert " ++ CertFile ++ " -key " ++ KeyFile ++ " -msg", - test_server:format("openssl cmd: ~p~n", [Cmd]), + ct:print("openssl cmd: ~p~n", [Cmd]), OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), @@ -608,17 +535,13 @@ erlang_client_openssl_server_nowrap_seqnum(Config) when is_list(Config) -> %% Clean close down! Server needs to be closed first !! close_port(OpensslPort), ssl_test_lib:close(Client), - process_flag(trap_exit, false), - ok. + process_flag(trap_exit, false). %%-------------------------------------------------------------------- -erlang_server_openssl_client_nowrap_seqnum(doc) -> - ["Test that erlang client will renegotiate session when", +erlang_server_openssl_client_nowrap_seqnum() -> + [{doc, "Test that erlang client will renegotiate session when", "max sequence number celing is about to be reached. Although" "in the testcase we use the test option renegotiate_at" - " to lower treashold substantially."]; - -erlang_server_openssl_client_nowrap_seqnum(suite) -> - []; + " to lower treashold substantially."}]. erlang_server_openssl_client_nowrap_seqnum(Config) when is_list(Config) -> process_flag(trap_exit, true), ServerOpts = ?config(server_opts, Config), @@ -639,7 +562,7 @@ erlang_server_openssl_client_nowrap_seqnum(Config) when is_list(Config) -> Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++ version_flag(Version) ++ " -host localhost -msg", - test_server:format("openssl cmd: ~p~n", [Cmd]), + ct:print("openssl cmd: ~p~n", [Cmd]), OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), @@ -650,16 +573,14 @@ erlang_server_openssl_client_nowrap_seqnum(Config) when is_list(Config) -> %% Clean close down! Server needs to be closed first !! ssl_test_lib:close(Server), close_port(OpenSslPort), - process_flag(trap_exit, false), - ok. + process_flag(trap_exit, false). + %%-------------------------------------------------------------------- -erlang_client_openssl_server_no_server_ca_cert(doc) -> - ["Test erlang client when openssl server sends a cert chain not" +erlang_client_openssl_server_no_server_ca_cert() -> + [{doc, "Test erlang client when openssl server sends a cert chain not" "including the ca cert. Explicitly test this even if it is" - "implicitly tested eleswhere."]; -erlang_client_openssl_server_no_server_ca_cert(suite) -> - []; + "implicitly tested eleswhere."}]. erlang_client_openssl_server_no_server_ca_cert(Config) when is_list(Config) -> process_flag(trap_exit, true), ServerOpts = ?config(server_opts, Config), @@ -676,7 +597,7 @@ erlang_client_openssl_server_no_server_ca_cert(Config) when is_list(Config) -> Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ version_flag(Version) ++ " -cert " ++ CertFile ++ " -key " ++ KeyFile ++ " -msg", - test_server:format("openssl cmd: ~p~n", [Cmd]), + ct:print("openssl cmd: ~p~n", [Cmd]), OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), @@ -696,14 +617,11 @@ erlang_client_openssl_server_no_server_ca_cert(Config) when is_list(Config) -> %% Clean close down! Server needs to be closed first !! close_port(OpensslPort), ssl_test_lib:close(Client), - process_flag(trap_exit, false), - ok. + process_flag(trap_exit, false). %%-------------------------------------------------------------------- -erlang_client_openssl_server_client_cert(doc) -> - ["Test erlang client with openssl server when client sends cert"]; -erlang_client_openssl_server_client_cert(suite) -> - []; +erlang_client_openssl_server_client_cert() -> + [{doc,"Test erlang client with openssl server when client sends cert"}]. erlang_client_openssl_server_client_cert(Config) when is_list(Config) -> process_flag(trap_exit, true), ServerOpts = ?config(server_verification_opts, Config), @@ -722,7 +640,7 @@ erlang_client_openssl_server_client_cert(Config) when is_list(Config) -> " -cert " ++ CertFile ++ " -CAfile " ++ CaCertFile ++ " -key " ++ KeyFile ++ " -Verify 2", - test_server:format("openssl cmd: ~p~n", [Cmd]), + ct:print("openssl cmd: ~p~n", [Cmd]), OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), @@ -741,15 +659,12 @@ erlang_client_openssl_server_client_cert(Config) when is_list(Config) -> %% Clean close down! Server needs to be closed first !! close_port(OpensslPort), ssl_test_lib:close(Client), - process_flag(trap_exit, false), - ok. + process_flag(trap_exit, false). %%-------------------------------------------------------------------- -erlang_server_openssl_client_client_cert(doc) -> - ["Test erlang server with openssl client when client sends cert"]; -erlang_server_openssl_client_client_cert(suite) -> - []; +erlang_server_openssl_client_client_cert() -> + [{doc,"Test erlang server with openssl client when client sends cert"}]. erlang_server_openssl_client_client_cert(Config) when is_list(Config) -> process_flag(trap_exit, true), ServerOpts = ?config(server_verification_opts, Config), @@ -776,7 +691,7 @@ erlang_server_openssl_client_client_cert(Config) when is_list(Config) -> ++ " -key " ++ KeyFile ++ " -port " ++ integer_to_list(Port) ++ version_flag(Version) ++ " -host localhost", - test_server:format("openssl cmd: ~p~n", [Cmd]), + ct:print("openssl cmd: ~p~n", [Cmd]), OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), port_command(OpenSslPort, Data), @@ -786,16 +701,12 @@ erlang_server_openssl_client_client_cert(Config) when is_list(Config) -> %% Clean close down! Server needs to be closed first !! close_port(OpenSslPort), ssl_test_lib:close(Server), - process_flag(trap_exit, false), - ok. - + process_flag(trap_exit, false). %%-------------------------------------------------------------------- -erlang_server_erlang_client_client_cert(doc) -> - ["Test erlang server with erlang client when client sends cert"]; -erlang_server_erlang_client_client_cert(suite) -> - []; +erlang_server_erlang_client_client_cert() -> + [{doc,"Test erlang server with erlang client when client sends cert"}]. erlang_server_erlang_client_client_cert(Config) when is_list(Config) -> process_flag(trap_exit, true), ServerOpts = ?config(server_verification_opts, Config), @@ -828,30 +739,22 @@ erlang_server_erlang_client_client_cert(Config) when is_list(Config) -> ssl_test_lib:close(Server), ssl_test_lib:close(Client), - process_flag(trap_exit, false), - ok. -%%-------------------------------------------------------------------- + process_flag(trap_exit, false). -ciphers_rsa_signed_certs(doc) -> - ["Test cipher suites that uses rsa certs"]; - -ciphers_rsa_signed_certs(suite) -> - []; +%%-------------------------------------------------------------------- +ciphers_rsa_signed_certs() -> + [{doc,"Test cipher suites that uses rsa certs"}]. ciphers_rsa_signed_certs(Config) when is_list(Config) -> Version = ssl_record:protocol_version(ssl_record:highest_protocol_version([])), Ciphers = ssl_test_lib:rsa_suites(), run_suites(Ciphers, Version, Config, rsa). +%%-------------------------------------------------------------------- - -ciphers_dsa_signed_certs(doc) -> - ["Test cipher suites that uses dsa certs"]; - -ciphers_dsa_signed_certs(suite) -> - []; - +ciphers_dsa_signed_certs() -> + [{doc,"Test cipher suites that uses dsa certs"}]. ciphers_dsa_signed_certs(Config) when is_list(Config) -> Version = ssl_record:protocol_version(ssl_record:highest_protocol_version([])), @@ -859,90 +762,9 @@ ciphers_dsa_signed_certs(Config) when is_list(Config) -> Ciphers = ssl_test_lib:dsa_suites(), run_suites(Ciphers, Version, Config, dsa). -run_suites(Ciphers, Version, Config, Type) -> - {ClientOpts, ServerOpts} = - case Type of - rsa -> - {?config(client_opts, Config), - ?config(server_opts, Config)}; - dsa -> - {?config(client_opts, Config), - ?config(server_dsa_opts, Config)} - end, - - Result = lists:map(fun(Cipher) -> - cipher(Cipher, Version, Config, ClientOpts, ServerOpts) end, - Ciphers), - case lists:flatten(Result) of - [] -> - ok; - Error -> - test_server:format("Cipher suite errors: ~p~n", [Error]), - test_server:fail(cipher_suite_failed_see_test_case_log) - end. - -cipher(CipherSuite, Version, Config, ClientOpts, ServerOpts) -> - process_flag(trap_exit, true), - test_server:format("Testing CipherSuite ~p~n", [CipherSuite]), - {ClientNode, _ServerNode, Hostname} = ssl_test_lib:run_where(Config), - - Port = ssl_test_lib:inet_port(node()), - CertFile = proplists:get_value(certfile, ServerOpts), - KeyFile = proplists:get_value(keyfile, ServerOpts), - - Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ version_flag(Version) ++ - " -cert " ++ CertFile ++ " -key " ++ KeyFile ++ "", - - test_server:format("openssl cmd: ~p~n", [Cmd]), - - OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), - - wait_for_openssl_server(), - - ConnectionInfo = {ok, {Version, CipherSuite}}, - - Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, - {host, Hostname}, - {from, self()}, - {mfa, {ssl_test_lib, cipher_result, [ConnectionInfo]}}, - {options, - [{ciphers,[CipherSuite]} | - ClientOpts]}]), - - port_command(OpenSslPort, "Hello\n"), - - receive - {Port, {data, _}} when is_port(Port) -> - ok - after 500 -> - test_server:format("Time out on openssl port, check that" - " the messages Hello and world are received" - " during close of port" , []), - ok - end, - - port_command(OpenSslPort, " world\n"), - - Result = ssl_test_lib:wait_for_result(Client, ok), - - %% Clean close down! Server needs to be closed first !! - close_port(OpenSslPort), - ssl_test_lib:close(Client), - - Return = case Result of - ok -> - []; - Error -> - [{CipherSuite, Error}] - end, - process_flag(trap_exit, false), - Return. - %%-------------------------------------------------------------------- -erlang_client_bad_openssl_server(doc) -> - [""]; -erlang_client_bad_openssl_server(suite) -> - []; +erlang_client_bad_openssl_server() -> + [{doc,"Test what happens if openssl server sends garbage to erlang ssl client"}]. erlang_client_bad_openssl_server(Config) when is_list(Config) -> process_flag(trap_exit, true), ServerOpts = ?config(server_verification_opts, Config), @@ -957,7 +779,7 @@ erlang_client_bad_openssl_server(Config) when is_list(Config) -> Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ version_flag(Version) ++ " -cert " ++ CertFile ++ " -key " ++ KeyFile ++ "", - test_server:format("openssl cmd: ~p~n", [Cmd]), + ct:print("openssl cmd: ~p~n", [Cmd]), OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), @@ -973,7 +795,7 @@ erlang_client_bad_openssl_server(Config) when is_list(Config) -> %% Send garbage port_command(OpensslPort, ?OPENSSL_GARBAGE), - test_server:sleep(?SLEEP), + ct:sleep(?SLEEP), Client0 ! server_sent_garbage, @@ -997,13 +819,9 @@ erlang_client_bad_openssl_server(Config) when is_list(Config) -> %%-------------------------------------------------------------------- -expired_session(doc) -> - ["Test our ssl client handling of expired sessions. Will make" - "better code coverage of the ssl_manager module"]; - -expired_session(suite) -> - []; - +expired_session() -> + [{doc, "Test our ssl client handling of expired sessions. Will make" + "better code coverage of the ssl_manager module"}]. expired_session(Config) when is_list(Config) -> process_flag(trap_exit, true), ClientOpts = ?config(client_opts, Config), @@ -1017,7 +835,7 @@ expired_session(Config) when is_list(Config) -> Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ " -cert " ++ CertFile ++ " -key " ++ KeyFile ++ "", - test_server:format("openssl cmd: ~p~n", [Cmd]), + ct:print("openssl cmd: ~p~n", [Cmd]), OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), @@ -1032,7 +850,7 @@ expired_session(Config) when is_list(Config) -> ssl_test_lib:close(Client0), %% Make sure session is registered - test_server:sleep(?SLEEP), + ct:sleep(?SLEEP), Client1 = ssl_test_lib:start_client([{node, ClientNode}, @@ -1042,7 +860,7 @@ expired_session(Config) when is_list(Config) -> ssl_test_lib:close(Client1), %% Make sure session is unregistered due to expiration - test_server:sleep((?EXPIRE+1) * 1000), + ct:sleep((?EXPIRE+1) * 1000), Client2 = ssl_test_lib:start_client([{node, ClientNode}, @@ -1056,10 +874,9 @@ expired_session(Config) when is_list(Config) -> process_flag(trap_exit, false). %%-------------------------------------------------------------------- -ssl2_erlang_server_openssl_client(doc) -> - ["Test that ssl v2 clients are rejected"]; -ssl2_erlang_server_openssl_client(suite) -> - []; +ssl2_erlang_server_openssl_client() -> + [{doc,"Test that ssl v2 clients are rejected"}]. + ssl2_erlang_server_openssl_client(Config) when is_list(Config) -> process_flag(trap_exit, true), ServerOpts = ?config(server_opts, Config), @@ -1076,7 +893,7 @@ ssl2_erlang_server_openssl_client(Config) when is_list(Config) -> Cmd = "openssl s_client -port " ++ integer_to_list(Port) ++ " -host localhost -ssl2 -msg", - test_server:format("openssl cmd: ~p~n", [Cmd]), + ct:print("openssl cmd: ~p~n", [Cmd]), OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), port_command(OpenSslPort, Data), @@ -1089,10 +906,9 @@ ssl2_erlang_server_openssl_client(Config) when is_list(Config) -> process_flag(trap_exit, false). %%-------------------------------------------------------------------- -erlang_client_openssl_server_npn(doc) -> - ["Test erlang client with openssl server doing npn negotiation"]; -erlang_client_openssl_server_npn(suite) -> - []; +erlang_client_openssl_server_npn() -> + [{doc,"Test erlang client with openssl server doing npn negotiation"}]. + erlang_client_openssl_server_npn(Config) when is_list(Config) -> Data = "From openssl to erlang", start_erlang_client_and_openssl_server_for_npn_negotiation(Config, Data, fun(Client, OpensslPort) -> @@ -1100,33 +916,25 @@ erlang_client_openssl_server_npn(Config) when is_list(Config) -> ssl_test_lib:check_result(Client, ok) end), - ok. - %%-------------------------------------------------------------------- -erlang_client_openssl_server_npn_renegotiate(doc) -> - ["Test erlang client with openssl server doing npn negotiation and renegotiate"]; -erlang_client_openssl_server_npn_renegotiate(suite) -> - []; +erlang_client_openssl_server_npn_renegotiate() -> + [{doc,"Test erlang client with openssl server doing npn negotiation and renegotiate"}]. + erlang_client_openssl_server_npn_renegotiate(Config) when is_list(Config) -> Data = "From openssl to erlang", start_erlang_client_and_openssl_server_for_npn_negotiation(Config, Data, fun(Client, OpensslPort) -> port_command(OpensslPort, ?OPENSSL_RENEGOTIATE), - test_server:sleep(?SLEEP), + ct:sleep(?SLEEP), port_command(OpensslPort, Data), ssl_test_lib:check_result(Client, ok) end), ok. - - %%-------------------------------------------------------------------------- +erlang_server_openssl_client_npn() -> + [{doc,"Test erlang server with openssl client and npn negotiation"}]. - -erlang_server_openssl_client_npn(doc) -> - ["Test erlang server with openssl client and npn negotiation"]; -erlang_server_openssl_client_npn(suite) -> - []; erlang_server_openssl_client_npn(Config) when is_list(Config) -> Data = "From openssl to erlang", @@ -1137,25 +945,23 @@ erlang_server_openssl_client_npn(Config) when is_list(Config) -> ok. %%-------------------------------------------------------------------------- +erlang_server_openssl_client_npn_renegotiate() -> + [{doc,"Test erlang server with openssl client and npn negotiation with renegotiation"}]. -erlang_server_openssl_client_npn_renegotiate(doc) -> - ["Test erlang server with openssl client and npn negotiation with renegotiation"]; -erlang_server_openssl_client_npn_renegotiate(suite) -> - []; erlang_server_openssl_client_npn_renegotiate(Config) when is_list(Config) -> Data = "From openssl to erlang", start_erlang_server_and_openssl_client_for_npn_negotiation(Config, Data, fun(Server, OpensslPort) -> port_command(OpensslPort, ?OPENSSL_RENEGOTIATE), - test_server:sleep(?SLEEP), + ct:sleep(?SLEEP), port_command(OpensslPort, Data), ssl_test_lib:check_result(Server, ok) end), ok. %%-------------------------------------------------------------------------- - erlang_client_openssl_server_npn_only_server(Config) when is_list(Config) -> Data = "From openssl to erlang", - start_erlang_client_and_openssl_server_with_opts(Config, [], "-nextprotoneg spdy/2", Data, fun(Server, OpensslPort) -> + start_erlang_client_and_openssl_server_with_opts(Config, [], + "-nextprotoneg spdy/2", Data, fun(Server, OpensslPort) -> port_command(OpensslPort, Data), ssl_test_lib:check_result(Server, ok) end), @@ -1165,7 +971,10 @@ erlang_client_openssl_server_npn_only_server(Config) when is_list(Config) -> erlang_client_openssl_server_npn_only_client(Config) when is_list(Config) -> Data = "From openssl to erlang", - start_erlang_client_and_openssl_server_with_opts(Config, [{client_preferred_next_protocols, {client, [<<"spdy/2">>], <<"http/1.1">>}}], "", Data, fun(Server, OpensslPort) -> + start_erlang_client_and_openssl_server_with_opts(Config, + [{client_preferred_next_protocols, + {client, [<<"spdy/2">>], <<"http/1.1">>}}], "", + Data, fun(Server, OpensslPort) -> port_command(OpensslPort, Data), ssl_test_lib:check_result(Server, ok) end), @@ -1174,7 +983,8 @@ erlang_client_openssl_server_npn_only_client(Config) when is_list(Config) -> %%-------------------------------------------------------------------------- erlang_server_openssl_client_npn_only_server(Config) when is_list(Config) -> Data = "From openssl to erlang", - start_erlang_server_and_openssl_client_with_opts(Config, [{next_protocols_advertised, [<<"spdy/2">>]}], "", Data, fun(Server, OpensslPort) -> + start_erlang_server_and_openssl_client_with_opts(Config, [{next_protocols_advertised, [<<"spdy/2">>]}], "", + Data, fun(Server, OpensslPort) -> port_command(OpensslPort, Data), ssl_test_lib:check_result(Server, ok) end), @@ -1182,13 +992,94 @@ erlang_server_openssl_client_npn_only_server(Config) when is_list(Config) -> erlang_server_openssl_client_npn_only_client(Config) when is_list(Config) -> Data = "From openssl to erlang", - start_erlang_server_and_openssl_client_with_opts(Config, [], "-nextprotoneg spdy/2", Data, fun(Server, OpensslPort) -> + start_erlang_server_and_openssl_client_with_opts(Config, [], "-nextprotoneg spdy/2", + Data, fun(Server, OpensslPort) -> port_command(OpensslPort, Data), ssl_test_lib:check_result(Server, ok) end), ok. -%%-------------------------------------------------------------------------- +%%-------------------------------------------------------------------- +%% Internal functions ------------------------------------------------ +%%-------------------------------------------------------------------- +run_suites(Ciphers, Version, Config, Type) -> + {ClientOpts, ServerOpts} = + case Type of + rsa -> + {?config(client_opts, Config), + ?config(server_opts, Config)}; + dsa -> + {?config(client_opts, Config), + ?config(server_dsa_opts, Config)} + end, + + Result = lists:map(fun(Cipher) -> + cipher(Cipher, Version, Config, ClientOpts, ServerOpts) end, + Ciphers), + case lists:flatten(Result) of + [] -> + ok; + Error -> + ct:print("Cipher suite errors: ~p~n", [Error]), + ct:fail(cipher_suite_failed_see_test_case_log) + end. + +cipher(CipherSuite, Version, Config, ClientOpts, ServerOpts) -> + process_flag(trap_exit, true), + ct:print("Testing CipherSuite ~p~n", [CipherSuite]), + {ClientNode, _ServerNode, Hostname} = ssl_test_lib:run_where(Config), + + Port = ssl_test_lib:inet_port(node()), + CertFile = proplists:get_value(certfile, ServerOpts), + KeyFile = proplists:get_value(keyfile, ServerOpts), + + Cmd = "openssl s_server -accept " ++ integer_to_list(Port) ++ version_flag(Version) ++ + " -cert " ++ CertFile ++ " -key " ++ KeyFile ++ "", + + ct:print("openssl cmd: ~p~n", [Cmd]), + + OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), + + wait_for_openssl_server(), + + ConnectionInfo = {ok, {Version, CipherSuite}}, + + Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port}, + {host, Hostname}, + {from, self()}, + {mfa, {ssl_test_lib, cipher_result, [ConnectionInfo]}}, + {options, + [{ciphers,[CipherSuite]} | + ClientOpts]}]), + + port_command(OpenSslPort, "Hello\n"), + + receive + {Port, {data, _}} when is_port(Port) -> + ok + after 500 -> + ct:print("Time out on openssl port, check that" + " the messages Hello and world are received" + " during close of port" , []), + ok + end, + + port_command(OpenSslPort, " world\n"), + + Result = ssl_test_lib:wait_for_result(Client, ok), + + %% Clean close down! Server needs to be closed first !! + close_port(OpenSslPort), + ssl_test_lib:close(Client), + + Return = case Result of + ok -> + []; + Error -> + [{CipherSuite, Error}] + end, + process_flag(trap_exit, false), + Return. start_erlang_client_and_openssl_server_with_opts(Config, ErlangClientOpts, OpensslServerOpts, Data, Callback) -> process_flag(trap_exit, true), @@ -1209,7 +1100,7 @@ start_erlang_client_and_openssl_server_with_opts(Config, ErlangClientOpts, Opens integer_to_list(Port) ++ version_flag(Version) ++ " -cert " ++ CertFile ++ " -key " ++ KeyFile, - test_server:format("openssl cmd: ~p~n", [Cmd]), + ct:print("openssl cmd: ~p~n", [Cmd]), OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), @@ -1248,7 +1139,7 @@ start_erlang_client_and_openssl_server_for_npn_negotiation(Config, Data, Callbac Cmd = "openssl s_server -msg -nextprotoneg http/1.1,spdy/2 -accept " ++ integer_to_list(Port) ++ version_flag(Version) ++ " -cert " ++ CertFile ++ " -key " ++ KeyFile, - test_server:format("openssl cmd: ~p~n", [Cmd]), + ct:print("openssl cmd: ~p~n", [Cmd]), OpensslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), @@ -1286,7 +1177,7 @@ start_erlang_server_and_openssl_client_for_npn_negotiation(Config, Data, Callbac Cmd = "openssl s_client -nextprotoneg http/1.0,spdy/2 -msg -port " ++ integer_to_list(Port) ++ version_flag(Version) ++ " -host localhost", - test_server:format("openssl cmd: ~p~n", [Cmd]), + ct:print("openssl cmd: ~p~n", [Cmd]), OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), @@ -1297,6 +1188,7 @@ start_erlang_server_and_openssl_client_for_npn_negotiation(Config, Data, Callbac close_port(OpenSslPort), process_flag(trap_exit, false). + start_erlang_server_and_openssl_client_with_opts(Config, ErlangServerOpts, OpenSSLClientOpts, Data, Callback) -> process_flag(trap_exit, true), ServerOpts0 = ?config(server_opts, Config), @@ -1314,7 +1206,7 @@ start_erlang_server_and_openssl_client_with_opts(Config, ErlangServerOpts, OpenS Cmd = "openssl s_client " ++ OpenSSLClientOpts ++ " -msg -port " ++ integer_to_list(Port) ++ " -host localhost", - test_server:format("openssl cmd: ~p~n", [Cmd]), + ct:print("openssl cmd: ~p~n", [Cmd]), OpenSslPort = open_port({spawn, Cmd}, [stderr_to_stdout]), @@ -1333,7 +1225,7 @@ erlang_ssl_receive_and_assert_npn(Socket, Protocol, Data) -> ok. erlang_ssl_receive(Socket, Data) -> - test_server:format("Connection info: ~p~n", + ct:print("Connection info: ~p~n", [ssl:connection_info(Socket)]), receive {ssl, Socket, Data} -> @@ -1347,15 +1239,15 @@ erlang_ssl_receive(Socket, Data) -> io:format("openssl ~s~n",[Debug]), erlang_ssl_receive(Socket,Data); Other -> - test_server:fail({unexpected_message, Other}) + ct:fail({unexpected_message, Other}) after 4000 -> - test_server:fail({did_not_get, Data}) + ct:fail({did_not_get, Data}) end. connection_info(Socket, Version) -> case ssl:connection_info(Socket) of {ok, {Version, _} = Info} -> - test_server:format("Connection info: ~p~n", [Info]), + ct:print("Connection info: ~p~n", [Info]), ok; {ok, {OtherVersion, _}} -> {wrong_version, OtherVersion} @@ -1366,7 +1258,7 @@ connection_info_result(Socket) -> delayed_send(Socket, [ErlData, OpenSslData]) -> - test_server:sleep(?SLEEP), + ct:sleep(?SLEEP), ssl:send(Socket, ErlData), erlang_ssl_receive(Socket, OpenSslData). @@ -1418,7 +1310,7 @@ wait_for_openssl_server() -> %% it will be in accept. Parsing %% output is too error prone. (Even %% more so than sleep!) - test_server:sleep(?SLEEP) + ct:sleep(?SLEEP) end. version_flag(tlsv1) -> diff --git a/lib/stdlib/src/c.erl b/lib/stdlib/src/c.erl index a920921a5e..4c1c0f904b 100644 --- a/lib/stdlib/src/c.erl +++ b/lib/stdlib/src/c.erl @@ -116,7 +116,7 @@ machine_load(Mod, File, Opts) -> File2 = filename:join(Dir, filename:basename(File, ".erl")), case compile:output_generated(Opts) of true -> - Base = packages:last(Mod), + Base = atom_to_list(Mod), case filename:basename(File, ".erl") of Base -> code:purge(Mod), diff --git a/lib/stdlib/src/erl_eval.erl b/lib/stdlib/src/erl_eval.erl index 95ba6b1096..8471ae6b64 100644 --- a/lib/stdlib/src/erl_eval.erl +++ b/lib/stdlib/src/erl_eval.erl @@ -227,13 +227,6 @@ expr({bc,_,E,Qs}, Bs, Lf, Ef, RBs) -> expr({tuple,_,Es}, Bs0, Lf, Ef, RBs) -> {Vs,Bs} = expr_list(Es, Bs0, Lf, Ef), ret_expr(list_to_tuple(Vs), Bs, RBs); -expr({record_field,_,_,_}=Mod, Bs, _Lf, _Ef, RBs) -> - case expand_module_name(Mod, Bs) of - {atom,_,A} -> - ret_expr(A, Bs, RBs); %% This is the "x.y" syntax - _ -> - erlang:raise(error, {badexpr, '.'}, stacktrace()) - end; expr({record_field,_,_,Name,_}, _Bs, _Lf, _Ef, _RBs) -> erlang:raise(error, {undef_record,Name}, stacktrace()); expr({record_index,_,Name,_}, _Bs, _Lf, _Ef, _RBs) -> @@ -332,8 +325,7 @@ expr({call,L1,{remote,L2,{record_field,_,{atom,_,''},{atom,_,qlc}=Mod}, Bs, Lf, Ef, RBs) when length(As0) =< 1 -> expr({call,L1,{remote,L2,Mod,Func},As}, Bs, Lf, Ef, RBs); expr({call,_,{remote,_,Mod,Func},As0}, Bs0, Lf, Ef, RBs) -> - Mod1 = expand_module_name(Mod, Bs0), - {value,M,Bs1} = expr(Mod1, Bs0, Lf, Ef, none), + {value,M,Bs1} = expr(Mod, Bs0, Lf, Ef, none), {value,F,Bs2} = expr(Func, Bs0, Lf, Ef, none), {As,Bs3} = expr_list(As0, merge_bindings(Bs1, Bs2), Lf, Ef), %% M could be a parameterized module (not an atom). @@ -1210,41 +1202,6 @@ ret_expr(_Old, New) -> line(Expr) -> element(2, Expr). -%% In syntax trees, module/package names are atoms or lists of atoms. - -expand_module_name({atom,L,A} = M, Bs) -> - case binding({module,A}, Bs) of - {value, A1} -> - {atom,L,A1}; - unbound -> - case packages:is_segmented(A) of - true -> - M; - false -> -%%% P = case binding({module,'$package'}, Bs) of -%%% {value, P1} -> P1; -%%% unbound -> "" -%%% end, -%%% A1 = list_to_atom(packages:concat(P, A)), -%%% {atom,L,list_to_atom(A1)} - {atom,L,A} - end - end; -expand_module_name(M, _) -> - case erl_parse:package_segments(M) of - error -> - M; - M1 -> - L = element(2,M), - Mod = packages:concat(M1), - case packages:is_valid(Mod) of - true -> - {atom,L,list_to_atom(Mod)}; - false -> - erlang:raise(error, {bad_module_name, Mod}, stacktrace()) - end - end. - %% {?MODULE,expr,3} is still the stacktrace, despite the %% fact that expr() now takes two, three or four arguments... stacktrace() -> [{?MODULE,expr,3}]. diff --git a/lib/stdlib/src/erl_expand_records.erl b/lib/stdlib/src/erl_expand_records.erl index 85defacc43..d05f630d8e 100644 --- a/lib/stdlib/src/erl_expand_records.erl +++ b/lib/stdlib/src/erl_expand_records.erl @@ -135,8 +135,6 @@ pattern({tuple,Line,Ps}, St0) -> %%pattern({struct,Line,Tag,Ps}, St0) -> %% {TPs,TPsvs,St1} = pattern_list(Ps, St0), %% {{struct,Line,Tag,TPs},TPsvs,St1}; -pattern({record_field,_,_,_}=M, St) -> - {M,St}; % must be a package name pattern({record_index,Line,Name,Field}, St) -> {index_expr(Line, Field, Name, record_fields(Name, St)),St}; pattern({record,Line,Name,Pfs}, St0) -> @@ -306,8 +304,6 @@ expr({tuple,Line,Es0}, St0) -> %%expr({struct,Line,Tag,Es0}, Vs, St0) -> %% {Es1,Esvs,Esus,St1} = expr_list(Es0, Vs, St0), %% {{struct,Line,Tag,Es1},Esvs,Esus,St1}; -expr({record_field,_,_,_}=M, St) -> - {M,St}; % must be a package name expr({record_index,Line,Name,F}, St) -> I = index_expr(Line, F, Name, record_fields(Name, St)), expr(I, St); @@ -375,9 +371,6 @@ expr({call,Line,{atom,_La,N}=Atom,As0}, St0) -> end end end; -expr({call,Line,{record_field,_,_,_}=M,As0}, St0) -> - {As,St1} = expr_list(As0, St0), - {{call,Line,M,As},St1}; expr({call,Line,{remote,Lr,M,F},As0}, St0) -> {[M1,F1 | As1],St1} = expr_list([M,F | As0], St0), {{call,Line,{remote,Lr,M1,F1},As1},St1}; diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl index 0a442d950f..d24e2fff44 100644 --- a/lib/stdlib/src/erl_lint.erl +++ b/lib/stdlib/src/erl_lint.erl @@ -94,12 +94,10 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) -> %% the other function collections contain {Function, Arity}. -record(lint, {state=start :: 'start' | 'attribute' | 'function', module=[], %Module - package="", %Module package extends=[], %Extends behaviour=[], %Behaviour exports=gb_sets:empty() :: gb_set(), %Exports imports=[], %Imports - mod_imports=dict:new() :: dict(), %Module Imports compile=[], %Compile flags records=dict:new() :: dict(), %Record definitions locals=gb_sets:empty() :: gb_set(), %All defined functions (prescanned) @@ -539,7 +537,6 @@ start(File, Opts) -> end, #lint{state = start, exports = gb_sets:from_list([{module_info,0},{module_info,1}]), - mod_imports = dict:from_list([{erlang,erlang}]), compile = Opts, %% Internal pseudo-functions must appear as defined/reached. defined = gb_sets:from_list(pseudolocals()), @@ -681,8 +678,8 @@ form(Form, #lint{state=State}=St) -> %% start_state(Form, State) -> State' -start_state({attribute,L,module,{M,Ps}}, St) -> - St1 = set_module(M, L, St), +start_state({attribute,_,module,{M,Ps}}, St0) -> + St1 = St0#lint{module=M}, Arity = length(Ps), Ps1 = if is_atom(St1#lint.extends) -> ['BASE', 'THIS' | Ps]; @@ -693,23 +690,13 @@ start_state({attribute,L,module,{M,Ps}}, St) -> St2 = add_instance(Arity, St1), St3 = ensure_new(Arity, St2), St3#lint{state=attribute, extends=[], global_vt=Vt}; -start_state({attribute,L,module,M}, St) -> - St1 = set_module(M, L, St), +start_state({attribute,_,module,M}, St0) -> + St1 = St0#lint{module=M}, St1#lint{state=attribute, extends=[]}; start_state(Form, St) -> St1 = add_error(element(2, Form), undefined_module, St), attribute_state(Form, St1#lint{state=attribute, extends=[]}). -set_module(M, L, St) -> - M1 = package_to_string(M), - case packages:is_valid(M1) of - true -> - St#lint{module=list_to_atom(M1), - package=packages:strip_last(M1)}; - false -> - add_error(L, {bad_module_name, M1}, St) - end. - ensure_new(Arity, St) -> case St#lint.new of true -> @@ -1007,9 +994,9 @@ check_imports(Forms, St0) -> true -> Usage = St0#lint.usage, Unused = ordsets:subtract(St0#lint.imports, Usage#usage.imported), - Imports = [{{FA,list_to_atom(package_to_string(Mod))},L} - || {attribute,L,import,{Mod,Fs}} <- Forms, - FA <- lists:usort(Fs)], + Imports = [{{FA,Mod},L} || + {attribute,L,import,{Mod,Fs}} <- Forms, + FA <- lists:usort(Fs)], Bad = [{FM,L} || FM <- Unused, {FM2,L} <- Imports, FM =:= FM2], func_line_warning(unused_import, Bad, St0) end. @@ -1222,73 +1209,46 @@ export_type(Line, ETs, #lint{usage = Usage, exp_types = ETs0} = St0) -> -spec import(line(), import(), lint_state()) -> lint_state(). import(Line, {Mod,Fs}, St) -> - Mod1 = package_to_string(Mod), - case packages:is_valid(Mod1) of - true -> - Mfs = ordsets:from_list(Fs), - case check_imports(Line, Mfs, St#lint.imports) of - [] -> - St#lint{imports=add_imports(list_to_atom(Mod1), Mfs, - St#lint.imports)}; - Efs -> - {Err, St1} = - foldl(fun ({bif,{F,A},_}, {Err,St0}) -> - %% BifClash - import directive - Warn = is_warn_enabled(bif_clash, St0) - and (not bif_clash_specifically_disabled(St0,{F,A})), - AutoImpSup = is_autoimport_suppressed(St0#lint.no_auto,{F,A}), - OldBif = erl_internal:old_bif(F,A), - {Err,if - Warn and (not AutoImpSup) and OldBif -> - add_error - (Line, - {redefine_old_bif_import, {F,A}}, - St0); - Warn and (not AutoImpSup) -> - add_warning - (Line, - {redefine_bif_import, {F,A}}, - St0); - true -> - St0 - end}; - (Ef, {_Err,St0}) -> - {true,add_error(Line, - {redefine_import,Ef}, - St0)} - end, - {false,St}, Efs), - if - not Err -> - St1#lint{imports= - add_imports(list_to_atom(Mod1), Mfs, + Mfs = ordsets:from_list(Fs), + case check_imports(Line, Mfs, St#lint.imports) of + [] -> + St#lint{imports=add_imports(Mod, Mfs, + St#lint.imports)}; + Efs -> + {Err, St1} = + foldl(fun ({bif,{F,A},_}, {Err,St0}) -> + %% BifClash - import directive + Warn = is_warn_enabled(bif_clash, St0) andalso + (not bif_clash_specifically_disabled(St0,{F,A})), + AutoImpSup = is_autoimport_suppressed(St0#lint.no_auto,{F,A}), + OldBif = erl_internal:old_bif(F,A), + {Err,if + Warn and (not AutoImpSup) and OldBif -> + add_error + (Line, + {redefine_old_bif_import, {F,A}}, + St0); + Warn and (not AutoImpSup) -> + add_warning + (Line, + {redefine_bif_import, {F,A}}, + St0); + true -> + St0 + end}; + (Ef, {_Err,St0}) -> + {true,add_error(Line, + {redefine_import,Ef}, + St0)} + end, + {false,St}, Efs), + if + not Err -> + St1#lint{imports=add_imports(Mod, Mfs, St#lint.imports)}; - true -> - St1 - end - end; - false -> - add_error(Line, {bad_module_name, Mod1}, St) - end; -import(Line, Mod, St) -> - Mod1 = package_to_string(Mod), - case packages:is_valid(Mod1) of - true -> - Key = list_to_atom(packages:last(Mod1)), - Imps = St#lint.mod_imports, -%%% case dict:is_key(Key, Imps) of -%%% true -> -%%% M = packages:last(Mod1), -%%% P = packages:strip_last(Mod1), -%%% add_error(Line, {redefine_mod_import, M, P}, St); -%%% false -> -%%% St#lint{mod_imports = -%%% dict:store(Key, list_to_atom(Mod1), Imps)} -%%% end; - St#lint{mod_imports = dict:store(Key, list_to_atom(Mod1), - Imps)}; - false -> - add_error(Line, {bad_module_name, Mod1}, St) + true -> + St1 + end end. check_imports(_Line, Fs, Is) -> @@ -1463,13 +1423,6 @@ pattern({record_index,Line,Name,Field}, _Vt, _Old, _Bvt, St) -> pattern_field(Field, Name, Dfs, St1) end), {Vt1,[],St1}; -pattern({record_field,Line,_,_}=M, _Vt, _Old, _Bvt, St0) -> - case expand_package(M, St0) of - {error, St1} -> - {[],[],add_error(Line, illegal_expr, St1)}; - {_, St1} -> - {[],[],St1} - end; pattern({record,Line,Name,Pfs}, Vt, Old, Bvt, St) -> case dict:find(Name, St#lint.records) of {ok,{_Line,Fields}} -> @@ -1851,13 +1804,6 @@ gexpr({tuple,_Line,Es}, Vt, St) -> gexpr({record_index,Line,Name,Field}, _Vt, St) -> check_record(Line, Name, St, fun (Dfs, St1) -> record_field(Field, Name, Dfs, St1) end ); -gexpr({record_field,Line,_,_}=M, _Vt, St0) -> - case expand_package(M, St0) of - {error, St1} -> - {[],add_error(Line, illegal_expr, St1)}; - {_, St1} -> - {[], St1} - end; gexpr({record_field,Line,Rec,Name,Field}, Vt, St0) -> {Rvt,St1} = gexpr(Rec, Vt, St0), {Fvt,St2} = check_record(Line, Name, St1, @@ -1996,8 +1942,6 @@ is_gexpr({tuple,_L,Es}, RDs) -> is_gexpr_list(Es, RDs); %% is_gexpr_list(Es, RDs); is_gexpr({record_index,_L,_Name,Field}, RDs) -> is_gexpr(Field, RDs); -is_gexpr({record_field,_L,_,_}=M, _RDs) -> - erl_parse:package_segments(M) =/= error; is_gexpr({record_field,_L,Rec,_Name,Field}, RDs) -> is_gexpr_list([Rec,Field], RDs); is_gexpr({record,L,Name,Inits}, RDs) -> @@ -2086,13 +2030,6 @@ expr({record,Line,Name,Inits}, Vt, St) -> fun (Dfs, St1) -> init_fields(Inits, Line, Name, Dfs, Vt, St1) end); -expr({record_field,Line,_,_}=M, _Vt, St0) -> - case expand_package(M, St0) of - {error, St1} -> - {[],add_error(Line, illegal_expr, St1)}; - {_, St1} -> - {[], St1} - end; expr({record_field,Line,Rec,Name,Field}, Vt, St0) -> {Rvt,St1} = record_expr(Line, Rec, Vt, St0), {Fvt,St2} = check_record(Line, Name, St1, @@ -2163,20 +2100,14 @@ expr({call,Line,{remote,_Lr,{atom,_Lm,erlang},{atom,Lf,is_record}},[E,A]}, expr({call,Line,{atom,Lf,is_record},[E,A]}, Vt, St0); expr({call,L,{tuple,Lt,[{atom,Lm,erlang},{atom,Lf,is_record}]},As}, Vt, St) -> expr({call,L,{remote,Lt,{atom,Lm,erlang},{atom,Lf,is_record}},As}, Vt, St); +expr({call,Line,{remote,_Lr,{atom,_Lm,M},{atom,Lf,F}},As}, Vt, St0) -> + St1 = keyword_warning(Lf, F, St0), + St2 = check_remote_function(Line, M, F, As, St1), + expr_list(As, Vt, St2); expr({call,Line,{remote,_Lr,M,F},As}, Vt, St0) -> - case expand_package(M, St0) of - {error, _} -> - expr_list([M,F|As], Vt, St0); - {{atom,_La,M1}, St1} -> - case F of - {atom,Lf,F1} -> - St2 = keyword_warning(Lf, F1, St1), - St3 = check_remote_function(Line, M1, F1, As, St2), - expr_list(As, Vt, St3); - _ -> - expr_list([F|As], Vt, St1) - end - end; + St1 = keyword_warning(Line, M, St0), + St2 = keyword_warning(Line, F, St1), + expr_list([M,F|As], Vt, St2); expr({call,Line,{atom,La,F},As}, Vt, St0) -> St1 = keyword_warning(La, F, St0), {Asvt,St2} = expr_list(As, Vt, St1), @@ -2232,13 +2163,6 @@ expr({call,Line,{atom,La,F},As}, Vt, St0) -> end end} end; -expr({call,Line,{record_field,_,_,_}=F,As}, Vt, St0) -> - case expand_package(F, St0) of - {error, _} -> - expr_list([F|As], Vt, St0); - {A, St1} -> - expr({call,Line,A,As}, Vt, St1) - end; expr({call,Line,F,As}, Vt, St0) -> St = warn_invalid_call(Line,F,St0), expr_list([F|As], Vt, St); %They see the same variables @@ -3658,49 +3582,6 @@ control_type($n, Need) -> Need; control_type($i, Need) -> [term|Need]; control_type(_C, _Need) -> error. -%% In syntax trees, module/package names are atoms or lists of atoms. - -package_to_string(A) when is_atom(A) -> atom_to_list(A); -package_to_string(L) when is_list(L) -> packages:concat(L). - -expand_package({atom,L,A} = M, St0) -> - St1 = keyword_warning(L, A, St0), - case dict:find(A, St1#lint.mod_imports) of - {ok, A1} -> - {{atom,L,A1}, St1}; - error -> - Name = atom_to_list(A), - case packages:is_valid(Name) of - true -> - case packages:is_segmented(Name) of - true -> - {M, St1}; - false -> - M1 = packages:concat(St1#lint.package, - Name), - {{atom,L,list_to_atom(M1)}, St1} - end; - false -> - St2 = add_error(L, {bad_module_name, Name}, St1), - {error, St2} - end - end; -expand_package(M, St0) -> - L = element(2, M), - case erl_parse:package_segments(M) of - error -> - {error, St0}; - M1 -> - Name = package_to_string(M1), - case packages:is_valid(Name) of - true -> - {{atom,L,list_to_atom(Name)}, St0}; - false -> - St1 = add_error(L, {bad_module_name, Name}, St0), - {error, St1} - end - end. - %% Prebuild set of local functions (to override auto-import) local_functions(Forms) -> diff --git a/lib/stdlib/src/erl_parse.yrl b/lib/stdlib/src/erl_parse.yrl index 27a2ba80eb..002abc11e8 100644 --- a/lib/stdlib/src/erl_parse.yrl +++ b/lib/stdlib/src/erl_parse.yrl @@ -26,7 +26,7 @@ attribute attr_val function function_clauses function_clause clause_args clause_guard clause_body expr expr_100 expr_150 expr_160 expr_200 expr_300 expr_400 expr_500 -expr_600 expr_700 expr_800 expr_900 +expr_600 expr_700 expr_800 expr_max list tail list_comprehension lc_expr lc_exprs @@ -253,15 +253,9 @@ expr_700 -> function_call : '$1'. expr_700 -> record_expr : '$1'. expr_700 -> expr_800 : '$1'. -expr_800 -> expr_900 ':' expr_max : +expr_800 -> expr_max ':' expr_max : {remote,?line('$2'),'$1','$3'}. -expr_800 -> expr_900 : '$1'. - -expr_900 -> '.' atom : - {record_field,?line('$1'),{atom,?line('$1'),''},'$2'}. -expr_900 -> expr_900 '.' atom : - {record_field,?line('$2'),'$1','$3'}. -expr_900 -> expr_max : '$1'. +expr_800 -> expr_max : '$1'. expr_max -> var : '$1'. expr_max -> atomic : '$1'. @@ -510,7 +504,7 @@ Erlang code. -export([parse_form/1,parse_exprs/1,parse_term/1]). -export([normalise/1,abstract/1,tokens/1,tokens/2]). --export([abstract/2, package_segments/1]). +-export([abstract/2]). -export([inop_prec/1,preop_prec/1,func_prec/0,max_prec/0]). -export([set_line/2,get_attribute/2,get_attributes/1]). @@ -679,20 +673,6 @@ build_attribute({atom,La,module}, Val) -> {attribute,La,module,Module}; [{atom,_Lm,Module},ExpList] -> {attribute,La,module,{Module,var_list(ExpList)}}; - [Name] -> - case package_segments(Name) of - error -> - error_bad_decl(La, module); - Module -> - {attribute,La,module,Module} - end; - [Name,ExpList] -> - case package_segments(Name) of - error -> - error_bad_decl(La, module); - Module -> - {attribute,La,module,{Module,var_list(ExpList)}} - end; _Other -> error_bad_decl(La, module) end; @@ -704,22 +684,8 @@ build_attribute({atom,La,export}, Val) -> end; build_attribute({atom,La,import}, Val) -> case Val of - [Name] -> - case package_segments(Name) of - error -> - error_bad_decl(La, import); - Module -> - {attribute,La,import,Module} - end; [{atom,_Lm,Mod},ImpList] -> {attribute,La,import,{Mod,farity_list(ImpList)}}; - [Name, ImpList] -> - case package_segments(Name) of - error -> - error_bad_decl(La, import); - Module -> - {attribute,La,import,{Module,farity_list(ImpList)}} - end; _Other -> error_bad_decl(La, import) end; build_attribute({atom,La,record}, Val) -> @@ -820,18 +786,6 @@ term(Expr) -> catch _:_R -> ret_err(?line(Expr), "bad attribute") end. -package_segments(Name) -> - package_segments(Name, [], []). - -package_segments({record_field, _, F1, F2}, Fs, As) -> - package_segments(F1, [F2 | Fs], As); -package_segments({atom, _, A}, [F | Fs], As) -> - package_segments(F, Fs, [A | As]); -package_segments({atom, _, A}, [], As) -> - lists:reverse([A | As]); -package_segments(_, _, _) -> - error. - %% build_function([Clause]) -> {function,Line,Name,Arity,[Clause]} build_function(Cs) -> @@ -900,12 +854,6 @@ normalise({cons,_,Head,Tail}) -> [normalise(Head)|normalise(Tail)]; normalise({tuple,_,Args}) -> list_to_tuple(normalise_list(Args)); -%% Atom dot-notation, as in 'foo.bar.baz' -normalise({record_field,_,_,_}=A) -> - case package_segments(A) of - error -> erlang:error({badarg, A}); - As -> list_to_atom(packages:concat(As)) - end; %% Special case for unary +/-. normalise({op,_,'+',{char,_,I}}) -> I; normalise({op,_,'+',{integer,_,I}}) -> I; @@ -1083,9 +1031,9 @@ preop_prec('#') -> {700,800}. func_prec() -> {800,700}. --spec max_prec() -> 1000. +-spec max_prec() -> 900. -max_prec() -> 1000. +max_prec() -> 900. %%% [Experimental]. The parser just copies the attributes of the %%% scanner tokens to the abstract format. This design decision has diff --git a/lib/stdlib/src/filename.erl b/lib/stdlib/src/filename.erl index 59d6de5d10..0c50eb34e6 100644 --- a/lib/stdlib/src/filename.erl +++ b/lib/stdlib/src/filename.erl @@ -878,7 +878,7 @@ filter_options(_Base, [], Result) -> %% Gets the source file given path of object code and module name. get_source_file(Obj, Mod, Rules) -> - source_by_rules(dirname(Obj), packages:last(Mod), Rules). + source_by_rules(dirname(Obj), atom_to_list(Mod), Rules). source_by_rules(Dir, Base, [{From, To}|Rest]) -> case try_rule(Dir, Base, From, To) of diff --git a/lib/stdlib/src/qlc_pt.erl b/lib/stdlib/src/qlc_pt.erl index ad25fd559c..d441f38e44 100644 --- a/lib/stdlib/src/qlc_pt.erl +++ b/lib/stdlib/src/qlc_pt.erl @@ -31,9 +31,6 @@ %% Also in qlc.erl. -define(QLC_Q(L1, L2, L3, L4, LC, Os), {call,L1,{remote,L2,{atom,L3,?APIMOD},{atom,L4,?Q}},[LC | Os]}). --define(QLC_QQ(L1, L2, L3, L4, L5, L6, LC, Os), % packages... - {call,L1,{remote,L2,{record_field,L3,{atom,L4,''}, - {atom,L5,?APIMOD}},{atom,L6,?Q}},[LC | Os]}). -define(IMP_Q(L1, L2, LC, Os), {call,L,{atom,L2,?Q},[LC | Os]}). %% Also in qlc.erl. @@ -2475,13 +2472,6 @@ qlcmf(?QLC_Q(L1, L2, L3, L4, LC0, Os0), F, Imp, A0, No0) when length(Os0) < 2 -> NL = make_lcid(L1, No), {T, A} = F(NL, LC, A2), {?QLC_Q(L1, L2, L3, L4, T, Os), A, No + 1}; -qlcmf(?QLC_QQ(L1, L2, L3, L4, L5, L6, LC0, Os0), - F, Imp, A0, No0) when length(Os0) < 2 -> - {Os, A1, No1} = qlcmf(Os0, F, Imp, A0, No0), - {LC, A2, No} = qlcmf(LC0, F, Imp, A1, No1), % nested... - NL = make_lcid(L1, No), - {T, A} = F(NL, LC, A2), - {?QLC_QQ(L1, L2, L3, L4, L5, L6, T, Os), A, No + 1}; qlcmf(?IMP_Q(L1, L2, LC0, Os0), F, Imp=true, A0, No0) when length(Os0) < 2 -> {Os, A1, No1} = qlcmf(Os0, F, Imp, A0, No0), {LC, A2, No} = qlcmf(LC0, F, Imp, A1, No1), % nested... diff --git a/lib/stdlib/src/shell.erl b/lib/stdlib/src/shell.erl index 688492d724..5c929d2f51 100644 --- a/lib/stdlib/src/shell.erl +++ b/lib/stdlib/src/shell.erl @@ -139,16 +139,6 @@ stop_restricted() -> application:unset_env(stdlib, restricted_shell), exit(restricted_shell_stopped). -default_packages() -> - []. -%%% ['erl','erl.lang']. - -default_modules() -> - []. -%%% [{pdict, 'erl.lang.proc.pdict'}, -%%% {keylist, 'erl.lang.list.keylist'}, -%%% {debug, 'erl.system.debug'}]. - -spec server(boolean(), boolean()) -> 'terminated'. server(NoCtrlG, StartSync) -> @@ -183,15 +173,7 @@ server(StartSync) -> end end, %% Our spawner has fixed the process groups. - Bs0 = erl_eval:new_bindings(), - Bs = lists:foldl(fun ({K, V}, D) -> - erl_eval:add_binding({module,K}, V, D) - end, - lists:foldl(fun (P, D) -> - import_all(P, D) - end, - Bs0, default_packages()), - default_modules()), + Bs = erl_eval:new_bindings(), %% Use an Ets table for record definitions. It takes too long to %% send a huge term to and from the evaluator. Ets makes it @@ -1032,38 +1014,6 @@ local_func(which, [{atom,_,M}], Bs, _Shell, _RT, _Lf, _Ef) -> end; local_func(which, [_Other], _Bs, _Shell, _RT, _Lf, _Ef) -> erlang:raise(error, function_clause, [{shell,which,1}]); -local_func(import, [M], Bs, _Shell, _RT, _Lf, _Ef) -> - case erl_parse:package_segments(M) of - error -> erlang:raise(error, function_clause, [{shell,import,1}]); - M1 -> - Mod = packages:concat(M1), - case packages:is_valid(Mod) of - true -> - Key = list_to_atom(packages:last(Mod)), - Mod1 = list_to_atom(Mod), - {value,ok,erl_eval:add_binding({module,Key}, Mod1, Bs)}; - false -> - exit({{bad_module_name, Mod}, [{shell,import,1}]}) - end - end; -local_func(import_all, [P], Bs0, _Shell, _RT, _Lf, _Ef) -> - case erl_parse:package_segments(P) of - error -> erlang:raise(error, function_clause, [{shell,import_all,1}]); - P1 -> - Name = packages:concat(P1), - case packages:is_valid(Name) of - true -> - Bs1 = import_all(Name, Bs0), - {value,ok,Bs1}; - false -> - exit({{bad_package_name, Name}, - [{shell,import_all,1}]}) - end - end; -local_func(use, [M], Bs, Shell, RT, Lf, Ef) -> - local_func(import, [M], Bs, Shell, RT, Lf, Ef); -local_func(use_all, [M], Bs, Shell, RT, Lf, Ef) -> - local_func(import_all, [M], Bs, Shell, RT, Lf, Ef); local_func(history, [{integer,_,N}], Bs, _Shell, _RT, _Lf, _Ef) -> {value,history(N),Bs}; local_func(history, [_Other], _Bs, _Shell, _RT, _Lf, _Ef) -> @@ -1343,15 +1293,6 @@ record_attrs(Forms) -> %%% End of reading record information from file(s) -import_all(P, Bs0) -> - Ms = packages:find_modules(P), - lists:foldl(fun (M, Bs) -> - Key = list_to_atom(M), - M1 = list_to_atom(packages:concat(P, M)), - erl_eval:add_binding({module,Key}, M1, Bs) - end, - Bs0, Ms). - shell_req(Shell, Req) -> Shell ! {shell_req,self(),Req}, receive diff --git a/lib/stdlib/test/erl_expand_records_SUITE.erl b/lib/stdlib/test/erl_expand_records_SUITE.erl index e248934e10..e51c05a22c 100644 --- a/lib/stdlib/test/erl_expand_records_SUITE.erl +++ b/lib/stdlib/test/erl_expand_records_SUITE.erl @@ -107,8 +107,7 @@ attributes(doc) -> attributes(suite) -> []; attributes(Config) when is_list(Config) -> Ts = [ - <<"-import(erl_expand_records_SUITE). - -import(lists, [append/2, reverse/1]). + <<"-import(lists, [append/2, reverse/1]). -record(r, {a,b}). @@ -158,12 +157,12 @@ expr(Config) when is_list(Config) -> 2 = fun(X) -> X end(One + One), 3 = fun exprec_test:f/1(3), 4 = exprec_test:f(4), - 5 = ''.f(5), + 5 = f(5), L = receive {a,message,L0} -> L0 end, - case catch a.b.c:foo(bar) of + case catch a:foo(bar) of {'EXIT', _} -> ok end, _ = receive %Suppress warning. @@ -263,8 +262,7 @@ pattern(doc) -> pattern(suite) -> []; pattern(Config) when is_list(Config) -> Ts = [ - <<"-import(erl_expand_records_SUITE). - -import(lists, [append/2, reverse/1]). + <<"-import(lists, [append/2, reverse/1]). -record(r, {a,b}). @@ -292,10 +290,10 @@ pattern(Config) when is_list(Config) -> 21 = t(#r{a = #r{}}), 22 = t(2), 23 = t(#r{a = #r{}, b = b}), - 24 = t(a.b.c), + 24 = t(abc), ok. - t(a.b.c) -> + t(abc) -> 24; t($a) -> 2; diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl index 90a37f6441..774229fca9 100644 --- a/lib/stdlib/test/erl_lint_SUITE.erl +++ b/lib/stdlib/test/erl_lint_SUITE.erl @@ -1732,7 +1732,7 @@ otp_5362(Config) when is_list(Config) -> {otp_5362_2, <<"-export([inline/0]). - -import(lists.foo, [a/1,b/1]). % b/1 is not used + -import(lists, [a/1,b/1]). % b/1 is not used -compile([{inline,{inl,7}}]). % undefined -compile([{inline,[{inl,17}]}]). % undefined @@ -1764,7 +1764,7 @@ otp_5362(Config) when is_list(Config) -> {6,erl_lint,{bad_inline,{inl,17}}}, {11,erl_lint,{undefined_function,{fipp,0}}}, {22,erl_lint,{bad_nowarn_unused_function,{and_not_used,2}}}], - [{3,erl_lint,{unused_import,{{b,1},'lists.foo'}}}, + [{3,erl_lint,{unused_import,{{b,1},lists}}}, {9,erl_lint,{unused_function,{foop,0}}}, {19,erl_lint,{unused_function,{not_used,0}}}, {23,erl_lint,{unused_function,{and_not_used,1}}}]}}, diff --git a/lib/stdlib/test/erl_pp_SUITE.erl b/lib/stdlib/test/erl_pp_SUITE.erl index 07303174f1..db416b03b0 100644 --- a/lib/stdlib/test/erl_pp_SUITE.erl +++ b/lib/stdlib/test/erl_pp_SUITE.erl @@ -40,7 +40,7 @@ init_per_testcase/2, end_per_testcase/2]). -export([ func/1, call/1, recs/1, try_catch/1, if_then/1, - receive_after/1, bits/1, head_tail/1, package/1, + receive_after/1, bits/1, head_tail/1, cond1/1, block/1, case1/1, ops/1, messages/1, old_mnemosyne_syntax/1, import_export/1, misc_attrs/1, @@ -75,7 +75,7 @@ all() -> groups() -> [{expr, [], [func, call, recs, try_catch, if_then, receive_after, - bits, head_tail, package, cond1, block, case1, ops, + bits, head_tail, cond1, block, case1, ops, messages, old_mnemosyne_syntax]}, {attributes, [], [misc_attrs, import_export]}, {tickets, [], @@ -439,9 +439,6 @@ bits(Config) when is_list(Config) -> ?line ok = pp_expr(<<"<<{a,b}/binary>>">>), ?line ok = pp_expr(<<"<<{foo:bar(),b}/binary>>">>), ?line ok = pp_expr(<<"<<(foo:bar()):(foo:bar())/binary>>">>), - ?line ok = pp_expr(<<"<<(foo.bar)/binary>>">>), - ?line ok = pp_expr(<<"<<(foo.bar):all/binary>>">>), - ?line ok = pp_expr(<<"<<(foo.bar):(foo.bar)/binary>>">>), ok. head_tail(suite) -> @@ -463,17 +460,6 @@ head_tail(Config) when is_list(Config) -> ?line compile(Config, Ts), ok. -package(suite) -> - []; -package(Config) when is_list(Config) -> - Ts = [{package_1, - <<"t() -> a.b:foo().">>}, - {package_2, - <<"t() -> .lists:sort([]).">>} - ], - ?line compile(Config, Ts), - ok. - cond1(suite) -> []; cond1(Config) when is_list(Config) -> @@ -615,13 +601,11 @@ misc_attrs(suite) -> []; misc_attrs(Config) when is_list(Config) -> ?line ok = pp_forms(<<"-module(m). ">>), - ?line ok = pp_forms(<<"-module(m.p, [A,B]). ">>), ?line ok = pp_forms(<<"-module(m, [Aafjlksfjdlsjflsdfjlsdjflkdsfjlk," "Blsjfdlslfjsdf]). ">>), ?line ok = pp_forms(<<"-export([]). ">>), ?line ok = pp_forms(<<"-export([foo/2, bar/0]). ">>), ?line ok = pp_forms(<<"-export([bar/0]). ">>), - ?line ok = pp_forms(<<"-import(.lists). ">>), ?line ok = pp_forms(<<"-import(lists, []). ">>), ?line ok = pp_forms(<<"-import(lists, [map/2]). ">>), ?line ok = pp_forms(<<"-import(lists, [map/2, foreach/2]). ">>), diff --git a/lib/stdlib/test/qlc_SUITE.erl b/lib/stdlib/test/qlc_SUITE.erl index e3090e4a47..cac8309bd9 100644 --- a/lib/stdlib/test/qlc_SUITE.erl +++ b/lib/stdlib/test/qlc_SUITE.erl @@ -6062,21 +6062,6 @@ otp_6673(Config) when is_list(Config) -> ], ?line run(Config, Ts_RT), - %% Ulf Wiger provided a patch that makes QLC work with packages: - Dir = filename:join(?privdir, "p"), - ?line ok = filelib:ensure_dir(filename:join(Dir, ".")), - File = filename:join(Dir, "p.erl"), - ?line ok = file:write_file(File, - <<"-module(p.p).\n" - "-export([q/0]).\n" - "-include_lib(\"stdlib/include/qlc.hrl\").\n" - "q() ->\n" - " .qlc:q([X || X <- [1,2]]).">>), - ?line {ok, 'p.p'} = compile:file(File, [{outdir,Dir}]), - ?line code:purge('p.p'), - ?line {module, 'p.p'} = code:load_abs(filename:rootname(File), 'p.p'), - ?line [1,2] = qlc:e(p.p:q()), - ok. otp_6964(doc) -> diff --git a/lib/syntax_tools/src/erl_prettypr.erl b/lib/syntax_tools/src/erl_prettypr.erl index 577dd21a77..1a55a5e71c 100644 --- a/lib/syntax_tools/src/erl_prettypr.erl +++ b/lib/syntax_tools/src/erl_prettypr.erl @@ -645,10 +645,6 @@ lay_2(Node, Ctxt) -> set_prec(Ctxt, PrecR)), beside(D1, beside(text(":"), D2)); - qualified_name -> - Ss = erl_syntax:qualified_name_segments(Node), - lay_qualified_name(Ss, Ctxt); - %% %% The rest is in alphabetical order %% @@ -972,26 +968,6 @@ maybe_parentheses(D, Prec, Ctxt) -> D end. -lay_qualified_name([S | Ss1] = Ss, Ctxt) -> - case erl_syntax:type(S) of - atom -> - case erl_syntax:atom_value(S) of - '' -> - beside(text("."), - lay_qualified_name_1(Ss1, Ctxt)); - _ -> - lay_qualified_name_1(Ss, Ctxt) - end; - _ -> - lay_qualified_name_1(Ss, Ctxt) - end. - -lay_qualified_name_1([S], Ctxt) -> - lay(S, Ctxt); -lay_qualified_name_1([S | Ss], Ctxt) -> - beside(lay(S, Ctxt), beside(text("."), - lay_qualified_name_1(Ss, Ctxt))). - lay_string(S, Ctxt) -> %% S includes leading/trailing double-quote characters. The segment %% width is 2/3 of the ribbon width - this seems to work well. diff --git a/lib/syntax_tools/src/erl_syntax.erl b/lib/syntax_tools/src/erl_syntax.erl index 93b9dc54dd..f7420030c3 100644 --- a/lib/syntax_tools/src/erl_syntax.erl +++ b/lib/syntax_tools/src/erl_syntax.erl @@ -235,8 +235,6 @@ prefix_expr/2, prefix_expr_argument/1, prefix_expr_operator/1, - qualified_name/1, - qualified_name_segments/1, query_expr/1, query_expr_body/1, receive_expr/1, @@ -451,7 +449,6 @@ %% <td>parentheses</td> %% <td>prefix_expr</td> %% </tr><tr> -%% <td>qualified_name</td> %% <td>query_expr</td> %% <td>receive_expr</td> %% <td>record_access</td> @@ -516,7 +513,6 @@ %% @see operator/1 %% @see parentheses/1 %% @see prefix_expr/2 -%% @see qualified_name/1 %% @see query_expr/1 %% @see receive_expr/3 %% @see record_access/3 @@ -586,11 +582,7 @@ type(Node) -> {record, _, _, _, _} -> record_expr; {record, _, _, _} -> record_expr; {record_field, _, _, _, _} -> record_access; - {record_field, _, _, _} -> - case is_qualified_name(Node) of - true -> qualified_name; - false -> record_access - end; + {record_field, _, _, _} -> record_access; {record_index, _, _, _} -> record_index_expr; {remote, _, _, _} -> module_qualifier; {rule, _, _, _, _} -> rule; @@ -3047,9 +3039,6 @@ revert_module_name(A) -> case type(A) of atom -> {ok, concrete(A)}; - qualified_name -> - Ss = qualified_name_segments(A), - {ok, [concrete(S) || S <- Ss]}; _ -> error end. @@ -3095,11 +3084,7 @@ attribute_arguments(Node) -> M0 -> {M0, none} end, - M2 = if is_list(M1) -> - qualified_name([atom(A) || A <- M1]); - true -> - atom(M1) - end, + M2 = atom(M1), M = set_pos(M2, Pos), if Vs == none -> [M]; true -> [M, set_pos(list(Vs), Pos)] @@ -3109,20 +3094,11 @@ attribute_arguments(Node) -> list(unfold_function_names(Data, Pos)), Pos)]; import -> - case Data of - {Module, Imports} -> - [if is_list(Module) -> - qualified_name([atom(A) - || A <- Module]); - true -> - set_pos(atom(Module), Pos) - end, - set_pos( - list(unfold_function_names(Imports, Pos)), - Pos)]; - _ -> - [qualified_name([atom(A) || A <- Data])] - end; + {Module, Imports} = Data, + [set_pos(atom(Module), Pos), + set_pos( + list(unfold_function_names(Imports, Pos)), + Pos)]; file -> {File, Line} = Data, [set_pos(string(File), Pos), @@ -3254,53 +3230,6 @@ module_qualifier_body(Node) -> %% ===================================================================== -%% @doc Creates an abstract qualified name. The result represents -%% "<code><em>S1</em>.<em>S2</em>. ... .<em>Sn</em></code>", if -%% `Segments' is `[S1, S2, ..., Sn]'. -%% -%% @see qualified_name_segments/1 - -%% type(Node) = qualified_name -%% data(Node) = [syntaxTree()] -%% -%% `erl_parse' representation: -%% -%% {record_field, Pos, Node, Node} -%% -%% Node = {atom, Pos, Value} | {record_field, Pos, Node, Node} -%% -%% Note that if not all leaf subnodes are (abstract) atoms, then Node -%% represents a Mnemosyne query record field access ('record_access'); -%% see type/1 for details. - --spec qualified_name([syntaxTree()]) -> syntaxTree(). - -qualified_name(Segments) -> - tree(qualified_name, Segments). - -revert_qualified_name(Node) -> - Pos = get_pos(Node), - fold_qualified_name(qualified_name_segments(Node), Pos). - - -%% ===================================================================== -%% @doc Returns the list of name segments of a -%% `qualified_name' node. -%% -%% @see qualified_name/1 - --spec qualified_name_segments(syntaxTree()) -> [syntaxTree()]. - -qualified_name_segments(Node) -> - case unwrap(Node) of - {record_field, _, _, _} = Node1 -> - unfold_qualified_name(Node1); - Node1 -> - data(Node1) - end. - - -%% ===================================================================== %% @doc Creates an abstract function definition. If `Clauses' %% is `[C1, ..., Cn]', the result represents %% "<code><em>Name</em> <em>C1</em>; ...; <em>Name</em> @@ -6112,8 +6041,6 @@ revert_root(Node) -> revert_parentheses(Node); prefix_expr -> revert_prefix_expr(Node); - qualified_name -> - revert_qualified_name(Node); query_expr -> revert_query_expr(Node); receive_expr -> @@ -6356,8 +6283,6 @@ subtrees(T) -> prefix_expr -> [[prefix_expr_operator(T)], [prefix_expr_argument(T)]]; - qualified_name -> - [qualified_name_segments(T)]; query_expr -> [[query_expr_body(T)]]; receive_expr -> @@ -6488,7 +6413,6 @@ make_tree(match_expr, [[P], [E]]) -> match_expr(P, E); make_tree(module_qualifier, [[M], [N]]) -> module_qualifier(M, N); make_tree(parentheses, [[E]]) -> parentheses(E); make_tree(prefix_expr, [[F], [A]]) -> prefix_expr(F, A); -make_tree(qualified_name, [S]) -> qualified_name(S); make_tree(query_expr, [[B]]) -> query_expr(B); make_tree(receive_expr, [C]) -> receive_expr(C); make_tree(receive_expr, [C, [E], A]) -> receive_expr(C, E, A); @@ -6832,32 +6756,6 @@ fold_variable_names(Vs) -> unfold_variable_names(Vs, Pos) -> [set_pos(variable(V), Pos) || V <- Vs]. -%% Support functions for qualified names ("foo.bar.baz", -%% "erl.lang.lists", etc.). The representation overlaps with the weird -%% "Mnesia query record access" operators. The '.' operator is left -%% associative, so folding should nest on the left. - -is_qualified_name({record_field, _, L, R}) -> - is_qualified_name(L) andalso is_qualified_name(R); -is_qualified_name({atom, _, _}) -> true; -is_qualified_name(_) -> false. - -unfold_qualified_name(Node) -> - lists:reverse(unfold_qualified_name(Node, [])). - -unfold_qualified_name({record_field, _, L, R}, Ss) -> - unfold_qualified_name(R, unfold_qualified_name(L, Ss)); -unfold_qualified_name(S, Ss) -> [S | Ss]. - -fold_qualified_name([S | Ss], Pos) -> - fold_qualified_name(Ss, Pos, {atom, Pos, atom_value(S)}). - -fold_qualified_name([S | Ss], Pos, Ack) -> - fold_qualified_name(Ss, Pos, {record_field, Pos, Ack, - {atom, Pos, atom_value(S)}}); -fold_qualified_name([], _Pos, Ack) -> - Ack. - %% Support functions for transforming lists of record field definitions. %% %% There is no unique representation for field definitions in the diff --git a/lib/syntax_tools/src/erl_syntax_lib.erl b/lib/syntax_tools/src/erl_syntax_lib.erl index 36cd35f15d..2c94ac776d 100644 --- a/lib/syntax_tools/src/erl_syntax_lib.erl +++ b/lib/syntax_tools/src/erl_syntax_lib.erl @@ -2223,11 +2223,6 @@ module_name_to_atom(M) -> case erl_syntax:type(M) of atom -> erl_syntax:atom_value(M); - qualified_name -> - list_to_atom(packages:concat( - [erl_syntax:atom_value(A) - || A <- erl_syntax:qualified_name_segments(M)]) - ); _ -> throw(syntax_error) end. diff --git a/lib/test_server/doc/src/test_server_ctrl.xml b/lib/test_server/doc/src/test_server_ctrl.xml index 41bc0bcc75..af96f1fe7e 100644 --- a/lib/test_server/doc/src/test_server_ctrl.xml +++ b/lib/test_server/doc/src/test_server_ctrl.xml @@ -427,11 +427,21 @@ Optional, if not given the test server controller node <p>A <c>CoverFile</c> can have the following entries:</p> <code type="none"> {exclude, all | ExcludeModuleList}. -{include, IncludeModuleList}. </code> +{include, IncludeModuleList}. +{cross, CrossCoverInfo}.</code> <p>Note that each line must end with a full stop. <c>ExcludeModuleList</c> and <c>IncludeModuleList</c> are lists of atoms, where each atom is a module name. </p> + + <p><c>CrossCoverInfo</c> is used when collecting cover data + over multiple tests. Modules listed here are compiled, but + they will not be analysed when the test is finished. See + <seealso + marker="#cross_cover_analyse-2">cross_cover_analyse/2</seealso> + for more information about the cross cover mechanism and the + format of <c>CrossCoverInfo</c>. + </p> <p>If both an <c>Application</c> and a <c>CoverFile</c> is given, all modules in the application are cover compiled, except for the modules listed in <c>ExcludeModuleList</c>. The @@ -467,30 +477,71 @@ Optional, if not given the test server controller node </desc> </func> <func> - <name>cross_cover_analyse(Level) -> ok</name> - <fsummary>Analyse cover data collected from all tests</fsummary> + <name>cross_cover_analyse(Level, Tests) -> ok</name> + <fsummary>Analyse cover data collected from multiple tests</fsummary> <type> <v>Level = details | overview</v> + <v>Tests = [{Tag,LogDir}]</v> + <v>Tag = atom()</v> + <d>Test identifier.</d> + <v>LogDir = string()</v> + <d>Log directory for the test identified by <c>Tag</c>. This + can either be the <c>run.<timestamp></c> directory or + the parent directory of this (in which case the latest + <c>run.<timestamp></c> directory is chosen.</d> </type> <desc> - <p>Analyse cover data collected from all tests. The modules - analysed are the ones listed in the cross cover file - <c>cross.cover</c> in the current directory of the test - server.</p> - <p>The modules listed in the <c>cross.cover</c> file are - modules that are heavily used by other applications than the - one they belong to. This function should be run after all - tests are completed, and the result will be stored in a file - called cross_cover.html in the run.<timestamp> - directory of the application the modules belong to. - </p> - <p>The <c>cross.cover</c> file contains elements like this:</p> - <pre> -{App,Modules}. </pre> - <p>where <c>App</c> can be an application name or the atom - <c>all</c>. The application (or all applications) will cover - compile the listed <c>Modules</c>. - </p> + <p>Analyse cover data collected from multiple tests. The modules + analysed are the ones listed in <c>cross</c> statements in + the cover files. These are modules that are heavily used by + other tests than the one where they belong or are explicitly + tested. They should then be listed as cross modules in the + cover file for the test where they are used but do not + belong. Se example below.</p> + <p>This function should be run after all tests are completed, + and the result will be stored in a file called + <c>cross_cover.html</c> in the <c>run.<timestamp></c> + directory of the test the modules belong to.</p> + <p>Note that the function can be executed on any node, and it + does not require <c>test_server_ctrl</c> to be started first.</p> + <p>The <c>cross</c> statement in the cover file must be like this:</p> + <code type="none"> +{cross,[{Tag,Modules}]}.</code> + <p>where <c>Tag</c> is the same as <c>Tag</c> in the + <c>Tests</c> parameter to this function and <c>Modules</c> is a + list of module names (atoms).</p> + <p><em>Example:</em></p> + <p>If the module <c>m1</c> belongs to system <c>s1</c> but is + heavily used also in the tests for another system <c>s2</c>, + then the cover files for the two systems' tests could be like + this:</p> +<code type="none"> +s1.cover: + {include,[m1]}. + +s2.cover: + {include,[....]}. % modules belonging to system s2 + {cross,[{s1,[m1]}]}.</code> + <p>When the tests for both <c>s1</c> and <c>s2</c> are completed, run</p> +<code type="none"> +test_server_ctrl:cross_cover_analyse(Level,[{s1,S1LogDir},{s2,S2LogDir}]) +</code> + + <p>and the accumulated cover data for <c>m1</c> will be written to + <c>S1LogDir/[run.<timestamp>/]cross_cover.html</c>.</p> + <p>Note that the <c>m1</c> module will also be presented in the + normal coverage log for <c>s1</c> (due to the include statement in + <c>s1.cover</c>), but that only includes the coverage achieved by the + <c>s1</c> test itself.</p> + <p>The Tag in the <c>cross</c> statement in the cover file has + no other purpose than mapping the list of modules + (<c>[m1]</c> in the example above) to the correct log + directory where it should be included in the + <c>cross_cover.html</c> file (<c>S1LogDir</c> in the example + above). I.e. the value of <c>Tag</c> has no meaning, it + could be <c>foo</c> as well as <c>s1</c> above, as long as + the same <c>Tag</c> is used in the cover file and in the + call to this function.</p> </desc> </func> <func> diff --git a/lib/test_server/doc/src/ts.xml b/lib/test_server/doc/src/ts.xml index 4a2c536e96..82ba3a5017 100644 --- a/lib/test_server/doc/src/ts.xml +++ b/lib/test_server/doc/src/ts.xml @@ -5,7 +5,7 @@ <header> <copyright> <year>2007</year> - <year>2011</year> + <year>2012</year> <holder>Ericsson AB, All Rights Reserved</holder> </copyright> <legalnotice> @@ -450,7 +450,7 @@ This option is mandatory for remote targets <desc> <p>Analyse cover data collected from all tests. </p> - <p>See test_server_ctrl:cross_cover_analyse/1 + <p>See test_server_ctrl:cross_cover_analyse/2 </p> </desc> </func> diff --git a/lib/test_server/src/Makefile b/lib/test_server/src/Makefile index 20e7a5942c..3261936472 100644 --- a/lib/test_server/src/Makefile +++ b/lib/test_server/src/Makefile @@ -69,7 +69,6 @@ INTERNAL_HRL_FILES = test_server_internal.hrl TS_HRL_FILES= ts.hrl C_FILES = AUTOCONF_FILES = configure.in conf_vars.in -COVER_FILES = cross.cover PROGRAMS = configure config.sub config.guess install-sh CONFIG = ts.config ts.unix.config ts.win32.config @@ -137,7 +136,7 @@ release_tests_spec: opt $(INSTALL_DATA) $(ERL_FILES) $(TS_ERL_FILES) \ $(HRL_FILES) $(INTERNAL_HRL_FILES) $(TS_HRL_FILES) \ $(TS_TARGET_FILES) \ - $(AUTOCONF_FILES) $(C_FILES) $(COVER_FILES) $(CONFIG) \ + $(AUTOCONF_FILES) $(C_FILES) $(CONFIG) \ "$(RELEASE_PATH)/test_server" $(INSTALL_SCRIPT) $(PROGRAMS) "$(RELEASE_PATH)/test_server" diff --git a/lib/test_server/src/test_server.erl b/lib/test_server/src/test_server.erl index 9f06ac450b..37cd8fac99 100644 --- a/lib/test_server/src/test_server.erl +++ b/lib/test_server/src/test_server.erl @@ -60,8 +60,6 @@ -include("test_server_internal.hrl"). -include_lib("kernel/include/file.hrl"). --define(pl2a(M), test_server_sup:package_atom(M)). - init_target_info() -> [$.|Emu] = code:objfile_extension(), {_, OTPRel} = init:script_id(), @@ -97,7 +95,8 @@ init_purify() -> %% is found, else {error,application_not_found}. cover_compile({none,_Exclude,Include,Cross}) -> - CompileMods = Include++Cross, + CrossMods = lists:flatmap(fun({_,M}) -> M end,Cross), + CompileMods = Include++CrossMods, case length(CompileMods) of 0 -> io:fwrite("WARNING: No modules to cover compile!\n\n",[]), @@ -111,7 +110,8 @@ cover_compile({none,_Exclude,Include,Cross}) -> {ok,Include} end; cover_compile({App,all,Include,Cross}) -> - CompileMods = Include++Cross, + CrossMods = lists:flatmap(fun({_,M}) -> M end,Cross), + CompileMods = Include++CrossMods, case length(CompileMods) of 0 -> io:fwrite("WARNING: No modules to cover compile!\n\n",[]), @@ -129,9 +129,10 @@ cover_compile({App,all,Include,Cross}) -> {ok,Include} end; cover_compile({App,Exclude,Include,Cross}) -> + CrossMods = lists:flatmap(fun({_,M}) -> M end,Cross), case code:lib_dir(App) of {error,bad_name} -> - case Include++Cross of + case Include++CrossMods of [] -> io:format("\nWARNING: Can't find lib_dir for \'~w\'\n" "Not cover compiling!\n\n",[App]), @@ -152,7 +153,7 @@ cover_compile({App,Exclude,Include,Cross}) -> WC = filename:join(EbinDir,"*.beam"), AllMods = module_names(filelib:wildcard(WC)), AnalyseMods = (AllMods ++ Include) -- Exclude, - CompileMods = AnalyseMods ++ Cross, + CompileMods = AnalyseMods ++ CrossMods, case length(CompileMods) of 0 -> io:fwrite("WARNING: No modules to cover compile!\n\n",[]), @@ -918,7 +919,7 @@ run_test_case_eval(Mod, Func, Args0, Name, Ref, RunInit, put(test_server_logopts, LogOpts), Where = [{Mod,Func}], put(test_server_loc, Where), - FWInitResult = test_server_sup:framework_call(init_tc,[?pl2a(Mod),Func,Args0], + FWInitResult = test_server_sup:framework_call(init_tc,[Mod,Func,Args0], {ok,Args0}), set_tc_state(running), {{Time,Value},Loc,Opts} = @@ -1052,7 +1053,7 @@ do_end_tc_call(Mod, Func, Res, Return) -> Ref = make_ref(), if FwMod == "ct_framework" ; FwMod == "undefined"; FwMod == false -> case test_server_sup:framework_call( - end_tc, [?pl2a(Mod),Func,Res, Return], ok) of + end_tc, [Mod,Func,Res, Return], ok) of {fail,FWReason} -> {failed,FWReason}; ok -> @@ -1067,7 +1068,7 @@ do_end_tc_call(Mod, Func, Res, Return) -> end; true -> case test_server_sup:framework_call(FwMod, end_tc, - [?pl2a(Mod),Func,Res], Ref) of + [Mod,Func,Res], Ref) of {fail,FWReason} -> {failed,FWReason}; _Else -> @@ -1301,11 +1302,11 @@ get_loc(Pid) -> fw_error_notify(Mod, Func, Args, Error) -> test_server_sup:framework_call(error_notification, - [?pl2a(Mod),Func,[Args], + [Mod,Func,[Args], {Error,unknown}]). fw_error_notify(Mod, Func, Args, Error, Loc) -> test_server_sup:framework_call(error_notification, - [?pl2a(Mod),Func,[Args], + [Mod,Func,[Args], {Error,Loc}]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/lib/test_server/src/test_server_ctrl.erl b/lib/test_server/src/test_server_ctrl.erl index bc08c12089..c5c57426b4 100644 --- a/lib/test_server/src/test_server_ctrl.erl +++ b/lib/test_server/src/test_server_ctrl.erl @@ -53,8 +53,7 @@ -export([reject_io_reqs/1, get_levels/0, set_levels/3]). -export([multiply_timetraps/1, scale_timetraps/1, get_timetrap_parameters/0]). -export([create_priv_dir/1]). --export([cover/2, cover/3, cover/8, - cross_cover_analyse/2, cross_cover_analyse/3, trc/1, stop_trace/0]). +-export([cover/2, cover/3, cover/8, cross_cover_analyse/2, trc/1, stop_trace/0]). -export([testcase_callback/1]). -export([set_random_seed/1]). -export([kill_slavenodes/0]). @@ -88,17 +87,18 @@ -define(data_dir_suffix, "_data/"). -define(suitelog_name, "suite.log"). -define(coverlog_name, "cover.html"). +-define(raw_coverlog_name, "cover.log"). -define(cross_coverlog_name, "cross_cover.html"). +-define(raw_cross_coverlog_name, "cross_cover.log"). +-define(cross_cover_info, "cross_cover.info"). -define(cover_total, "total_cover.log"). -define(unexpected_io_log, "unexpected_io.log"). -define(last_file, "last_name"). -define(last_link, "last_link"). -define(last_test, "last_test"). -define(html_ext, ".html"). --define(cross_cover_file, "cross.cover"). -define(now, erlang:now()). --define(pl2a(M), test_server_sup:package_atom(M)). -define(void_fun, fun() -> ok end). -define(mod_result(X), if X == skip -> skipped; X == auto_skip -> skipped; @@ -409,7 +409,9 @@ cover(CoverFile, Analyse) -> cover(App, CoverFile, Analyse) -> controller_call({cover,{App,CoverFile},Analyse,true}). cover(App, CoverFile, Exclude, Include, Cross, Export, Analyse, Stop) -> - controller_call({cover,{App,{CoverFile,Exclude,Include,Cross,Export}},Analyse,Stop}). + controller_call({cover, + {App,{CoverFile,Exclude,Include,Cross,Export}}, + Analyse,Stop}). testcase_callback(ModFunc) -> controller_call({testcase_callback,ModFunc}). @@ -2277,7 +2279,7 @@ run_test_cases_loop([{auto_skip_case,{Type,Ref,Case,Comment},SkipMode}|Cases], set_io_buffering(undefined), {Mod,Func} = skip_case(auto, Ref, 0, Case, Comment, false, SkipMode), test_server_sup:framework_call(report, [tc_auto_skip, - {?pl2a(Mod),Func,Comment}]), + {Mod,Func,Comment}]), run_test_cases_loop(Cases, Config, TimetrapData, ParentMode, delete_status(Ref, Status)); _ -> @@ -2286,7 +2288,7 @@ run_test_cases_loop([{auto_skip_case,{Type,Ref,Case,Comment},SkipMode}|Cases], wait_for_cases(Ref), {Mod,Func} = skip_case(auto, Ref, 0, Case, Comment, true, SkipMode), test_server_sup:framework_call(report, [tc_auto_skip, - {?pl2a(Mod),Func,Comment}]), + {Mod,Func,Comment}]), case CurrIOHandler of {Ref,_} -> %% current_io_handler was set by start conf of this @@ -2303,7 +2305,7 @@ run_test_cases_loop([{auto_skip_case,{Type,Ref,Case,Comment},SkipMode}|Cases], %% this is a skipped end conf for a non-parallel group that's not %% nested under a parallel group {Mod,Func} = skip_case(auto, Ref, 0, Case, Comment, false, SkipMode), - test_server_sup:framework_call(report, [tc_auto_skip,{?pl2a(Mod),Func,Comment}]), + test_server_sup:framework_call(report, [tc_auto_skip,{Mod,Func,Comment}]), %% Check if this group is auto skipped because of error in the init conf. %% If so, check if the parent group is a sequence, and if it is, skip @@ -2334,7 +2336,7 @@ run_test_cases_loop([{auto_skip_case,{Type,Ref,Case,Comment},SkipMode}|Cases], %% this is a skipped end conf for a non-parallel group nested under %% a parallel group (io buffering is active) {Mod,Func} = skip_case(auto, Ref, 0, Case, Comment, true, SkipMode), - test_server_sup:framework_call(report, [tc_auto_skip,{?pl2a(Mod),Func,Comment}]), + test_server_sup:framework_call(report, [tc_auto_skip,{Mod,Func,Comment}]), case CurrIOHandler of {Ref,_} -> %% current_io_handler was set by start conf of this @@ -2350,7 +2352,7 @@ run_test_cases_loop([{auto_skip_case,{Type,Ref,Case,Comment},SkipMode}|Cases], %% this is a skipped start conf for a group which is not nested %% under a parallel group {Mod,Func} = skip_case(auto, Ref, 0, Case, Comment, false, SkipMode), - test_server_sup:framework_call(report, [tc_auto_skip,{?pl2a(Mod),Func,Comment}]), + test_server_sup:framework_call(report, [tc_auto_skip,{Mod,Func,Comment}]), run_test_cases_loop(Cases, Config, TimetrapData, [conf(Ref,[])|Mode], Status); {_,Ref0} when is_reference(Ref0) -> %% this is a skipped start conf for a group nested under a parallel group @@ -2361,7 +2363,7 @@ run_test_cases_loop([{auto_skip_case,{Type,Ref,Case,Comment},SkipMode}|Cases], ok end, {Mod,Func} = skip_case(auto, Ref, 0, Case, Comment, true, SkipMode), - test_server_sup:framework_call(report, [tc_auto_skip,{?pl2a(Mod),Func,Comment}]), + test_server_sup:framework_call(report, [tc_auto_skip,{Mod,Func,Comment}]), run_test_cases_loop(Cases, Config, TimetrapData, [conf(Ref,[])|Mode], Status) end; @@ -2369,7 +2371,7 @@ run_test_cases_loop([{auto_skip_case,{Case,Comment},SkipMode}|Cases], Config, TimetrapData, Mode, Status) -> {Mod,Func} = skip_case(auto, undefined, get(test_server_case_num)+1, Case, Comment, is_io_buffered(), SkipMode), - test_server_sup:framework_call(report, [tc_auto_skip,{?pl2a(Mod),Func,Comment}]), + test_server_sup:framework_call(report, [tc_auto_skip,{Mod,Func,Comment}]), run_test_cases_loop(Cases, Config, TimetrapData, Mode, update_status(skipped, Mod, Func, Status)); @@ -2385,7 +2387,7 @@ run_test_cases_loop([{skip_case,{conf,Ref,Case,Comment}}|Cases0], %% skipped start conf {skip_cases_upto(Ref, Cases0, Comment, conf, Mode),Config} end, - test_server_sup:framework_call(report, [tc_user_skip,{?pl2a(Mod),Func,Comment}]), + test_server_sup:framework_call(report, [tc_user_skip,{Mod,Func,Comment}]), run_test_cases_loop(Cases, Config1, TimetrapData, Mode, update_status(skipped, Mod, Func, Status)); @@ -2393,7 +2395,7 @@ run_test_cases_loop([{skip_case,{Case,Comment}}|Cases], Config, TimetrapData, Mode, Status) -> {Mod,Func} = skip_case(user, undefined, get(test_server_case_num)+1, Case, Comment, is_io_buffered()), - test_server_sup:framework_call(report, [tc_user_skip,{?pl2a(Mod),Func,Comment}]), + test_server_sup:framework_call(report, [tc_user_skip,{Mod,Func,Comment}]), run_test_cases_loop(Cases, Config, TimetrapData, Mode, update_status(skipped, Mod, Func, Status)); @@ -3571,7 +3573,7 @@ run_test_case1(Ref, Num, Mod, Func, Args, RunInit, end, test_server_sup:framework_call(report, - [tc_start,{{?pl2a(Mod),Func},MinorName}]), + [tc_start,{{Mod,Func},MinorName}]), print_props((RunInit==skip_init), get_props(Mode)), GroupName = case get_name(Mode) of @@ -3756,7 +3758,7 @@ progress(skip, CaseNum, Mod, Func, Loc, Reason, Time, print(major, "=result skipped", []), print(1, "*** SKIPPED *** ~s", [get_info_str(Func, CaseNum, get(test_server_cases))]), - test_server_sup:framework_call(report, [tc_done,{?pl2a(Mod),Func, + test_server_sup:framework_call(report, [tc_done,{Mod,Func, {skipped,Reason1}}]), ReasonStr = reason_to_string(Reason1), ReasonStr1 = lists:flatten([string:strip(S,left) || @@ -3787,7 +3789,7 @@ progress(failed, CaseNum, Mod, Func, Loc, timetrap_timeout, T, print(1, "*** FAILED *** ~s", [get_info_str(Func, CaseNum, get(test_server_cases))]), test_server_sup:framework_call(report, - [tc_done,{?pl2a(Mod),Func, + [tc_done,{Mod,Func, {failed,timetrap_timeout}}]), FormatLastLoc = test_server_sup:format_loc(get_last_loc(Loc)), ErrorReason = io_lib:format("{timetrap_timeout,~s}", [FormatLastLoc]), @@ -3813,7 +3815,7 @@ progress(failed, CaseNum, Mod, Func, Loc, {testcase_aborted,Reason}, _T, print(1, "*** FAILED *** ~s", [get_info_str(Func, CaseNum, get(test_server_cases))]), test_server_sup:framework_call(report, - [tc_done,{?pl2a(Mod),Func, + [tc_done,{Mod,Func, {failed,testcase_aborted}}]), FormatLastLoc = test_server_sup:format_loc(get_last_loc(Loc)), ErrorReason = io_lib:format("{testcase_aborted,~s}", [FormatLastLoc]), @@ -3838,7 +3840,7 @@ progress(failed, CaseNum, Mod, Func, unknown, Reason, Time, print(major, "=result failed: ~p, ~p", [Reason,unknown]), print(1, "*** FAILED *** ~s", [get_info_str(Func, CaseNum, get(test_server_cases))]), - test_server_sup:framework_call(report, [tc_done,{?pl2a(Mod),Func, + test_server_sup:framework_call(report, [tc_done,{Mod,Func, {failed,Reason}}]), TimeStr = io_lib:format(if is_float(Time) -> "~.3fs"; true -> "~w" @@ -3874,7 +3876,7 @@ progress(failed, CaseNum, Mod, Func, Loc, Reason, Time, print(major, "=result failed: ~p, ~p", [Reason,Loc]), print(1, "*** FAILED *** ~s", [get_info_str(Func, CaseNum, get(test_server_cases))]), - test_server_sup:framework_call(report, [tc_done,{?pl2a(Mod),Func, + test_server_sup:framework_call(report, [tc_done,{Mod,Func, {failed,Reason}}]), TimeStr = io_lib:format(if is_float(Time) -> "~.3fs"; true -> "~w" @@ -3899,7 +3901,7 @@ progress(failed, CaseNum, Mod, Func, Loc, Reason, Time, progress(ok, _CaseNum, Mod, Func, _Loc, RetVal, Time, Comment0, {St0,St1}) -> print(minor, "successfully completed test case", []), - test_server_sup:framework_call(report, [tc_done,{?pl2a(Mod),Func,ok}]), + test_server_sup:framework_call(report, [tc_done,{Mod,Func,ok}]), Comment = case RetVal of {comment,RetComment} -> @@ -4546,7 +4548,7 @@ collect_case_invoke(Mod, Case, MFA, St) -> end; _ -> Suite = test_server_sup:framework_call(get_suite, - [?pl2a(Mod),Case], + [Mod,Case], []), collect_subcases(Mod, Case, MFA, St, Suite) end. @@ -4898,33 +4900,52 @@ pinfo(P) -> %% - it does not belong to the application, but is listed in the %% {include,List} part of the App.cover file %% - it does not belong to the application, but is listed in the -%% cross.cover file (in the test_server application) under 'all' -%% or under the tested application. -%% -%% The modules listed in the cross.cover file are modules that are -%% hevily used by other applications than the one they belong -%% to. After all tests are completed, these modules can be analysed -%% with coverage data from all tests - see cross_cover_analyse/1. The -%% result is stored in a file called cross_cover.html in the -%% run.<timestamp> directory of the application the modules belong -%% to. -%% -%% For example, the lists module is listed in cross.cover to be -%% included in all tests. lists belongs to the stdlib -%% application. cross_cover_analyse/1 will create a file named -%% cross_cover.html under the newest stdlib.logs/run.xxx directory, -%% where the coverage result for the lists module from all tests is -%% presented. -%% -%% The lists module is also presented in the normal coverage log -%% for stdlib, but that only includes the coverage achieved by -%% the stdlib tests themselves. -%% -%% The Cross cover file cross.cover contains elements like this: -%% {App,Modules}. -%% where App can be an application name or the atom all. The -%% application (or all applications) shall cover compile the listed -%% Modules. +%% {cross,[{Tag,List}]} part of the App.cover file +%% +%% The modules listed in the 'cross' part of the cover file are +%% modules that are heavily used by other tests than the one where +%% they are explicitly tested. They should then be listed as 'cross' +%% in the cover file for the test where they are used but do not +%% belong. +%% +%% After all tests are completed, the these modules can be analysed +%% with coverage data from all tests where they are compiled - see +%% cross_cover_analyse/2. The result is stored in a file called +%% cross_cover.html in the run.<timestamp> directory of the +%% test the modules belong to. +%% +%% Example: +%% If the module m1 belongs to system s1 but is heavily used also in +%% the tests for another system s2, then the cover files for the two +%% systems could be like this: +%% +%% s1.cover: +%% {include,[m1]}. +%% +%% s2.cover: +%% {include,[....]}. % modules belonging to system s2 +%% {cross,[{s1,[m1]}]}. +%% +%% When the tests for both s1 and s2 are completed, run +%% cross_cover_analyse(Level,[{s1,S1LogDir},{s2,S2LogDir}]), and +%% the accumulated cover data for m1 will be written to +%% S1LogDir/[run.<timestamp>/]cross_cover.html +%% +%% S1LogDir and S2LogDir are either the run.<timestamp> directories +%% for the two tests, or the parent directory of these, in which case +%% the latest run.<timestamp> directory will be chosen. +%% +%% Note that the m1 module will also be presented in the normal +%% coverage log for s1 (due to the include statement in s1.cover), but +%% that only includes the coverage achieved by the s1 test itself. +%% +%% The Tag in the 'cross' statement in the cover file has no other +%% purpose than mapping the list of modules ([m1] in the example +%% above) to the correct log directory where it should be included in +%% the cross_cover.html file (S1LogDir in the example above). +%% I.e. the value of the Tag has no meaning, it could be foo as well +%% as s1 above, as long as the same Tag is used in the cover file and +%% in the call to cross_cover_analyse/2. %% Cover compilation @@ -4933,8 +4954,7 @@ cover_compile({App,{_File,Exclude,Include,Cross,_Export}}) -> cover_compile1({App,Exclude,Include,Cross}); cover_compile({App,CoverFile}) -> - Cross = get_cross_modules(App), - {Exclude,Include} = read_cover_file(CoverFile), + {Exclude,Include,Cross} = read_cover_file(CoverFile), cover_compile1({App,Exclude,Include,Cross}). cover_compile1(What) -> @@ -4945,41 +4965,57 @@ cover_compile1(What) -> %% (Exclude), and a list of modules that are not members of the %% application but shall be compiled (Include). read_cover_file(none) -> - {[],[]}; + {[],[],[]}; read_cover_file(CoverFile) -> case file:consult(CoverFile) of {ok,List} -> - case check_cover_file(List, [], []) of - {ok,Exclude,Include} -> {Exclude,Include}; + case check_cover_file(List, [], [], []) of + {ok,Exclude,Include,Cross} -> {Exclude,Include,Cross}; error -> io:fwrite("Faulty format of CoverFile ~p\n", [CoverFile]), - {[],[]} + {[],[],[]} end; {error,Reason} -> io:fwrite("Can't read CoverFile ~p\nReason: ~p\n", [CoverFile,Reason]), - {[],[]} + {[],[],[]} end. -check_cover_file([{exclude,all}|Rest], _, Include) -> - check_cover_file(Rest, all, Include); -check_cover_file([{exclude,Exclude}|Rest], _, Include) -> +check_cover_file([{exclude,all}|Rest], _, Include, Cross) -> + check_cover_file(Rest, all, Include, Cross); +check_cover_file([{exclude,Exclude}|Rest], _, Include, Cross) -> case lists:all(fun(M) -> is_atom(M) end, Exclude) of true -> - check_cover_file(Rest, Exclude, Include); + check_cover_file(Rest, Exclude, Include, Cross); false -> error end; -check_cover_file([{include,Include}|Rest], Exclude, _) -> +check_cover_file([{include,Include}|Rest], Exclude, _, Cross) -> case lists:all(fun(M) -> is_atom(M) end, Include) of true -> - check_cover_file(Rest, Exclude, Include); + check_cover_file(Rest, Exclude, Include, Cross); false -> error end; -check_cover_file([], Exclude, Include) -> - {ok,Exclude,Include}. +check_cover_file([{cross,Cross}|Rest], Exclude, Include, _) -> + case check_cross(Cross) of + true -> + check_cover_file(Rest, Exclude, Include, Cross); + false -> + error + end; +check_cover_file([], Exclude, Include, Cross) -> + {ok,Exclude,Include,Cross}. +check_cross([{Tag,Modules}|Rest]) -> + case lists:all(fun(M) -> is_atom(M) end, [Tag|Modules]) of + true -> + check_cross(Rest); + false -> + false + end; +check_cross([]) -> + true. %% Cover analysis, per application @@ -5000,16 +5036,17 @@ cover_analyse({App,CoverInfo}, Analyse, AnalyseMods, Stop, TestDir) -> "<p><a href=\"~s\">Coverdata collected over all tests</a></p>", [?cross_coverlog_name]), - {CoverFile,_Included,Excluded} = + {CoverFile,_Included,Excluded,Cross} = case CoverInfo of - {File,Excl,Incl,_Cross,Export} -> + {File,Excl,Incl,Cr,Export} -> cover:export(Export), - {File,Incl,Excl}; + {File,Incl,Excl,Cr}; File -> - {Excl,Incl} = read_cover_file(File), - {File,Incl,Excl} + {Excl,Incl,Cr} = read_cover_file(File), + {File,Incl,Excl,Cr} end, io:fwrite(CoverLog, "<p>CoverFile: <code>~p</code>\n", [CoverFile]), + write_cross_cover_info(TestDir,Cross), case length(cover:imported_modules()) of Imps when Imps > 0 -> @@ -5022,6 +5059,8 @@ cover_analyse({App,CoverInfo}, Analyse, AnalyseMods, Stop, TestDir) -> io:fwrite(CoverLog, "<p>Excluded module(s): <code>~p</code>\n", [Excluded]), Coverage = cover_analyse(Analyse, AnalyseMods, Stop), + file:write_file(filename:join(TestDir,?raw_coverlog_name), + term_to_binary(Coverage)), case lists:filter(fun({_M,{_,_,_}}) -> false; (_) -> true @@ -5043,20 +5082,20 @@ cover_analyse(Analyse, AnalyseMods, Stop) -> test_server:cover_analyse({Analyse,TestDir}, AnalyseMods, Stop). -%% Cover analysis, cross application +%% Cover analysis - accumulated over multiple tests %% This can be executed on any node after all tests are finished. -%% Apps = [{App,Dir}] -%% App = atom(), application name -%% Dir = string(), the log directory for App, normally where -%% run.<timestamp> is found. -%% Modules = [atom()], modules that have been cover compiled during tests -%% of other apps than the one they belong to. -cross_cover_analyse(Analyse, Apps) -> - cross_cover_analyse(Analyse, Apps, get_cross_modules()). -cross_cover_analyse(Analyse, Apps, Modules) -> - Apps1 = get_latest_run_dirs(Apps), - Apps2 = add_cross_modules(Modules,Apps1), - CoverdataFiles = get_coverdata_files(Apps2), +%% Analyse = overview | details +%% TagDirs = [{Tag,Dir}] +%% Tag = atom(), identifier +%% Dir = string(), the log directory for Tag, it can be a +%% run.<timestamp> directory or the parent directory of +%% such (in which case the latest run.<timestamp> directory +%% is used) +cross_cover_analyse(Analyse, TagDirs0) -> + TagDirs = get_latest_run_dirs(TagDirs0), + TagMods = get_all_cross_info(TagDirs,[]), + TagDirMods = add_cross_modules(TagMods,TagDirs), + CoverdataFiles = get_coverdata_files(TagDirMods), lists:foreach(fun(CDF) -> cover:import(CDF) end, CoverdataFiles), io:fwrite("Cover analysing...\n", []), DetailsFun = @@ -5066,39 +5105,52 @@ cross_cover_analyse(Analyse, Apps, Modules) -> OutFile = filename:join(Dir, atom_to_list(M) ++ ".CROSS_COVER.html"), - cover:analyse_to_file(M, OutFile, [html]), - {file,OutFile} + case cover:analyse_to_file(M, OutFile, [html]) of + {ok,_} -> + {file,OutFile}; + Error -> + Error + end end; _ -> fun(_,_) -> undefined end end, - Coverage = analyse_apps(Apps2, DetailsFun, []), + Coverage = analyse_tests(TagDirMods, DetailsFun, []), cover:stop(), - write_cross_cover_logs(Coverage,Apps2). + write_cross_cover_logs(Coverage,TagDirMods). -%% For each application from which there are cross cover analysed +write_cross_cover_info(_Dir,[]) -> + ok; +write_cross_cover_info(Dir,Cross) -> + {ok,Fd} = file:open(filename:join(Dir,?cross_cover_info),[write]), + lists:foreach(fun(C) -> io:format(Fd,"~p.~n",[C]) end, Cross), + file:close(Fd). + +%% For each test from which there are cross cover analysed %% modules, write a cross cover log (cross_cover.html). -write_cross_cover_logs([{App,Coverage}|T],Apps) -> - case lists:keyfind(App,1,Apps) of +write_cross_cover_logs([{Tag,Coverage}|T],TagDirMods) -> + case lists:keyfind(Tag,1,TagDirMods) of {_,Dir,Mods} when Mods=/=[] -> + file:write_file(filename:join(Dir,?raw_cross_coverlog_name), + term_to_binary(Coverage)), CoverLogName = filename:join(Dir,?cross_coverlog_name), {ok,CoverLog} = file:open(CoverLogName, [write]), write_coverlog_header(CoverLog), io:fwrite(CoverLog, "<h1>Coverage results for \'~w\' from all tests</h1>\n", - [App]), + [Tag]), write_cover_result_table(CoverLog, Coverage), io:fwrite("Written file ~p\n", [CoverLogName]); _ -> ok end, - write_cross_cover_logs(T,Apps); + write_cross_cover_logs(T,TagDirMods); write_cross_cover_logs([],_) -> io:fwrite("done\n", []). %% Get the latest run.<timestamp> directories -get_latest_run_dirs([{App,Dir}|Apps]) -> - [{App,get_latest_run_dir(Dir)} | get_latest_run_dirs(Apps)]; +get_latest_run_dirs([{Tag,Dir}|Rest]) -> + [{Tag,get_latest_run_dir(Dir)} | get_latest_run_dirs(Rest)]; get_latest_run_dirs([]) -> []. @@ -5117,44 +5169,47 @@ get_latest_dir([_|T],Latest) -> get_latest_dir([],Latest) -> Latest. -%% Associate the cross cover modules with their applications. -add_cross_modules(Mods,Apps)-> - do_add_cross_modules(Mods,[{App,Dir,[]} || {App,Dir} <- Apps]). -do_add_cross_modules([Mod|Mods],Apps)-> - App = get_app(Mod), - NewApps = - case lists:keytake(App,1,Apps) of - {value,{App,Dir,AppMods},Rest} -> - [{App,Dir,lists:umerge([Mod],AppMods)}|Rest]; +get_all_cross_info([{_Tag,Dir}|Rest],Acc) -> + case file:consult(filename:join(Dir,?cross_cover_info)) of + {ok,TagMods} -> + get_all_cross_info(Rest,TagMods++Acc); + _ -> + get_all_cross_info(Rest,Acc) + end; +get_all_cross_info([],Acc) -> + Acc. + +%% Associate the cross cover modules with their log directories +add_cross_modules(TagMods,TagDirs)-> + do_add_cross_modules(TagMods,[{Tag,Dir,[]} || {Tag,Dir} <- TagDirs]). +do_add_cross_modules([{Tag,Mods1}|TagMods],TagDirMods)-> + NewTagDirMods = + case lists:keytake(Tag,1,TagDirMods) of + {value,{Tag,Dir,Mods},Rest} -> + [{Tag,Dir,lists:umerge(lists:sort(Mods1),Mods)}|Rest]; false -> - Apps + TagDirMods end, - do_add_cross_modules(Mods,NewApps); -do_add_cross_modules([],Apps) -> - %% Just to get the modules in the same order as app-only cover log - [{App,Dir,lists:reverse(Mods)} || {App,Dir,Mods} <- Apps]. - -get_app(Module) -> - Beam = code:which(Module), - AppDir = filename:basename(filename:dirname(filename:dirname(Beam))), - [AppStr|_] = string:tokens(AppDir,"-"), - list_to_atom(AppStr). + do_add_cross_modules(TagMods,NewTagDirMods); +do_add_cross_modules([],TagDirMods) -> + %% Just to get the modules in the same order as in the normal cover log + [{Tag,Dir,lists:reverse(Mods)} || {Tag,Dir,Mods} <- TagDirMods]. %% Find all exported coverdata files. -get_coverdata_files(Apps) -> +get_coverdata_files(TagDirMods) -> lists:flatmap( - fun({_,LatestAppDir,_}) -> - filelib:wildcard(filename:join(LatestAppDir,"all.coverdata")) + fun({_,LatestDir,_}) -> + filelib:wildcard(filename:join(LatestDir,"all.coverdata")) end, - Apps). + TagDirMods). -%% For each application, analyse all modules +%% For each test, analyse all modules %% Used for cross cover analysis. -analyse_apps([{App,LastTest,Modules}|T], DetailsFun, Acc) -> +analyse_tests([{Tag,LastTest,Modules}|T], DetailsFun, Acc) -> Cov = analyse_modules(LastTest, Modules, DetailsFun, []), - analyse_apps(T, DetailsFun, [{App,Cov}|Acc]); -analyse_apps([], _DetailsFun, Acc) -> + analyse_tests(T, DetailsFun, [{Tag,Cov}|Acc]); +analyse_tests([], _DetailsFun, Acc) -> Acc. %% Analyse each module @@ -5167,27 +5222,6 @@ analyse_modules(_Dir, [], _DetailsFun, Acc) -> Acc. -%% Read the cross cover file (cross.cover) -get_cross_modules() -> - get_cross_modules(all). -get_cross_modules(App) -> - case file:consult(?cross_cover_file) of - {ok,List} -> - get_cross_modules(App, List, []); - _X -> - [] - end. - -get_cross_modules(App, [{_To,Modules}|T], Acc) when App==all-> - get_cross_modules(App, T, Acc ++ Modules); -get_cross_modules(App, [{To,Modules}|T], Acc) when To==App; To==all-> - get_cross_modules(App, T, Acc ++ Modules); -get_cross_modules(App, [_H|T], Acc) -> - get_cross_modules(App, T, Acc); -get_cross_modules(_App, [], Acc) -> - Acc. - - %% Support functions for writing the cover logs (both cross and normal) write_coverlog_header(CoverLog) -> case catch diff --git a/lib/test_server/src/test_server_sup.erl b/lib/test_server/src/test_server_sup.erl index c7553cccb5..a6d426887e 100644 --- a/lib/test_server/src/test_server_sup.erl +++ b/lib/test_server/src/test_server_sup.erl @@ -28,7 +28,7 @@ get_username/0, get_os_family/0, hostatom/0, hostatom/1, hoststr/0, hoststr/1, framework_call/2,framework_call/3,framework_call/4, - format_loc/1, package_str/1, package_atom/1, + format_loc/1, call_trace/1]). -include("test_server_internal.hrl"). -define(crash_dump_tar,"crash_dumps.tar.gz"). @@ -553,7 +553,7 @@ format_loc([{Mod,Func,Line}|Rest]) -> format_loc([{Mod,LineOrFunc}]) -> format_loc({Mod,LineOrFunc}); format_loc({Mod,Func}) when is_atom(Func) -> - io_lib:format("{~s,~w}",[package_str(Mod),Func]); + io_lib:format("{~w,~w}",[Mod,Func]); format_loc(Loc) -> io_lib:format("~p",[Loc]). @@ -562,15 +562,15 @@ format_loc1([{Mod,Func,Line}]) -> format_loc1([{Mod,Func,Line}|Rest]) -> [" ",format_loc1({Mod,Func,Line}),",\n"|format_loc1(Rest)]; format_loc1({Mod,Func,Line}) -> - ModStr = package_str(Mod), + ModStr = atom_to_list(Mod), case {lists:member(no_src, get(test_server_logopts)), lists:reverse(ModStr)} of {false,[$E,$T,$I,$U,$S,$_|_]} -> - io_lib:format("{~s,~w,<a href=\"~s~s#~w\">~w</a>}", - [ModStr,Func,downcase(ModStr),?src_listing_ext, + io_lib:format("{~w,~w,<a href=\"~s~s#~w\">~w</a>}", + [Mod,Func,downcase(ModStr),?src_listing_ext, Line,Line]); _ -> - io_lib:format("{~s,~w,~w}",[ModStr,Func,Line]) + io_lib:format("{~w,~w,~w}",[Mod,Func,Line]) end. downcase(S) -> downcase(S, []). @@ -581,22 +581,6 @@ downcase([C|Rest], Result) -> downcase([], Result) -> lists:reverse(Result). -package_str(Mod) when is_atom(Mod) -> - atom_to_list(Mod); -package_str(Mod) when is_list(Mod), is_atom(hd(Mod)) -> - %% convert [s1,s2] -> "s1.s2" - [_|M] = lists:flatten(["."++atom_to_list(S) || S <- Mod]), - M; -package_str(Mod) when is_list(Mod) -> - Mod. - -package_atom(Mod) when is_atom(Mod) -> - Mod; -package_atom(Mod) when is_list(Mod), is_atom(hd(Mod)) -> - list_to_atom(package_str(Mod)); -package_atom(Mod) when is_list(Mod) -> - list_to_atom(Mod). - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% call_trace(TraceSpecFile) -> ok %% diff --git a/lib/test_server/src/ts.erl b/lib/test_server/src/ts.erl index 115e783070..cfd7161dbd 100644 --- a/lib/test_server/src/ts.erl +++ b/lib/test_server/src/ts.erl @@ -160,8 +160,8 @@ help(installed) -> " the given run options\n", " ts:cross_cover_analyse(Level)\n" " - Used after ts:run with option cover or \n" - " cover_details. Analyses modules specified in\n" - " cross.cover.\n" + " cover_details. Analyses modules specified with\n" + " a 'cross' statement in the cover spec file.\n" " Level can be 'overview' or 'details'.\n", " ts:compile_testcases()~n" " ts:compile_testcases(Apps)~n" @@ -528,8 +528,7 @@ cross_cover_analyse([Level]) -> cross_cover_analyse(Level); cross_cover_analyse(Level) -> Apps = get_last_app_tests(), - Modules = get_cross_modules(Apps,[]), - test_server_ctrl:cross_cover_analyse(Level,Apps,Modules). + test_server_ctrl:cross_cover_analyse(Level,Apps). get_last_app_tests() -> AllTests = filelib:wildcard(filename:join(["*","*_test.logs"])), @@ -558,30 +557,6 @@ get_last_app_tests([Dir|Dirs],RE,Acc) -> get_last_app_tests([],_,Acc) -> Acc. -get_cross_modules([{App,_}|Apps],Acc) -> - Mods = cross_modules(App), - get_cross_modules(Apps,lists:umerge(Mods,Acc)); -get_cross_modules([],Acc) -> - Acc. - -cross_modules(App) -> - case default_coverfile(App) of - none -> - []; - File -> - case catch file:consult(File) of - {ok,CoverSpec} -> - case lists:keyfind(cross_apps,1,CoverSpec) of - false -> - []; - {cross_apps,App,Modules} -> - lists:usort(Modules) - end; - _ -> - [] - end - end. - %%% Implementation. check_and_run(Fun) -> diff --git a/lib/test_server/test/test_server_SUITE.erl b/lib/test_server/test/test_server_SUITE.erl index 95a3423fef..fb82a87fd0 100644 --- a/lib/test_server/test/test_server_SUITE.erl +++ b/lib/test_server/test/test_server_SUITE.erl @@ -80,7 +80,7 @@ all() -> [test_server_SUITE, test_server_parallel01_SUITE, test_server_conf02_SUITE, test_server_conf01_SUITE, test_server_skip_SUITE, test_server_shuffle01_SUITE, - test_server_break_SUITE]. + test_server_break_SUITE, test_server_cover_SUITE]. %%-------------------------------------------------------------------- @@ -93,37 +93,95 @@ test_server_SUITE(Config) -> % rpc:call(Node,dbg, tracer,[]), % rpc:call(Node,dbg, p,[all,c]), % rpc:call(Node,dbg, tpl,[test_server_ctrl,x]), - run_test_server_tests("test_server_SUITE", 38, 1, 30, - 19, 9, 1, 11, 2, 25, Config). + run_test_server_tests("test_server_SUITE", + [{test_server_SUITE,skip_case7,"SKIPPED!"}], + 38, 1, 30, 19, 9, 1, 11, 2, 25, Config). test_server_parallel01_SUITE(Config) -> - run_test_server_tests("test_server_parallel01_SUITE", 37, 0, 19, - 19, 0, 0, 0, 0, 37, Config). + run_test_server_tests("test_server_parallel01_SUITE", [], + 37, 0, 19, 19, 0, 0, 0, 0, 37, Config). test_server_shuffle01_SUITE(Config) -> - run_test_server_tests("test_server_shuffle01_SUITE", 130, 0, 0, - 76, 0, 0, 0, 0, 130, Config). + run_test_server_tests("test_server_shuffle01_SUITE", [], + 130, 0, 0, 76, 0, 0, 0, 0, 130, Config). test_server_skip_SUITE(Config) -> - run_test_server_tests("test_server_skip_SUITE", 3, 0, 1, - 0, 0, 1, 3, 0, 0, Config). + run_test_server_tests("test_server_skip_SUITE", [], + 3, 0, 1, 0, 0, 1, 3, 0, 0, Config). test_server_conf01_SUITE(Config) -> - run_test_server_tests("test_server_conf01_SUITE", 24, 0, 12, - 12, 0, 0, 0, 0, 24, Config). + run_test_server_tests("test_server_conf01_SUITE", [], + 24, 0, 12, 12, 0, 0, 0, 0, 24, Config). test_server_conf02_SUITE(Config) -> - run_test_server_tests("test_server_conf02_SUITE", 26, 0, 12, - 12, 0, 0, 0, 0, 26, Config). + run_test_server_tests("test_server_conf02_SUITE", [], + 26, 0, 12, 12, 0, 0, 0, 0, 26, Config). test_server_break_SUITE(Config) -> - D = run_test_server_tests("test_server_break_SUITE", 8, 2, 6, - 4, 0, 0, 0, 2, 6, Config), - D. + run_test_server_tests("test_server_break_SUITE", [], + 8, 2, 6, 4, 0, 0, 0, 2, 6, Config). -run_test_server_tests(SuiteName, NCases, NFail, NExpected, NSucc, +test_server_cover_SUITE(Config) -> + case test_server:is_cover() of + true -> + {skip, "Cover already running"}; + false -> + PrivDir = ?config(priv_dir,Config), + + %% Test suite has two test cases + %% tc1 calls cover_helper:foo/0 + %% tc2 calls cover_helper:bar/0 + %% Each function in cover_helper is one line. + %% + %% First test run skips tc2, so only cover_helper:foo/0 is executed. + %% Cover file specifies to include cover_helper in this test run. + CoverFile1 = filename:join(PrivDir,"t1.cover"), + CoverSpec1 = {include,[cover_helper]}, + file:write_file(CoverFile1,io_lib:format("~p.~n",[CoverSpec1])), + run_test_server_tests("test_server_cover_SUITE", + [{test_server_cover_SUITE,tc2,"SKIPPED!"}], + 4, 0, 2, 1, 1, 0, 1, 0, 3, + CoverFile1, Config), + + %% Next test run skips tc1, so only cover_helper:bar/0 is executed. + %% Cover file specifies cross compilation of cover_helper + CoverFile2 = filename:join(PrivDir,"t2.cover"), + CoverSpec2 = {cross,[{t1,[cover_helper]}]}, + file:write_file(CoverFile2,io_lib:format("~p.~n",[CoverSpec2])), + run_test_server_tests("test_server_cover_SUITE", + [{test_server_cover_SUITE,tc1,"SKIPPED!"}], + 4, 0, 2, 1, 1, 0, 1, 0, 3, CoverFile2, Config), + + %% Cross cover analyse + WorkDir = ?config(work_dir,Config), + WC = filename:join([WorkDir,"test_server_cover_SUITE.logs","run.*"]), + [D2,D1|_] = lists:reverse(lists:sort(filelib:wildcard(WC))), + TagDirs = [{t1,D1},{t2,D2}], + test_server_ctrl:cross_cover_analyse(details,TagDirs), + + %% Check that cover log shows only what is really included + %% in the test and cross cover log show the accumulated + %% result. + {ok,Cover1} = file:read_file(filename:join(D1,"cover.log")), + [{cover_helper,{1,1,_}}] = binary_to_term(Cover1), + {ok,Cover2} = file:read_file(filename:join(D2,"cover.log")), + [] = binary_to_term(Cover2), + {ok,Cross} = file:read_file(filename:join(D1,"cross_cover.log")), + [{cover_helper,{2,0,_}}] = binary_to_term(Cross), + ok + end. + + +run_test_server_tests(SuiteName, Skip, NCases, NFail, NExpected, NSucc, NUsrSkip, NAutoSkip, NActualSkip, NActualFail, NActualSucc, Config) -> + run_test_server_tests(SuiteName, Skip, NCases, NFail, NExpected, NSucc, + NUsrSkip, NAutoSkip, + NActualSkip, NActualFail, NActualSucc, false, Config). + +run_test_server_tests(SuiteName, Skip, NCases, NFail, NExpected, NSucc, + NUsrSkip, NAutoSkip, + NActualSkip, NActualFail, NActualSucc, Cover, Config) -> WorkDir = proplists:get_value(work_dir, Config), ct:log("<a href=\"file://~s\">Test case log files</a>\n", @@ -131,11 +189,17 @@ run_test_server_tests(SuiteName, NCases, NFail, NExpected, NSucc, Node = proplists:get_value(node, Config), {ok,_Pid} = rpc:call(Node,test_server_ctrl, start, []), + case Cover of + false -> + ok; + _ -> + rpc:call(Node,test_server_ctrl,cover,[Cover,details]) + end, rpc:call(Node, test_server_ctrl,add_dir_with_skip, [SuiteName, [proplists:get_value(data_dir,Config)],SuiteName, - [{test_server_SUITE,skip_case7,"SKIPPED!"}]]), + Skip]), until(fun() -> rpc:call(Node,test_server_ctrl,jobs,[]) =:= [] diff --git a/lib/test_server/test/test_server_SUITE_data/Makefile.src b/lib/test_server/test/test_server_SUITE_data/Makefile.src index ec8ddd78b0..c770627f04 100644 --- a/lib/test_server/test/test_server_SUITE_data/Makefile.src +++ b/lib/test_server/test/test_server_SUITE_data/Makefile.src @@ -5,4 +5,6 @@ all: erlc test_server_shuffle01_SUITE.erl erlc test_server_conf02_SUITE.erl erlc test_server_skip_SUITE.erl - erlc test_server_break_SUITE.erl
\ No newline at end of file + erlc test_server_break_SUITE.erl + erlc test_server_cover_SUITE.erl + erlc +debug_info test_server_cover_SUITE_data/cover_helper.erl
\ No newline at end of file diff --git a/lib/test_server/test/test_server_SUITE_data/test_server_break_SUITE.erl b/lib/test_server/test/test_server_SUITE_data/test_server_break_SUITE.erl index 70e30a3334..d9f009679a 100644 --- a/lib/test_server/test/test_server_SUITE_data/test_server_break_SUITE.erl +++ b/lib/test_server/test/test_server_SUITE_data/test_server_break_SUITE.erl @@ -41,7 +41,7 @@ init_per_suite(Config) -> spawn(fun break_and_continue_sup/0), Config. -end_per_suite(Config) -> +end_per_suite(_Config) -> ok. init_per_testcase(Case,Config) when Case==break_in_init_tc -> @@ -90,19 +90,19 @@ break_in_end_tc_after_fail(Config) when is_list(Config) -> break_in_end_tc_after_abort(Config) when is_list(Config) -> ?t:adjusted_sleep(2000). % will cause a timetrap timeout -%%%----------------------------------------------------------------- -%%% Internal functions - %% This test case checks that all breaks in previous test cases was %% also continued, and that the break lasted as long as expected. %% The reason for this is that some of the breaks above are in %% end_per_testcase, and failures there will only produce a warning, %% not an error - so this is to catch the error for real. -check_all_breaks(Config) -> +check_all_breaks(Config) when is_list(Config) -> break_and_continue_sup ! {done,self()}, receive {Breaks,Continued} -> check_all_breaks(Breaks,Continued) end. +%%%----------------------------------------------------------------- +%%% Internal functions + check_all_breaks([{From,Case,T,Start}|Breaks],[{From,End}|Continued]) -> Diff = timer:now_diff(End,Start), diff --git a/lib/test_server/test/test_server_SUITE_data/test_server_cover_SUITE.erl b/lib/test_server/test/test_server_SUITE_data/test_server_cover_SUITE.erl new file mode 100644 index 0000000000..b1ae70a302 --- /dev/null +++ b/lib/test_server/test/test_server_SUITE_data/test_server_cover_SUITE.erl @@ -0,0 +1,58 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2012. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +-module(test_server_cover_SUITE). + +-export([all/1, init_per_suite/1, end_per_suite/1]). +-export([init_per_testcase/2, end_per_testcase/2]). +-export([tc1/1, tc2/1]). + +-include_lib("test_server/include/test_server.hrl"). + +all(suite) -> + [tc1,tc2]. + +init_per_suite(Config) -> + Config. + +end_per_suite(_Config) -> + ok. + +init_per_testcase(_Case,Config) -> + Dog = ?t:timetrap({minutes,10}), + [{watchdog, Dog}|Config]. + +end_per_testcase(_Case,Config) -> + Dog=?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + ok. + + +%%%----------------------------------------------------------------- +%%% Test cases +tc1(Config) when is_list(Config) -> + cover_helper:foo(), + ok. + +tc2(Config) when is_list(Config) -> + cover_helper:bar(), + ok. + +%%%----------------------------------------------------------------- +%%% Internal functions + diff --git a/lib/test_server/test/test_server_SUITE_data/test_server_cover_SUITE_data/cover_helper.erl b/lib/test_server/test/test_server_SUITE_data/test_server_cover_SUITE_data/cover_helper.erl new file mode 100644 index 0000000000..6c74eb4e8a --- /dev/null +++ b/lib/test_server/test/test_server_SUITE_data/test_server_cover_SUITE_data/cover_helper.erl @@ -0,0 +1,4 @@ +-module(cover_helper). +-compile(export_all). +foo() -> ok. +bar() -> ok. diff --git a/lib/wx/aclocal.m4 b/lib/wx/aclocal.m4 index 9578cd35c4..5d555a5123 100644 --- a/lib/wx/aclocal.m4 +++ b/lib/wx/aclocal.m4 @@ -1849,6 +1849,32 @@ case $erl_gethrvtime in esac ])dnl +dnl ---------------------------------------------------------------------- +dnl +dnl LM_TRY_ENABLE_CFLAG +dnl +dnl +dnl Tries a CFLAG and sees if it can be enabled without compiler errors +dnl $1: textual cflag to add +dnl $2: variable to store the modified CFLAG in +dnl Usage example LM_TRY_ENABLE_CFLAG([-Werror=return-type], [CFLAGS]) +dnl +dnl +AC_DEFUN([LM_TRY_ENABLE_CFLAG], [ + AC_MSG_CHECKING([if we can add $1 to CFLAGS]) + saved_CFLAGS=$CFLAGS; + CFLAGS="$1 $CFLAGS"; + AC_TRY_COMPILE([],[return 0;],can_enable_flag=true,can_enable_flag=false) + CFLAGS=$saved_CFLAGS; + if test "X$can_enable_flag" = "Xtrue"; then + AC_MSG_RESULT([yes]) + AS_VAR_SET($2, "$1 $CFLAGS") + else + AC_MSG_RESULT([no]) + AS_VAR_SET($2, "$CFLAGS") + fi +]) + dnl ERL_TRY_LINK_JAVA(CLASSES, FUNCTION-BODY dnl [ACTION_IF_FOUND [, ACTION-IF-NOT-FOUND]]) dnl Freely inspired by AC_TRY_LINK. (Maybe better to create a diff --git a/lib/wx/configure.in b/lib/wx/configure.in index 8a1083e54b..c45d2285af 100755 --- a/lib/wx/configure.in +++ b/lib/wx/configure.in @@ -643,6 +643,12 @@ fi dnl - if test "$WXERL_CAN_BUILD_DRIVER" != "false" AC_SUBST(WXERL_CAN_BUILD_DRIVER) +if test "x$GCC" = xyes; then + # Treat certain GCC warnings as errors + LM_TRY_ENABLE_CFLAG([-Werror=return-type], [CFLAGS]) + LM_TRY_ENABLE_CFLAG([-Werror=return-type], [CXXFLAGS]) +fi + ############################################################################# dnl |