diff options
Diffstat (limited to 'lib/asn1')
-rw-r--r-- | lib/asn1/doc/src/asn1_ug.xml | 50 | ||||
-rw-r--r-- | lib/asn1/doc/src/asn1ct.xml | 6 | ||||
-rw-r--r-- | lib/asn1/doc/src/asn1rt.xml | 30 | ||||
-rw-r--r-- | lib/asn1/src/asn1.appup.src | 30 | ||||
-rw-r--r-- | lib/asn1/src/asn1ct.erl | 16 | ||||
-rw-r--r-- | lib/asn1/src/asn1ct_check.erl | 69 | ||||
-rw-r--r-- | lib/asn1/src/asn1ct_gen.erl | 6 | ||||
-rw-r--r-- | lib/asn1/src/asn1ct_table.erl | 34 | ||||
-rw-r--r-- | lib/asn1/src/asn1ct_tok.erl | 2 | ||||
-rw-r--r-- | lib/asn1/src/asn1ct_value.erl | 3 | ||||
-rw-r--r-- | lib/asn1/src/asn1rt.erl | 3 | ||||
-rw-r--r-- | lib/asn1/test/asn1_SUITE.erl | 2 | ||||
-rw-r--r-- | lib/asn1/test/asn1_SUITE_data/EnumExt.asn1 | 2 | ||||
-rw-r--r-- | lib/asn1/test/asn1_appup_test.erl | 359 | ||||
-rw-r--r-- | lib/asn1/test/error_SUITE.erl | 29 | ||||
-rw-r--r-- | lib/asn1/test/testEnumExt.erl | 4 | ||||
-rw-r--r-- | lib/asn1/test/testPrimStrings.erl | 2 |
17 files changed, 157 insertions, 490 deletions
diff --git a/lib/asn1/doc/src/asn1_ug.xml b/lib/asn1/doc/src/asn1_ug.xml index eb9f000e75..ee54fdffd7 100644 --- a/lib/asn1/doc/src/asn1_ug.xml +++ b/lib/asn1/doc/src/asn1_ug.xml @@ -205,16 +205,13 @@ ok is saved in the <c>People.asn1db</c> file, the generated Erlang code is compiled using the Erlang compiler and loaded into the Erlang runtime system. Now there is a user interface - of encode/2 and decode/2 in the module People, which is invoked by: + for <c>encode/2</c> and <c>decode/2</c> in the module People, + which is invoked by: <br></br> <c><![CDATA['People':encode(<Type name>,<Value>),]]></c> <br></br> or <br></br> -<c><![CDATA['People':decode(<Type name>,<Value>),]]></c> <br></br> - - Alternatively one can use the <c><![CDATA[asn1rt:encode(<Module name> ,<Type name>,<Value>)]]></c> and <c><![CDATA[asn1rt:decode(< Module name>,<Type name>,<Value>)]]></c> calls. - However, they are not as efficient as the previous methods since they - result in an additional <c>apply/3</c> call.</p> +<c><![CDATA['People':decode(<Type name>,<Value>),]]></c></p> <p>Assume there is a network application which receives instances of the ASN.1 defined type Person, modifies and sends them back again:</p> @@ -241,16 +238,14 @@ receive encoding-rules. <br></br> The encoder and the decoder can also be run from - the shell. The following dialogue with the shell illustrates - how the functions - <c>asn1rt:encode/3</c> and <c>asn1rt:decode/3</c> are used.</p> + the shell.</p> <pre> 2> <input>Rockstar = {'Person',"Some Name",roving,50}.</input> {'Person',"Some Name",roving,50} -3> <input>{ok,Bin} = asn1rt:encode('People','Person',Rockstar).</input> +3> <input>{ok,Bin} = 'People':encode('Person',Rockstar).</input> {ok,<<243,17,19,9,83,111,109,101,32,78,97,109,101,2,1,2, 2,1,50>>} -4> <input>{ok,Person} = asn1rt:decode('People','Person',Bin).</input> +4> <input>{ok,Person} = 'People':decode('Person',Bin).</input> {ok,{'Person',"Some Name",roving,50}} 5> </pre> </section> @@ -279,11 +274,8 @@ The encoder and the decoder can also be run from (including the compiler).</p> </item> <item> - <p>The module <c>asn1rt</c> which provides the run-time functions. - However, it is preferable to use the generated <c>encode/2</c> and - <c>decode/2</c> functions in each module, ie. - Module:encode(Type,Value), in favor of the <c>asn1rt</c> - interface.</p> + <p>The module <c>asn1rt_nif</c> which provides the run-time functions + for the ASN.1 decoder for the BER back-end.</p> </item> </list> <p>The reason for the division of the interface into compile-time @@ -384,25 +376,9 @@ asn1ct:decode('H323-MESSAGES','SomeChoiceType',Bytes). </pre> <section> <title>Run-time Functions</title> - <p>A brief description of the major functions is given here. For a - complete description of each function see - <seealso marker="asn1rt"> the Asn1 Reference Manual</seealso>, the <c>asn1rt</c> module.</p> - <p>The generic run-time encode and decode functions can be invoked as below:</p> - <pre> -asn1rt:encode('H323-MESSAGES','SomeChoiceType',{call,"octetstring"}). -asn1rt:decode('H323-MESSAGES','SomeChoiceType',Bytes). </pre> - <p>Or, preferable like:</p> - <pre> -'H323-MESSAGES':encode('SomeChoiceType',{call,"octetstring"}). -'H323-MESSAGES':decode('SomeChoiceType',Bytes). </pre> - <p>The asn1 nif is enabled in two occasions: encoding of - asn1 values when the asn1 spec is compiled with <c>per</c> and - or decode of encoded asn1 values when the asn1 spec is - compiled with <c>ber</c>. In - those cases the nif will be loaded automatically at the first call - to <c>encode</c>/<c>decode</c>. If one doesn't want the performance - overhead of the nif being loaded at the first call it is possible - to load the nif separately by loading the <c>asn1rt_nif</c> module.</p> + <p>When an ASN.1 specification is compiled with the <c>ber</c> + option, the module <c>asn1rt_nif</c> module and the NIF library in + <c>asn1/priv_dir</c> will be needed at run-time.</p> <p>By invoking the function <c>info/0</c> in a generated module, one gets information about which compiler options were used.</p> </section> @@ -414,8 +390,8 @@ asn1rt:decode('H323-MESSAGES','SomeChoiceType',Bytes). </pre> a line number indicating where in the source file the error was detected. If no errors are found, an Erlang ASN.1 module will be created as default.</p> - <p>The run-time encoders and decoders (in the <c>asn1rt</c> module) do - execute within a catch and returns <c>{ok, Data}</c> or + <p>The run-time encoders and decoders execute within a catch and + returns <c>{ok, Data}</c> or <c>{error, {asn1, Description}}</c> where <c>Description</c> is an Erlang term describing the error. </p> diff --git a/lib/asn1/doc/src/asn1ct.xml b/lib/asn1/doc/src/asn1ct.xml index 5871c8ad68..4d5a1a402a 100644 --- a/lib/asn1/doc/src/asn1ct.xml +++ b/lib/asn1/doc/src/asn1ct.xml @@ -61,7 +61,7 @@ and <c>uper_bin</c> options will still work, but will print a warning. </p> <p>Another change in R16 is that the generated <c>encode/2</c> - function (and <c>asn1rt:encode/3</c>) always returns a binary. + function always returns a binary. The <c>encode/2</c> function for the BER back-end used to return an iolist.</p> </note> @@ -326,6 +326,8 @@ File3.asn </pre> not always checked. Returns <c>{ok, Bytes}</c> if successful or <c>{error, Reason}</c> if an error occurred. </p> + <p>This function is deprecated. + Use <c>Module:encode(Type, Value)</c> instead.</p> </desc> </func> <func> @@ -339,6 +341,8 @@ File3.asn </pre> <desc> <p>Decodes <c>Type</c> from <c>Module</c> from the binary <c>Bytes</c>. Returns <c>{ok, Value}</c> if successful.</p> + <p>This function is deprecated. + Use <c>Module:decode(Type, Bytes)</c> instead.</p> </desc> </func> <func> diff --git a/lib/asn1/doc/src/asn1rt.xml b/lib/asn1/doc/src/asn1rt.xml index 6e22e45d93..3cf56b01ca 100644 --- a/lib/asn1/doc/src/asn1rt.xml +++ b/lib/asn1/doc/src/asn1rt.xml @@ -34,9 +34,12 @@ <module>asn1rt</module> <modulesummary>ASN.1 runtime support functions</modulesummary> <description> - <p>This module is the interface module for the ASN.1 runtime support functions. - To encode and decode ASN.1 types in runtime the functions in this module - should be used.</p> + <warning> + <p> + All functions in this module are deprecated and will be + removed in a future release. + </p> + </warning> </description> <funcs> @@ -52,6 +55,7 @@ <desc> <p>Decodes <c>Type</c> from <c>Module</c> from the binary <c>Bytes</c>. Returns <c>{ok,Value}</c> if successful.</p> + <p>Use <c>Module:decode(Type, Bytes)</c> instead of this function.</p> </desc> </func> @@ -65,16 +69,13 @@ <v>Reason = term()</v> </type> <desc> - <p>Encodes <c>Value</c> of <c>Type</c> defined in the ASN.1 module - <c>Module</c>. Returns a possibly nested list of bytes and or binaries - if successful. To get as fast execution as possible the - encode function only performs rudimentary tests that the input - <c>Value</c> - is a correct instance of <c>Type</c>. The length of strings is for example - not always checked. </p> - <note> - <p>Starting in R16, <c>Bytes</c> is always a binary.</p> - </note> + <p>Encodes <c>Value</c> of <c>Type</c> defined in the ASN.1 + module <c>Module</c>. Returns a binary if successful. To get + as fast execution as possible the encode function only + performs rudimentary tests that the input <c>Value</c> is a + correct instance of <c>Type</c>. The length of strings is, for + example, not always checked. </p> + <p>Use <c>Module:encode(Type, Value)</c> instead of this function.</p> </desc> </func> @@ -90,6 +91,7 @@ <p><c>info/1</c> returns the version of the asn1 compiler that was used to compile the module. It also returns the compiler options that was used.</p> + <p>Use <c>Module:info()</c> instead of this function.</p> </desc> </func> @@ -106,6 +108,7 @@ to a list of integers, where each integer represents one character as its unicode value. The function fails if the binary is not a properly encoded UTF8 string.</p> + <p>Use <seealso marker="stdlib:unicode#characters_to_list-1">unicode:characters_to_list/1</seealso> instead of this function.</p> </desc> </func> @@ -121,6 +124,7 @@ <p><c>utf8_list_to_binary/1</c> Transforms a list of integers, where each integer represents one character as its unicode value, to a UTF8 encoded binary.</p> + <p>Use <seealso marker="stdlib:unicode#characters_to_binary-1">unicode:characters_to_binary/1</seealso> instead of this function.</p> </desc> </func> diff --git a/lib/asn1/src/asn1.appup.src b/lib/asn1/src/asn1.appup.src index 2d11eddfbf..e4b3508cc4 100644 --- a/lib/asn1/src/asn1.appup.src +++ b/lib/asn1/src/asn1.appup.src @@ -1,11 +1,21 @@ +%% -*- erlang -*- +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2014. 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% {"%VSN%", -% This version does not change anything of the runtime modules -% Only changes in compile time modules and thus no need for upgrade on target -[ - ], - [ - ]}. - - - - + [{<<".*">>,[{restart_application, asn1}]}], + [{<<".*">>,[{restart_application, asn1}]}] +}. diff --git a/lib/asn1/src/asn1ct.erl b/lib/asn1/src/asn1ct.erl index 531a4935fe..9ec43197bf 100644 --- a/lib/asn1/src/asn1ct.erl +++ b/lib/asn1/src/asn1ct.erl @@ -19,6 +19,10 @@ %% %% -module(asn1ct). +-deprecated([decode/3,encode/3]). +-compile([{nowarn_deprecated_function,{asn1rt,decode,3}}, + {nowarn_deprecated_function,{asn1rt,encode,2}}, + {nowarn_deprecated_function,{asn1rt,encode,3}}]). %% Compile Time functions for ASN.1 (e.g ASN.1 compiler). @@ -1040,7 +1044,7 @@ get_file_list1(Stream,Dir,Includes,Acc) -> Ret = io:get_line(Stream,''), case Ret of eof -> - file:close(Stream), + ok = file:close(Stream), lists:reverse(Acc); FileName -> SuffixedNameList = @@ -1926,8 +1930,9 @@ read_config_file(ModuleName) -> Includes = [I || {i,I} <- Options], read_config_file1(ModuleName,Includes); {error,Reason} -> - file:format_error(Reason), - throw({error,{"error reading asn1 config file",Reason}}) + Error = "error reading asn1 config file: " ++ + file:format_error(Reason), + throw({error,Error}) end. read_config_file1(ModuleName,[]) -> case filename:extension(ModuleName) of @@ -1945,8 +1950,9 @@ read_config_file1(ModuleName,[H|T]) -> {error,enoent} -> read_config_file1(ModuleName,T); {error,Reason} -> - file:format_error(Reason), - throw({error,{"error reading asn1 config file",Reason}}) + Error = "error reading asn1 config file: " ++ + file:format_error(Reason), + throw({error,Error}) end. get_config_info(CfgList,InfoType) -> diff --git a/lib/asn1/src/asn1ct_check.erl b/lib/asn1/src/asn1ct_check.erl index f94f3b56bc..b9f2cb876a 100644 --- a/lib/asn1/src/asn1ct_check.erl +++ b/lib/asn1/src/asn1ct_check.erl @@ -2464,7 +2464,7 @@ normalize_value(S0, Type, {'DEFAULT',Value}, NameList) -> {'BIT STRING',CType,_} -> normalize_bitstring(S,Value,CType); {'OCTET STRING',CType,_} -> - normalize_octetstring(S,Value,CType); + normalize_octetstring(S0, Value, CType); {'NULL',_CType,_} -> %%normalize_null(Value); 'NULL'; @@ -2612,20 +2612,9 @@ normalize_octetstring(S,Value,CType) -> fun normalize_octetstring/3,[]); {Name,String} when is_atom(Name) -> normalize_octetstring(S,String,CType); - List when is_list(List) -> - %% check if list elements are valid octet values - lists:map(fun([])-> ok; - (H)when H > 255-> - asn1ct:warning("not legal octet value ~p in OCTET STRING, ~p~n", - [H,List],S, - "not legal octet value ~p in OCTET STRING"); - (_)-> ok - end, List), - List; - Other -> - asn1ct:warning("unknown default value ~p~n",[Other],S, - "unknown default value"), - Value + _ -> + Item = S#state.value, + throw(asn1_error(S, Item, illegal_octet_string_value)) end. normalize_objectidentifier(S, Value) -> @@ -2642,16 +2631,19 @@ normalize_objectdescriptor(Value) -> normalize_real(Value) -> Value. -normalize_enumerated(S, Id, {Base,Ext}) -> +normalize_enumerated(S, Id0, NNL) -> + {Id,_} = lookup_enum_value(S, Id0, NNL), + Id. + +lookup_enum_value(S, Id, {Base,Ext}) -> %% Extensible ENUMERATED. - normalize_enumerated(S, Id, Base++Ext); -normalize_enumerated(S, #'Externalvaluereference'{value=Id}, - NamedNumberList) -> - normalize_enumerated(S, Id, NamedNumberList); -normalize_enumerated(S, Id, NamedNumberList) when is_atom(Id) -> - case lists:keymember(Id, 1, NamedNumberList) of - true -> - Id; + lookup_enum_value(S, Id, Base++Ext); +lookup_enum_value(S, #'Externalvaluereference'{value=Id}, NNL) -> + lookup_enum_value(S, Id, NNL); +lookup_enum_value(S, Id, NNL) when is_atom(Id) -> + case lists:keyfind(Id, 1, NNL) of + {_,_}=Ret -> + Ret; false -> throw(asn1_error(S, S#state.value, {undefined,Id})) end. @@ -3088,7 +3080,6 @@ check_type(S=#state{recordtopname=TopName},Type,Ts) when is_record(Ts,type) -> Ct=maybe_illicit_implicit_tag(open_type,Tag), TempNewDef#newt{type='ASN1_OPEN_TYPE',tag=Ct}; 'INTEGER' -> - check_integer(S,[],Constr), TempNewDef#newt{tag= merge_tags(Tag,?TAG_PRIMITIVE(?N_INTEGER))}; @@ -3786,8 +3777,9 @@ resolv_value(S,Val) -> resolv_value1(S,Id). resolv_value1(S, ERef = #'Externalvaluereference'{value=Name}) -> - case catch resolve_namednumber(S,S#state.type,Name) of - V when is_integer(V) -> V; + case catch resolve_namednumber(S, S#state.type, Name) of + V when is_integer(V) -> + V; _ -> case get_referenced_type(S,ERef) of {Err,_Reason} when Err == error; Err == 'EXIT' -> @@ -3840,21 +3832,20 @@ resolve_value_from_object(S,Object,FieldName) -> end. - resolve_namednumber(S,#typedef{typespec=Type},Name) -> case Type#type.def of {'ENUMERATED',NameList} -> - NamedNumberList=check_enumerated(S,NameList,Type#type.constraint), - N = normalize_enumerated(S,Name,NamedNumberList), - {value,{_,V}} = lists:keysearch(N,1,NamedNumberList), - V; + resolve_namednumber_1(S, Name, NameList, Type); {'INTEGER',NameList} -> - NamedNumberList = check_enumerated(S,NameList,Type#type.constraint), - {value,{_,V}} = lists:keysearch(Name,1,NamedNumberList), - V; + resolve_namednumber_1(S, Name, NameList, Type); _ -> not_enumerated end. + +resolve_namednumber_1(S, Name, NameList, Type) -> + NamedNumberList = check_enumerated(S, NameList, Type#type.constraint), + {_,N} = lookup_enum_value(S, Name, NamedNumberList), + N. check_constraints(S,[{'ContainedSubtype',Type} | Rest], Acc) -> {RefMod,CTDef} = get_referenced_type(S,Type#type.def), @@ -3935,9 +3926,9 @@ check_constraint(S,{simpletable,Type}) -> #'Externaltypereference'{} -> ERef = check_externaltypereference(S,C), {simpletable,ERef#'Externaltypereference'.type}; - #type{def=#'Externaltypereference'{type=T}} -> - check_externaltypereference(S,C#type.def), - {simpletable,T}; + #type{def=#'Externaltypereference'{}=ExtTypeRef} -> + ERef = check_externaltypereference(S, ExtTypeRef), + {simpletable,ERef#'Externaltypereference'.type}; {valueset,#type{def=ERef=#'Externaltypereference'{}}} -> % this is an object set {_,TDef} = get_referenced_type(S,ERef), case TDef#typedef.typespec of @@ -6811,6 +6802,8 @@ asn1_error(#state{mname=Where}, Item, Error) -> format_error({already_defined,Name,PrevLine}) -> io_lib:format("the name ~p has already been defined at line ~p", [Name,PrevLine]); +format_error(illegal_octet_string_value) -> + "expecting a bstring or an hstring as value for an OCTET STRING"; format_error({invalid_fields,Fields,Obj}) -> io_lib:format("invalid ~s in ~p", [format_fields(Fields),Obj]); format_error({missing_mandatory_fields,Fields,Obj}) -> diff --git a/lib/asn1/src/asn1ct_gen.erl b/lib/asn1/src/asn1ct_gen.erl index 71d870b4ce..4707e517b4 100644 --- a/lib/asn1/src/asn1ct_gen.erl +++ b/lib/asn1/src/asn1ct_gen.erl @@ -71,7 +71,7 @@ pgen_module(OutFile,Erules,Module, HrlGenerated = pgen_hrl(Erules,Module,TypeOrVal,Options,Indent), asn1ct_name:start(), ErlFile = lists:concat([OutFile,".erl"]), - open_output_file(ErlFile), + _ = open_output_file(ErlFile), asn1ct_func:start_link(), gen_head(Erules,Module,HrlGenerated), pgen_exports(Erules,Module,TypeOrVal), @@ -190,7 +190,7 @@ pgen_check_defaultval(Erules,Module) -> "********~n~n",[X]) end, lists:foreach(Fun,CheckObjects), - file:close(IoDevice); + ok = file:close(IoDevice); _ -> ok end, gen_check_defaultval(Erules,Module,CheckObjects). @@ -1124,7 +1124,7 @@ pgen_info() -> open_hrl(OutFile,Module) -> File = lists:concat([OutFile,".hrl"]), - open_output_file(File), + _ = open_output_file(File), gen_hrlhead(Module). %% EMIT functions ************************ diff --git a/lib/asn1/src/asn1ct_table.erl b/lib/asn1/src/asn1ct_table.erl index a5eb6d0413..2eca80eda3 100644 --- a/lib/asn1/src/asn1ct_table.erl +++ b/lib/asn1/src/asn1ct_table.erl @@ -22,34 +22,25 @@ %% Table abstraction module for ASN.1 compiler -export([new/1]). --export([new/2]). -export([new_reuse/1]). --export([new_reuse/2]). -export([exists/1]). -export([size/1]). -export([insert/2]). -export([lookup/2]). -export([match/2]). -export([to_list/1]). --export([delete/1]). % TODO: Remove (since we run in a separate process) +-export([delete/1]). -%% Always creates a new table -new(Table) -> new(Table, []). -new(Table, Options) -> - TableId = case get(Table) of - undefined -> - ets:new(Table, Options); - _ -> - delete(Table), - ets:new(Table, Options) - end, +%% Always create a new table. +new(Table) -> + undefined = get(Table), %Assertion. + TableId = ets:new(Table, []), put(Table, TableId). -%% Only create it if it doesn't exist yet -new_reuse(Table) -> new_reuse(Table, []). -new_reuse(Table, Options) -> - not exists(Table) andalso new(Table, Options). +%% Only create it if it doesn't exist yet. +new_reuse(Table) -> + not exists(Table) andalso new(Table). exists(Table) -> get(Table) =/= undefined. @@ -63,14 +54,17 @@ match(Table, MatchSpec) -> ets:match(get(Table), MatchSpec). to_list(Table) -> ets:tab2list(get(Table)). +%% Deleting tables is no longer strictly necessary since each compilation +%% runs in separate process, but it will reduce memory consumption +%% especially when many compilations are run in parallel. + delete(Tables) when is_list(Tables) -> [delete(T) || T <- Tables], true; delete(Table) when is_atom(Table) -> - case get(Table) of + case erase(Table) of undefined -> true; TableId -> - ets:delete(TableId), - erase(Table) + ets:delete(TableId) end. diff --git a/lib/asn1/src/asn1ct_tok.erl b/lib/asn1/src/asn1ct_tok.erl index 85199c65ec..33f4379173 100644 --- a/lib/asn1/src/asn1ct_tok.erl +++ b/lib/asn1/src/asn1ct_tok.erl @@ -36,7 +36,7 @@ process(Stream,Lno,R) -> process(io:get_line(Stream, ''), Stream,Lno+1,R). process(eof, Stream,Lno,R) -> - file:close(Stream), + ok = file:close(Stream), lists:flatten(lists:reverse([{'$end',Lno}|R])); diff --git a/lib/asn1/src/asn1ct_value.erl b/lib/asn1/src/asn1ct_value.erl index a86c963b9d..221cd991a7 100644 --- a/lib/asn1/src/asn1ct_value.erl +++ b/lib/asn1/src/asn1ct_value.erl @@ -18,6 +18,7 @@ %% %% -module(asn1ct_value). +-compile([{nowarn_deprecated_function,{asn1rt,utf8_list_to_binary,1}}]). %% Generate Erlang values for ASN.1 types. %% The value is randomized within it's constraints @@ -352,7 +353,7 @@ random_unnamed_bit_string(M, C) -> random(Upper) -> {A1,A2,A3} = erlang:now(), - random:seed(A1,A2,A3), + _ = random:seed(A1, A2, A3), random:uniform(Upper). size_random(C) -> diff --git a/lib/asn1/src/asn1rt.erl b/lib/asn1/src/asn1rt.erl index d18f81346a..ad8b879c38 100644 --- a/lib/asn1/src/asn1rt.erl +++ b/lib/asn1/src/asn1rt.erl @@ -18,14 +18,13 @@ %% %% -module(asn1rt). +-deprecated(module). %% Runtime functions for ASN.1 (i.e encode, decode) -export([encode/2,encode/3,decode/3,load_driver/0,unload_driver/0,info/1]). -export([utf8_binary_to_list/1,utf8_list_to_binary/1]). - --deprecated([load_driver/0,unload_driver/0]). encode(Module,{Type,Term}) -> encode(Module,Type,Term). diff --git a/lib/asn1/test/asn1_SUITE.erl b/lib/asn1/test/asn1_SUITE.erl index 3b34feb5a3..d438300596 100644 --- a/lib/asn1/test/asn1_SUITE.erl +++ b/lib/asn1/test/asn1_SUITE.erl @@ -860,7 +860,7 @@ duplicate_tags(Config) -> rtUI(Config) -> test(Config, fun rtUI/3). rtUI(Config, Rule, Opts) -> asn1_test_lib:compile("Prim", Config, [Rule|Opts]), - {ok, _} = asn1rt:info('Prim'), + _ = 'Prim':info(), Rule = 'Prim':encoding_rule(), io:format("Default BIT STRING format: ~p\n", ['Prim':bit_string_format()]). diff --git a/lib/asn1/test/asn1_SUITE_data/EnumExt.asn1 b/lib/asn1/test/asn1_SUITE_data/EnumExt.asn1 index 8dc5f3d7e1..74fa97e7aa 100644 --- a/lib/asn1/test/asn1_SUITE_data/EnumExt.asn1 +++ b/lib/asn1/test/asn1_SUITE_data/EnumExt.asn1 @@ -18,6 +18,8 @@ Ext1 ::= ENUMERATED { magenta(9) } +SubExt1 ::= Ext1 ( blue | orange | black ) + Noext ::= ENUMERATED { blue(0), red(1), diff --git a/lib/asn1/test/asn1_appup_test.erl b/lib/asn1/test/asn1_appup_test.erl index a2c1423eda..7391959645 100644 --- a/lib/asn1/test/asn1_appup_test.erl +++ b/lib/asn1/test/asn1_appup_test.erl @@ -21,8 +21,8 @@ %% Purpose: Verify the application specifics of the asn1 application %%---------------------------------------------------------------------- -module(asn1_appup_test). --compile({no_auto_import,[error/1]}). -compile(export_all). +-include_lib("common_test/include/ct.hrl"). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -44,16 +44,9 @@ end_per_group(_GroupName, Config) -> init_per_suite(suite) -> []; init_per_suite(doc) -> []; init_per_suite(Config) when is_list(Config) -> - AppFile = file_name(asn1, ".app"), - AppupFile = file_name(asn1, ".appup"), - [{app_file, AppFile}, {appup_file, AppupFile}|Config]. + Config. -file_name(App, Ext) -> - LibDir = code:lib_dir(App), - filename:join([LibDir, "ebin", atom_to_list(App) ++ Ext]). - - end_per_suite(suite) -> []; end_per_suite(doc) -> []; end_per_suite(Config) when is_list(Config) -> @@ -62,349 +55,7 @@ end_per_suite(Config) when is_list(Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -appup(suite) -> - []; -appup(doc) -> - "perform a simple check of the appup file"; +appup() -> + [{doc, "perform a simple check of the asn1 appup file"}]. appup(Config) when is_list(Config) -> - AppupFile = key1search(appup_file, Config), - AppFile = key1search(app_file, Config), - Modules = modules(AppFile), - check_appup(AppupFile, Modules). - -modules(File) -> - case file:consult(File) of - {ok, [{application,asn1,Info}]} -> - case lists:keysearch(modules,1,Info) of - {value, {modules, Modules}} -> - Modules; - false -> - fail({bad_appinfo, Info}) - end; - Error -> - fail({bad_appfile, Error}) - end. - - -check_appup(AppupFile, Modules) -> - case file:consult(AppupFile) of - {ok, [{V, UpFrom, DownTo}]} -> - io:format("V= ~p, UpFrom= ~p, DownTo= ~p, Modules= ~p~n", - [V, UpFrom, DownTo, Modules]), - check_appup(V, UpFrom, DownTo, Modules); - Else -> - fail({bad_appupfile, Else}) - end. - - -check_appup(V, UpFrom, DownTo, Modules) -> - check_version(V), - check_depends(up, UpFrom, Modules), - check_depends(down, DownTo, Modules), - ok. - - -check_depends(_, [], _) -> - ok; -check_depends(UpDown, [Dep|Deps], Modules) -> - check_depend(UpDown, Dep, Modules), - check_depends(UpDown, Deps, Modules). - - -check_depend(up,I={add_application,_App},Modules) -> - d("check_instructions(~w) -> entry with" - "~n Instruction: ~p" - "~n Modules: ~p", [up,I , Modules]), - ok; -check_depend(down,I={remove_application,_App},Modules) -> - d("check_instructions(~w) -> entry with" - "~n Instruction: ~p" - "~n Modules: ~p", [down,I , Modules]), - ok; -check_depend(UpDown, {V, Instructions}, Modules) -> - d("check_instructions(~w) -> entry with" - "~n V: ~p" - "~n Modules: ~p", [UpDown, V, Modules]), - check_version(V), - case check_instructions(UpDown, - Instructions, Instructions, [], [], Modules) of - {_Good, []} -> - ok; - {_, Bad} -> - fail({bad_instructions, Bad, UpDown}) - end. - - -check_instructions(_, [], _, Good, Bad, _) -> - {lists:reverse(Good), lists:reverse(Bad)}; -check_instructions(UpDown, [Instr|Instrs], AllInstr, Good, Bad, Modules) -> - d("check_instructions(~w) -> entry with" - "~n Instr: ~p", [UpDown,Instr]), - case (catch check_instruction(UpDown, Instr, AllInstr, Modules)) of - ok -> - check_instructions(UpDown, Instrs, AllInstr, - [Instr|Good], Bad, Modules); - {error, Reason} -> - d("check_instructions(~w) -> bad instruction: " - "~n Reason: ~p", [UpDown,Reason]), - check_instructions(UpDown, Instrs, AllInstr, Good, - [{Instr, Reason}|Bad], Modules) - end. - -%% A new module is added -check_instruction(up, {add_module, Module}, _, Modules) - when is_atom(Module) -> - d("check_instruction -> entry when up-add_module instruction with" - "~n Module: ~p", [Module]), - check_module(Module, Modules); - -%% An old module is re-added -check_instruction(down, {add_module, Module}, _, Modules) - when is_atom(Module) -> - d("check_instruction -> entry when down-add_module instruction with" - "~n Module: ~p", [Module]), - case (catch check_module(Module, Modules)) of - {error, {unknown_module, Module, Modules}} -> - ok; - ok -> - error({existing_readded_module, Module}) - end; - -%% Removing a module on upgrade: -%% - the module has been removed from the app-file. -%% - check that no module depends on this (removed) module -check_instruction(up, {remove, {Module, Pre, Post}}, _, Modules) - when is_atom(Module), is_atom(Pre), is_atom(Post) -> - d("check_instruction -> entry when up-remove instruction with" - "~n Module: ~p" - "~n Pre: ~p" - "~n Post: ~p", [Module, Pre, Post]), - case (catch check_module(Module, Modules)) of - {error, {unknown_module, Module, Modules}} -> - check_purge(Pre), - check_purge(Post); - ok -> - error({existing_removed_module, Module}) - end; - -%% Removing a module on downgrade: the module exist -%% in the app-file. -check_instruction(down, {remove, {Module, Pre, Post}}, AllInstr, Modules) - when is_atom(Module), is_atom(Pre), is_atom(Post) -> - d("check_instruction -> entry when down-remove instruction with" - "~n Module: ~p" - "~n Pre: ~p" - "~n Post: ~p", [Module, Pre, Post]), - case (catch check_module(Module, Modules)) of - ok -> - check_purge(Pre), - check_purge(Post), - check_no_remove_depends(Module, AllInstr); - {error, {unknown_module, Module, Modules}} -> - error({nonexisting_removed_module, Module}) - end; - -check_instruction(_, {load_module, Module, Pre, Post, Depend}, - AllInstr, Modules) - when is_atom(Module), is_atom(Pre), is_atom(Post), is_list(Depend) -> - d("check_instruction -> entry when load_module instruction with" - "~n Module: ~p" - "~n Pre: ~p" - "~n Post: ~p" - "~n Depend: ~p", [Module, Pre, Post, Depend]), - check_module(Module, Modules), - check_module_depend(Module, Depend, Modules), - check_module_depend(Module, Depend, updated_modules(AllInstr, [])), - check_purge(Pre), - check_purge(Post); - -check_instruction(_, {update, Module, Change, Pre, Post, Depend}, - AllInstr, Modules) - when is_atom(Module), is_atom(Pre), is_atom(Post), is_list(Depend) -> - d("check_instruction -> entry when update instruction with" - "~n Module: ~p" - "~n Change: ~p" - "~n Pre: ~p" - "~n Post: ~p" - "~n Depend: ~p", [Module, Change, Pre, Post, Depend]), - check_module(Module, Modules), - check_module_depend(Module, Depend, Modules), - check_module_depend(Module, Depend, updated_modules(AllInstr, [])), - check_change(Change), - check_purge(Pre), - check_purge(Post); - -check_instruction(_, {apply, {Module, Function, Args}}, - _AllInstr, Modules) - when is_atom(Module), is_atom(Function), is_list(Args) -> - d("check_instruction -> entry when apply instruction with" - "~n Module: ~p" - "~n Function: ~p" - "~n Args: ~p", [Module, Function, Args]), - check_module(Module, Modules), - check_apply(Module,Function,Args); - -check_instruction(_, Instr, _AllInstr, _Modules) -> - d("check_instruction -> entry when unknown instruction with" - "~n Instr: ~p", [Instr]), - error({error, {unknown_instruction, Instr}}). - - -%% If Module X depends on Module Y, then module Y must have an update -%% instruction of some sort (otherwise the depend is faulty). -updated_modules([], Modules) -> - d("update_modules -> entry when done with" - "~n Modules: ~p", [Modules]), - Modules; -updated_modules([Instr|Instrs], Modules) -> - d("update_modules -> entry with" - "~n Instr: ~p" - "~n Modules: ~p", [Instr,Modules]), - Module = instruction_module(Instr), - d("update_modules -> Module: ~p", [Module]), - updated_modules(Instrs, [Module|Modules]). - -instruction_module({add_module, Module}) -> - Module; -instruction_module({remove, {Module, _, _}}) -> - Module; -instruction_module({load_module, Module, _, _, _}) -> - Module; -instruction_module({update, Module, _, _, _, _}) -> - Module; -instruction_module({apply, {Module, _, _}}) -> - Module; -instruction_module(Instr) -> - d("instruction_module -> entry when unknown instruction with" - "~n Instr: ~p", [Instr]), - error({error, {unknown_instruction, Instr}}). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -check_version(V) when is_list(V) -> - ok; -check_version(V) -> - error({bad_version, V}). - - -check_module(M, Modules) when is_atom(M) -> - case lists:member(M,Modules) of - true -> - ok; - false -> - error({unknown_module, M, Modules}) - end; -check_module(M, _) -> - error({bad_module, M}). - -check_apply(Module,Function,Args) -> - case (catch Module:module_info()) of - Info when is_list(Info) -> - check_exported(Function,Args,Info); - {'EXIT',{undef,_}} -> - error({not_existing_module,Module}) - end. - -check_exported(Function,Args,Info) -> - case lists:keysearch(exports,1,Info) of - {value,{exports,FunList}} -> - case lists:keysearch(Function,1,FunList) of - {value,{_,Arity}} when Arity==length(Args) -> - ok; - _ -> - error({not_exported_function,Function,length(Args)}) - end; - _ -> - error({bad_export,Info}) - end. - -check_module_depend(M, [], _) when is_atom(M) -> - d("check_module_depend -> entry with" - "~n M: ~p", [M]), - ok; -check_module_depend(M, Deps, Modules) when is_atom(M), is_list(Deps) -> - d("check_module_depend -> entry with" - "~n M: ~p" - "~n Deps: ~p" - "~n Modules: ~p", [M, Deps, Modules]), - case [Dep || Dep <- Deps, lists:member(Dep, Modules) == false] of - [] -> - ok; - Unknown -> - error({unknown_depend_modules, Unknown}) - end; -check_module_depend(_M, D, _Modules) -> - d("check_module_depend -> entry when bad depend with" - "~n D: ~p", [D]), - error({bad_depend, D}). - - -check_no_remove_depends(_Module, []) -> - ok; -check_no_remove_depends(Module, [Instr|Instrs]) -> - check_no_remove_depend(Module, Instr), - check_no_remove_depends(Module, Instrs). - -check_no_remove_depend(Module, {load_module, Mod, _Pre, _Post, Depend}) -> - case lists:member(Module, Depend) of - true -> - error({removed_module_in_depend, load_module, Mod, Module}); - false -> - ok - end; -check_no_remove_depend(Module, {update, Mod, _Change, _Pre, _Post, Depend}) -> - case lists:member(Module, Depend) of - true -> - error({removed_module_in_depend, update, Mod, Module}); - false -> - ok - end; -check_no_remove_depend(_, _) -> - ok. - - -check_change(soft) -> - ok; -check_change({advanced, _Something}) -> - ok; -check_change(Change) -> - error({bad_change, Change}). - - -check_purge(soft_purge) -> - ok; -check_purge(brutal_purge) -> - ok; -check_purge(Purge) -> - error({bad_purge, Purge}). - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -error(Reason) -> - throw({error, Reason}). - -fail(Reason) -> - exit({suite_failed, Reason}). - -key1search(Key, L) -> - case lists:keysearch(Key, 1, L) of - undefined -> - fail({not_found, Key, L}); - {value, {Key, Value}} -> - Value - end. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -d(F, A) -> - d(false, F, A). - -d(true, F, A) -> - io:format(F ++ "~n", A); -d(_, _, _) -> - ok. - - + ok = ?t:appup_test(asn1). diff --git a/lib/asn1/test/error_SUITE.erl b/lib/asn1/test/error_SUITE.erl index 6451f81c01..930b44cea6 100644 --- a/lib/asn1/test/error_SUITE.erl +++ b/lib/asn1/test/error_SUITE.erl @@ -19,7 +19,7 @@ -module(error_SUITE). -export([suite/0,all/0,groups/0, - already_defined/1,enumerated/1,objects/1]). + already_defined/1,enumerated/1,objects/1,values/1]). -include_lib("test_server/include/test_server.hrl"). @@ -29,9 +29,11 @@ all() -> [{group,p}]. groups() -> - [{p,parallel(),[already_defined, - enumerated, - objects]}]. + [{p,parallel(), + [already_defined, + enumerated, + objects, + values]}]. parallel() -> case erlang:system_info(schedulers) > 1 of @@ -138,6 +140,25 @@ objects(Config) -> } = run(P, Config), ok. +values(Config) -> + M = 'Values', + P = {M, + <<"Values DEFINITIONS AUTOMATIC TAGS ::= BEGIN\n" + " os1 OCTET STRING ::= \"abc\"\n" + " os2 OCTET STRING ::= 42\n" + " os3 OCTET STRING ::= { 1, 3 }\n" + "END\n">>}, + {error, + [ + {structured_error,{M,2},asn1ct_check, + illegal_octet_string_value}, + {structured_error,{M,3},asn1ct_check, + illegal_octet_string_value}, + {structured_error,{M,4},asn1ct_check, + illegal_octet_string_value} + ] + } = run(P, Config), + ok. run({Mod,Spec}, Config) -> diff --git a/lib/asn1/test/testEnumExt.erl b/lib/asn1/test/testEnumExt.erl index c66adaf949..878518be11 100644 --- a/lib/asn1/test/testEnumExt.erl +++ b/lib/asn1/test/testEnumExt.erl @@ -59,6 +59,10 @@ main(ber) -> common(ber). common(Erule) -> + roundtrip('SubExt1', blue), + roundtrip('SubExt1', orange), + roundtrip('SubExt1', black), + roundtrip('Seq', {'Seq',blue,42}), roundtrip('Seq', {'Seq',red,42}), roundtrip('Seq', {'Seq',green,42}), diff --git a/lib/asn1/test/testPrimStrings.erl b/lib/asn1/test/testPrimStrings.erl index 3262d61a4d..155d6f6ff5 100644 --- a/lib/asn1/test/testPrimStrings.erl +++ b/lib/asn1/test/testPrimStrings.erl @@ -18,6 +18,8 @@ %% %% -module(testPrimStrings). +-compile([{nowarn_deprecated_function,{asn1rt,utf8_list_to_binary,1}}, + {nowarn_deprecated_function,{asn1rt,utf8_binary_to_list,1}}]). -export([bit_string/2]). -export([octet_string/1]). |