%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 2001-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/.
%%
%% 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%
%%
%% Purpose: Test suite for the ASN.1 application
-module(asn1_SUITE).
-define(only_ber(Func),
if Rule =:= ber -> Func;
true -> ok
end).
-compile(export_all).
-include_lib("test_server/include/test_server.hrl").
%%------------------------------------------------------------------------------
%% Suite definition
%%------------------------------------------------------------------------------
suite() -> [{ct_hooks, [ts_install_cth]}].
all() ->
[{group, compile},
{group, parallel},
{group, app_test},
{group, appup_test},
% TODO: Investigate parallel running of these:
testComment,
testName2Number,
ticket_7407,
ticket7904,
{group, performance}].
groups() ->
[{compile, parallel([]),
[c_syntax,
c_string,
c_implicit_before_choice,
constraint_equivalence]},
{ber, parallel([]),
[ber_choiceinseq,
% Uses 'SOpttest'
ber_optional]},
{app_test, [], [{asn1_app_test, all}]},
{appup_test, [], [{asn1_appup_test, all}]},
{parallel, parallel([]),
[cover,
{group, ber},
% Uses 'P-Record', 'Constraints', 'MEDIA-GATEWAY-CONTROL'...
{group, [], [parse,
test_driver_load,
test_undecoded_rest,
specialized_decodes,
special_decode_performance,
testMegaco,
testConstraints,
testCompactBitString]},
default,
% Uses 'Def', 'MULTIMEDIA-SYSTEM-CONTROL', 'H323-MESSAGES', 'Prim',
% 'Real'
{group, [], [testPrim,
rtUI,
testPrimStrings,
testInvokeMod,
per,
ber_other,
der,
h323test,
per_GeneralString]},
testChoPrim,
testChoExtension,
testChoOptional,
testChoOptionalImplicitTag,
testChoRecursive,
testChoTypeRefCho,
testChoTypeRefPrim,
testChoTypeRefSeq,
testChoTypeRefSet,
testMultipleLevels,
testDef,
testOpt,
testSeqDefault,
% Uses 'External'
{group, [], [testChoExternal,
testPrimExternal,
testSeqExtension,
testSeqExternal,
testSeqOfExternal,
testSeqOfTag,
testSeqTag,
testSetExtension,
testSetExternal,
testSetOfExternal,
testSetOfTag,
testSetTag]},
testSeqOptional,
testSeqPrim,
testSeqTypeRefCho,
% Uses 'SeqTypeRefPrim'
{group, [], [testSeqTypeRefPrim,
testTypeValueNotation]},
testSeqTypeRefSeq,
testSeqTypeRefSet,
% Uses 'SeqOf'
{group, [], [testSeqOf,
testSeqOfIndefinite]}, % Uses 'Mvrasn*'
testSeqOfCho,
testSetDefault,
testExtensionAdditionGroup,
testSetOptional,
testSetPrim,
testSetTypeRefCho,
testSetTypeRefPrim,
testSetTypeRefSeq,
testSetTypeRefSet,
testSetOf,
testSetOfCho,
testEnumExt,
value_test,
value_bad_enum_test,
testSeq2738,
% Uses 'Constructed'
{group, [], [constructed,
ber_decode_error]},
% Uses 'SeqSetIndefinite'
{group, [], [testSeqIndefinite,
testSetIndefinite]},
testChoiceIndefinite,
per_open_type,
testInfObjectClass,
testParameterizedInfObj,
testMergeCompile,
testobj,
testDeepTConstr,
testExport,
testImport,
% Uses 'ParamBasic'
{group, [], [testParamBasic,
testDER]},
testMvrasn6,
testContextSwitchingTypes,
testOpenTypeImplicitTag,
duplicate_tags,
testROSE,
testINSTANCE_OF,
testTCAP,
test_ParamTypeInfObj,
test_Defed_ObjectIdentifier,
testSelectionType,
testSSLspecs,
testNortel,
% Uses 'PKCS7', 'InformationFramework'
{group, [], [test_WS_ParamClass,
test_modified_x420,
testX420]},
testTcapsystem,
testNBAPsystem,
test_compile_options,
testDoubleEllipses,
test_x691,
ticket_6143,
test_OTP_9688]},
{performance, [],
[testTimer_ber,
testTimer_per,
testTimer_uper,
smp]}].
parallel(Options) ->
case erlang:system_info(smp_support) andalso
erlang:system_info(schedulers) > 1 of
true -> [parallel|Options];
false -> Options
end.
%%------------------------------------------------------------------------------
%% Init/end
%%------------------------------------------------------------------------------
init_per_suite(Config) ->
Config.
end_per_suite(_Config) ->
ok.
init_per_group(_GroupName, Config) ->
Config.
end_per_group(_GroupName, Config) ->
Config.
init_per_testcase(Func, Config) ->
CaseDir = filename:join(?config(priv_dir, Config), Func),
ok = filelib:ensure_dir(filename:join([CaseDir, dummy_file])),
true = code:add_patha(CaseDir),
Dog = case Func of
testX420 -> ct:timetrap({minutes, 90});
_ -> ct:timetrap({minutes, 60})
end,
[{case_dir, CaseDir}, {watchdog, Dog}|Config].
end_per_testcase(_Func, Config) ->
code:del_path(?config(case_dir, Config)).
%%------------------------------------------------------------------------------
%% Test runners
%%------------------------------------------------------------------------------
test(Config, TestF) ->
test(Config, TestF, [per,
uper,
ber]).
test(Config, TestF, Rules) ->
Fun = fun(C, R, O) ->
M = element(2, erlang:fun_info(TestF, module)),
F = element(2, erlang:fun_info(TestF, name)),
io:format("Running ~p:~p with ~p...~n", [M, F, {R, O}]),
try
TestF(C, R, O)
catch
Class:Reason ->
NewReason = {Reason, [{rule, R}, {options, O}]},
erlang:raise(Class, NewReason,
erlang:get_stacktrace())
end
end,
Result = [run_case(Config, Fun, rule(Rule), opts(Rule)) || Rule <- Rules],
case lists:usort(Result) of
[true|_Skips] -> true; % At least one test ran
Skips -> {skip, [R || {skip, R} <- Skips]} % All skipped
end.
rule(A) when is_atom(A) -> A;
rule({A, _Opts} ) -> A.
opts(Rule) when is_atom(Rule) -> [];
opts({_Rule, Opts}) -> Opts.
run_case(Config, Fun, Rule, Opts) ->
CaseDir = ?config(case_dir, Config),
Dir = filename:join([CaseDir, join(Rule, Opts)]),
ok = filelib:ensure_dir(filename:join([Dir, dummy_file])),
replace_path(CaseDir, Dir),
NewConfig = lists:keyreplace(case_dir, 1, Config, {case_dir, Dir}),
% Run the actual test function
Result = Fun(NewConfig, Rule, Opts),
replace_path(Dir, CaseDir),
case Result of
{skip, _Reason} -> Result;
_ -> true
end.
replace_path(PathA, PathB) ->
true = code:del_path(PathA),
true = code:add_patha(PathB).
join(Rule, Opts) ->
string:join([atom_to_list(Rule)|lists:map(fun atom_to_list/1, Opts)], "_").
case_dir([], _Dir) ->
exit(no_case_dir);
case_dir([{case_dir, _}|Config], Dir) ->
[{case_dir, Dir}|Config];
case_dir([C|Config], Opt) ->
[C|case_dir(Config, Opt)].
%%------------------------------------------------------------------------------
%% Test cases
%%------------------------------------------------------------------------------
%% Cover run-time functions that are only called by the ASN.1 compiler
%% (if any).
cover(_) ->
Wc = filename:join([code:lib_dir(asn1),"ebin","asn1ct_eval_*.beam"]),
Beams = filelib:wildcard(Wc),
true = Beams =/= [],
[begin
M0 = filename:basename(Beam),
M1 = filename:rootname(M0),
M = list_to_atom(M1),
"asn1ct_eval_" ++ Group0 = M1,
Group = list_to_atom(Group0),
io:format("%%\n"
"%% ~s\n"
"%%\n", [M]),
asn1ct_func:start_link(),
[asn1ct_func:need({Group,F,A}) ||
{F,A} <- M:module_info(exports), F =/= module_info],
asn1ct_func:generate(group_leader())
end || Beam <- Beams],
ok.
testPrim(Config) -> test(Config, fun testPrim/3).
testPrim(Config, Rule, Opts) ->
asn1_test_lib:compile_all(["Prim", "Real"], Config, [Rule|Opts]),
testPrim:bool(Rule),
testPrim:int(Rule),
testPrim:enum(Rule),
testPrim:obj_id(Rule),
testPrim:rel_oid(Rule),
testPrim:null(Rule),
testPrim:real(Rule).
testCompactBitString(Config) -> test(Config, fun testCompactBitString/3).
testCompactBitString(Config, Rule, Opts) ->
asn1_test_lib:compile("PrimStrings", Config,
[Rule, compact_bit_string|Opts]),
testCompactBitString:compact_bit_string(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) ->
asn1_test_lib:compile_all(["PrimStrings", "BitStr"], Config, [Rule|Opts]),
testPrimStrings_cases(Rule),
asn1_test_lib:compile_all(["PrimStrings", "BitStr"], Config,
[legacy_bit_string,Rule|Opts]),
testPrimStrings:bit_string(Rule),
asn1_test_lib:compile_all(["PrimStrings", "BitStr"], Config,
[compact_bit_string,Rule|Opts]),
testPrimStrings:bit_string(Rule),
testPrimStrings:more_strings(Rule).
testPrimStrings_cases(Rule) ->
testPrimStrings:bit_string(Rule),
testPrimStrings:octet_string(Rule),
testPrimStrings:numeric_string(Rule),
testPrimStrings:other_strings(Rule),
testPrimStrings:universal_string(Rule),
testPrimStrings:bmp_string(Rule),
testPrimStrings:times(Rule),
testPrimStrings:utf8_string(Rule).
testPrimExternal(Config) -> test(Config, fun testPrimExternal/3).
testPrimExternal(Config, Rule, Opts) ->
asn1_test_lib:compile_all(["External", "PrimExternal"], Config,
[Rule|Opts]),
testPrimExternal:external(Rule),
asn1_test_lib:compile_all(["PrimStrings", "BitStr"], Config,
[Rule|Opts]),
testPrimStrings_cases(Rule),
testPrimStrings:more_strings(Rule).
testChoPrim(Config) -> test(Config, fun testChoPrim/3).
testChoPrim(Config, Rule, Opts) ->
asn1_test_lib:compile("ChoPrim", Config, [Rule|Opts]),
testChoPrim:bool(Rule),
testChoPrim:int(Rule).
testChoExtension(Config) -> test(Config, fun testChoExtension/3).
testChoExtension(Config, Rule, Opts) ->
asn1_test_lib:compile("ChoExtension", Config, [Rule|Opts]),
testChoExtension:extension(Rule).
testChoExternal(Config) -> test(Config, fun testChoExternal/3).
testChoExternal(Config, Rule, Opts) ->
asn1_test_lib:compile_all(["External", "ChoExternal"], Config, [Rule|Opts]),
testChoExternal:external(Rule).
testChoOptional(Config) -> test(Config, fun testChoOptional/3).
testChoOptional(Config, Rule, Opts) ->
asn1_test_lib:compile("ChoOptional", Config, [Rule|Opts]),
testChoOptional:optional(Rule).
testChoOptionalImplicitTag(Config) ->
test(Config, fun testChoOptionalImplicitTag/3,
[ber]).
testChoOptionalImplicitTag(Config, Rule, Opts) ->
%% Only meaningful for ber & co
asn1_test_lib:compile("ChoOptionalImplicitTag", Config, [Rule|Opts]),
testChoOptionalImplicitTag:optional(Rule).
testChoRecursive(Config) -> test(Config, fun testChoRecursive/3).
testChoRecursive(Config, Rule, Opts) ->
asn1_test_lib:compile("ChoRecursive", Config, [Rule|Opts]),
testChoRecursive:recursive(Rule).
testChoTypeRefCho(Config) -> test(Config, fun testChoTypeRefCho/3).
testChoTypeRefCho(Config, Rule, Opts) ->
asn1_test_lib:compile("ChoTypeRefCho", Config, [Rule|Opts]),
testChoTypeRefCho:choice(Rule).
testChoTypeRefPrim(Config) -> test(Config, fun testChoTypeRefPrim/3).
testChoTypeRefPrim(Config, Rule, Opts) ->
asn1_test_lib:compile("ChoTypeRefPrim", Config, [Rule|Opts]),
testChoTypeRefPrim:prim(Rule).
testChoTypeRefSeq(Config) -> test(Config, fun testChoTypeRefSeq/3).
testChoTypeRefSeq(Config, Rule, Opts) ->
asn1_test_lib:compile("ChoTypeRefSeq", Config, [Rule|Opts]),
testChoTypeRefSeq:seq(Rule).
testChoTypeRefSet(Config) -> test(Config, fun testChoTypeRefSet/3).
testChoTypeRefSet(Config, Rule, Opts) ->
asn1_test_lib:compile("ChoTypeRefSet", Config, [Rule|Opts]),
testChoTypeRefSet:set(Rule).
testMultipleLevels(Config) -> test(Config, fun testMultipleLevels/3).
testMultipleLevels(Config, Rule, Opts) ->
asn1_test_lib:compile("MultipleLevels", Config, [Rule|Opts]),
testMultipleLevels:main(Rule).
testDef(Config) -> test(Config, fun testDef/3).
testDef(Config, Rule, Opts) ->
asn1_test_lib:compile("Def", Config, [Rule|Opts]),
testDef:main(Rule).
testOpt(Config) -> test(Config, fun testOpt/3).
testOpt(Config, Rule, Opts) ->
asn1_test_lib:compile("Opt", Config, [Rule|Opts]),
testOpt:main(Rule).
testEnumExt(Config) -> test(Config, fun testEnumExt/3).
testEnumExt(Config, Rule, Opts) ->
asn1_test_lib:compile("EnumExt", Config, [Rule|Opts]),
testEnumExt:main(Rule).
%% Test of OTP-2523 ENUMERATED with extensionmark.
testSeqDefault(Config) -> test(Config, fun testSeqDefault/3).
testSeqDefault(Config, Rule, Opts) ->
asn1_test_lib:compile("SeqDefault", Config, [Rule|Opts]),
testSeqDefault:main(Rule).
testSeqExtension(Config) -> test(Config, fun testSeqExtension/3).
testSeqExtension(Config, Rule, Opts) ->
asn1_test_lib:compile_all(["External", "SeqExtension"], Config,
[Rule|Opts]),
DataDir = ?config(data_dir, Config),
testSeqExtension:main(DataDir, [Rule|Opts]).
testSeqExternal(Config) -> test(Config, fun testSeqExternal/3).
testSeqExternal(Config, Rule, Opts) ->
asn1_test_lib:compile_all(["External", "SeqExternal"], Config, [Rule|Opts]),
testSeqExternal:main(Rule).
testSeqOptional(Config) -> test(Config, fun testSeqOptional/3).
testSeqOptional(Config, Rule, Opts) ->
asn1_test_lib:compile("SeqOptional", Config, [Rule|Opts]),
testSeqOptional:main(Rule).
testSeqPrim(Config) -> test(Config, fun testSeqPrim/3).
testSeqPrim(Config, Rule, Opts) ->
asn1_test_lib:compile("SeqPrim", Config, [Rule|Opts]),
testSeqPrim:main(Rule).
%% Test of OTP-2738 Detect corrupt optional component.
testSeq2738(Config) -> test(Config, fun testSeq2738/3).
testSeq2738(Config, Rule, Opts) ->
asn1_test_lib:compile("Seq2738", Config, [Rule|Opts]),
testSeq2738:main(Rule).
testSeqTag(Config) -> test(Config, fun testSeqTag/3).
testSeqTag(Config, Rule, Opts) ->
asn1_test_lib:compile_all(["External", "SeqTag"], Config, [Rule|Opts]),
testSeqTag:main(Rule).
testSeqTypeRefCho(Config) -> test(Config, fun testSeqTypeRefCho/3).
testSeqTypeRefCho(Config, Rule, Opts) ->
asn1_test_lib:compile("SeqTypeRefCho", Config, [Rule|Opts]),
testSeqTypeRefCho:main(Rule).
testSeqTypeRefPrim(Config) -> test(Config, fun testSeqTypeRefPrim/3).
testSeqTypeRefPrim(Config, Rule, Opts) ->
asn1_test_lib:compile("SeqTypeRefPrim", Config, [Rule|Opts]),
testSeqTypeRefPrim:main(Rule).
testSeqTypeRefSeq(Config) -> test(Config, fun testSeqTypeRefSeq/3).
testSeqTypeRefSeq(Config, Rule, Opts) ->
asn1_test_lib:compile("SeqTypeRefSeq", Config, [Rule|Opts]),
testSeqTypeRefSeq:main(Rule).
testSeqTypeRefSet(Config) -> test(Config, fun testSeqTypeRefSet/3).
testSeqTypeRefSet(Config, Rule, Opts) ->
asn1_test_lib:compile("SeqTypeRefSet", Config, [Rule|Opts]),
testSeqTypeRefSet:main(Rule).
testSeqOf(Config) -> test(Config, fun testSeqOf/3).
testSeqOf(Config, Rule, Opts) ->
asn1_test_lib:compile_all(["SeqOf", "SeqOfEnum", "XSeqOf"], Config,
[Rule|Opts]),
testSeqOf:main(Rule).
testSeqOfCho(Config) -> test(Config, fun testSeqOfCho/3).
testSeqOfCho(Config, Rule, Opts) ->
asn1_test_lib:compile("SeqOfCho", Config, [Rule|Opts]),
testSeqOfCho:main(Rule).
testSeqOfIndefinite(Config) ->
test(Config, fun testSeqOfIndefinite/3, [ber]).
testSeqOfIndefinite(Config, Rule, Opts) ->
Files = ["Mvrasn-Constants-1", "Mvrasn-DataTypes-1", "Mvrasn-21-4",
"Mvrasn-20-4", "Mvrasn-19-4", "Mvrasn-18-4", "Mvrasn-17-4",
"Mvrasn-15-4", "Mvrasn-14-4", "Mvrasn-11-4", "SeqOf"],
asn1_test_lib:compile_all(Files, Config, [Rule|Opts]),
testSeqOfIndefinite:main().
testSeqOfExternal(Config) -> test(Config, fun testSeqOfExternal/3).
testSeqOfExternal(Config, Rule, Opts) ->
asn1_test_lib:compile_all(["External", "SeqOfExternal"], Config,
[Rule|Opts]),
testSeqOfExternal:main(Rule).
testSeqOfTag(Config) -> test(Config, fun testSeqOfTag/3).
testSeqOfTag(Config, Rule, Opts) ->
asn1_test_lib:compile_all(["External", "SeqOfTag"], Config, [Rule|Opts]),
testSeqOfTag:main(Rule).
testSetDefault(Config) -> test(Config, fun testSetDefault/3).
testSetDefault(Config, Rule, Opts) ->
asn1_test_lib:compile("SetDefault", Config, [Rule|Opts]),
testSetDefault:main(Rule).
testParamBasic(Config) -> test(Config, fun testParamBasic/3).
testParamBasic(Config, Rule, Opts) ->
asn1_test_lib:compile("ParamBasic", Config, [Rule|Opts]),
testParamBasic:main(Rule).
testSetExtension(Config) -> test(Config, fun testSetExtension/3).
testSetExtension(Config, Rule, Opts) ->
asn1_test_lib:compile_all(["External", "SetExtension"], Config,
[Rule|Opts]),
testSetExtension:main(Rule).
testSetExternal(Config) -> test(Config, fun testSetExternal/3).
testSetExternal(Config, Rule, Opts) ->
asn1_test_lib:compile_all(["External", "SetExternal"], Config, [Rule|Opts]),
testSetExternal:main(Rule).
testSetOptional(Config) -> test(Config, fun testSetOptional/3).
testSetOptional(Config, Rule, Opts) ->
asn1_test_lib:compile("SetOptional", Config, [Rule|Opts]),
testSetOptional:ticket_7533(Rule),
testSetOptional:main(Rule).
testSetPrim(Config) -> test(Config, fun testSetPrim/3).
testSetPrim(Config, Rule, Opts) ->
asn1_test_lib:compile("SetPrim", Config, [Rule|Opts]),
testSetPrim:main(Rule).
testSetTag(Config) -> test(Config, fun testSetTag/3).
testSetTag(Config, Rule, Opts) ->
asn1_test_lib:compile_all(["External", "SetTag"], Config, [Rule|Opts]),
testSetTag:main(Rule).
testSetTypeRefCho(Config) -> test(Config, fun testSetTypeRefCho/3).
testSetTypeRefCho(Config, Rule, Opts) ->
asn1_test_lib:compile("SetTypeRefCho", Config, [Rule|Opts]),
testSetTypeRefCho:main(Rule).
testSetTypeRefPrim(Config) -> test(Config, fun testSetTypeRefPrim/3).
testSetTypeRefPrim(Config, Rule, Opts) ->
asn1_test_lib:compile("SetTypeRefPrim", Config, [Rule|Opts]),
testSetTypeRefPrim:main(Rule).
testSetTypeRefSeq(Config) -> test(Config, fun testSetTypeRefSeq/3).
testSetTypeRefSeq(Config, Rule, Opts) ->
asn1_test_lib:compile("SetTypeRefSeq", Config, [Rule|Opts]),
testSetTypeRefSeq:main(Rule).
testSetTypeRefSet(Config) -> test(Config, fun testSetTypeRefSet/3).
testSetTypeRefSet(Config, Rule, Opts) ->
asn1_test_lib:compile("SetTypeRefSet", Config, [Rule|Opts]),
testSetTypeRefSet:main(Rule).
testSetOf(Config) -> test(Config, fun testSetOf/3).
testSetOf(Config, Rule, Opts) ->
asn1_test_lib:compile("SetOf", Config, [Rule|Opts]),
testSetOf:main(Rule).
testSetOfCho(Config) -> test(Config, fun testSetOfCho/3).
testSetOfCho(Config, Rule, Opts) ->
asn1_test_lib:compile("SetOfCho", Config, [Rule|Opts]),
testSetOfCho:main(Rule).
testSetOfExternal(Config) -> test(Config, fun testSetOfExternal/3).
testSetOfExternal(Config, Rule, Opts) ->
asn1_test_lib:compile_all(["External", "SetOfExternal"], Config,
[Rule|Opts]),
testSetOfExternal:main(Rule).
testSetOfTag(Config) -> test(Config, fun testSetOfTag/3).
testSetOfTag(Config, Rule, Opts) ->
asn1_test_lib:compile_all(["External", "SetOfTag"], Config, [Rule|Opts]),
testSetOfTag:main(Rule).
c_syntax(Config) ->
DataDir = ?config(data_dir, Config),
[{error, _} = asn1ct:compile(filename:join(DataDir, F))
|| F <-["Syntax",
"BadTypeEnding",
"BadValueAssignment1",
"BadValueAssignment2",
"BadValueSet",
"ChoiceBadExtension",
"EnumerationBadExtension",
"Example",
"Export1",
"MissingEnd",
"SequenceBadComma",
"SequenceBadComponentName",
"SequenceBadComponentType",
"SeqBadComma"]].
c_string(Config) ->
test(Config, fun c_string/3).
c_string(Config, Rule, Opts) ->
asn1_test_lib:compile("String", Config, [Rule|Opts]),
asn1ct:test('String').
c_implicit_before_choice(Config) ->
test(Config, fun c_implicit_before_choice/3, [ber]).
c_implicit_before_choice(Config, Rule, Opts) ->
DataDir = ?config(data_dir, Config),
CaseDir = ?config(case_dir, Config),
{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()].
per(Config) ->
test(Config, fun per/3, [per,uper]).
per(Config, Rule, Opts) ->
[module_test(M, Config, Rule, Opts) || M <- per_modules()].
ber_other(Config) ->
test(Config, fun ber_other/3, [ber]).
ber_other(Config, Rule, Opts) ->
[module_test(M, Config, Rule, Opts) || M <- ber_modules()].
der(Config) ->
asn1_test_lib:compile_all(ber_modules(), Config, [der]).
module_test(M, Config, Rule, Opts) ->
asn1_test_lib:compile(M, Config, [Rule|Opts]),
case asn1ct:test(list_to_atom(M), [{i, ?config(case_dir, Config)}]) of
ok -> ok;
Error ->
erlang:error({test_failed, M, Opts, Error})
end.
ber_choiceinseq(Config) ->
test(Config, fun ber_choiceinseq/3, [ber]).
ber_choiceinseq(Config, Rule, Opts) ->
asn1_test_lib:compile("ChoiceInSeq", Config, [Rule|Opts]).
ber_optional(Config) ->
test(Config, fun ber_optional/3, [ber]).
ber_optional(Config, Rule, Opts) ->
asn1_test_lib:compile("SOpttest", Config, [Rule|Opts]),
V = {'S', {'A', 10, asn1_NOVALUE, asn1_NOVALUE},
{'B', asn1_NOVALUE, asn1_NOVALUE, asn1_NOVALUE},
{'C', asn1_NOVALUE, 111, asn1_NOVALUE}},
{ok, B} = asn1_wrapper:encode('SOpttest', 'S', V),
Bytes = lists:flatten(B),
V2 = asn1_wrapper:decode('SOpttest', 'S', Bytes),
V = element(2, V2).
%% records used by test-case default
-record('Def1', {bool0,
bool1 = asn1_DEFAULT,
bool2 = asn1_DEFAULT,
bool3 = asn1_DEFAULT}).
default(Config) -> test(Config, fun default/3).
default(Config, Rule, Opts) ->
asn1_test_lib:compile("Def", Config, [Rule|Opts]),
{ok, Bytes1} = asn1_wrapper:encode('Def', 'Def1', #'Def1'{bool0 = true}),
{ok, {'Def1', true, false, false, false}} =
asn1_wrapper:decode('Def', 'Def1', lists:flatten(Bytes1)),
{ok, Bytes2} = asn1_wrapper:encode('Def', 'Def1', #'Def1'{bool0 = true,
bool2 = false}),
{ok, {'Def1', true, false, false, false}} =
asn1_wrapper:decode('Def', 'Def1', lists:flatten(Bytes2)).
value_test(Config) -> test(Config, fun value_test/3).
value_test(Config, Rule, Opts) ->
asn1_test_lib:compile("ObjIdValues", Config, [Rule|Opts]),
{ok, _} = asn1ct:test('ObjIdValues', 'ObjIdType',
'ObjIdValues':'mobileDomainId'()).
value_bad_enum_test(Config) ->
{error, _} = asn1ct:compile(?config(data_dir, Config) ++
"BadEnumValue1",
[{outdir, ?config(case_dir, Config)}]).
constructed(Config) ->
test(Config, fun constructed/3, [ber]).
constructed(Config, Rule, Opts) ->
asn1_test_lib:compile("Constructed", Config, [Rule|Opts]),
{ok, B} = asn1_wrapper:encode('Constructed', 'S', {'S', false}),
[40, 3, 1, 1, 0] = lists:flatten(B),
{ok, B1} = asn1_wrapper:encode('Constructed', 'S2', {'S2', false}),
[40, 5, 48, 3, 1, 1, 0] = lists:flatten(B1),
{ok, B2} = asn1_wrapper:encode('Constructed', 'I', 10),
[136, 1, 10] = lists:flatten(B2).
ber_decode_error(Config) ->
test(Config, fun ber_decode_error/3, [ber]).
ber_decode_error(Config, Rule, Opts) ->
asn1_test_lib:compile("Constructed", Config, [Rule|Opts]),
ber_decode_error:run(Opts).
h323test(Config) -> test(Config, fun h323test/3).
h323test(Config, Rule, Opts) ->
Files = ["H235-SECURITY-MESSAGES", "H323-MESSAGES",
"MULTIMEDIA-SYSTEM-CONTROL"],
asn1_test_lib:compile_all(Files, Config, [Rule|Opts]),
h323test:run(Rule).
per_GeneralString(Config) ->
test(Config, fun per_GeneralString/3, [per]).
per_GeneralString(Config, Rule, Opts) ->
asn1_test_lib:compile("MULTIMEDIA-SYSTEM-CONTROL", Config, [Rule|Opts]),
UI = [109, 64, 1, 57],
{ok, _V} = asn1_wrapper:decode('MULTIMEDIA-SYSTEM-CONTROL',
'MultimediaSystemControlMessage', UI).
per_open_type(Config) -> test(Config, fun per_open_type/3, [per]).
per_open_type(Config, Rule, Opts) ->
asn1_test_lib:compile("OpenType", Config, [Rule|Opts]),
{ok, _} = asn1ct:test('OpenType', 'Ot', {'Stype', 10, true}).
testConstraints(Config) -> test(Config, fun testConstraints/3).
testConstraints(Config, Rule, Opts) ->
asn1_test_lib:compile("Constraints", Config, [Rule|Opts]),
asn1_test_lib:compile("LargeConstraints", Config, [Rule|Opts]),
testConstraints:int_constraints(Rule).
testSeqIndefinite(Config) ->
test(Config, fun testSeqIndefinite/3, [ber]).
testSeqIndefinite(Config, Rule, Opts) ->
asn1_test_lib:compile("SeqSetIndefinite", Config, [Rule|Opts]),
testSeqIndefinite:main(Rule).
testSetIndefinite(Config) ->
test(Config, fun testSetIndefinite/3, [ber]).
testSetIndefinite(Config, Rule, Opts) ->
asn1_test_lib:compile("SeqSetIndefinite", Config, [Rule|Opts]),
testSetIndefinite:main(Rule).
testChoiceIndefinite(Config) ->
test(Config, fun testChoiceIndefinite/3, [ber]).
testChoiceIndefinite(Config, Rule, Opts) ->
asn1_test_lib:compile("ChoiceIndef", Config, [Rule|Opts]),
testChoiceIndefinite:main(Rule).
testInfObjectClass(Config) -> test(Config, fun testInfObjectClass/3).
testInfObjectClass(Config, Rule, Opts) ->
Files = ["ErrorClass", "InfClass"],
InfObjFiles = ["RANAPextract1", "InfObj", "MAP-ExtensionDataTypes",
"Objects", "INAPv2extract"],
RANAPFiles = ["RANAP-CommonDataTypes", "RANAP-Constants",
"RANAP-Containers", "RANAP-IEs", "RANAP-PDU-Contents",
"RANAP-PDU-Descriptions"],
asn1_test_lib:compile_all(Files ++ InfObjFiles ++ RANAPFiles, Config,
[Rule|Opts]),
testInfObjectClass:main(Rule),
testInfObj:main(Rule).
testParameterizedInfObj(Config) ->
test(Config, fun testParameterizedInfObj/3).
testParameterizedInfObj(Config, Rule, Opts) ->
asn1_test_lib:compile("Param", Config, [Rule|Opts]),
testParameterizedInfObj:main(Rule).
testMergeCompile(Config) -> test(Config, fun testMergeCompile/3).
testMergeCompile(Config, Rule, Opts) ->
Files = ["MS.set.asn", "RANAPSET.set.asn1", "Mvrasn4.set.asn",
"Mvrasn6.set.asn"],
asn1_test_lib:compile_all(Files, Config, [Rule|Opts]),
testMergeCompile:main(Rule),
testMergeCompile:mvrasn(Rule).
testobj(Config) -> test(Config, fun testobj/3).
testobj(Config, Rule, Opts) ->
asn1_test_lib:compile("RANAP", Config, [Rule|Opts]),
asn1_test_lib:compile_erlang("testobj", Config, []),
ok = testobj:run(),
ok = testParameterizedInfObj:ranap(Rule).
testDeepTConstr(Config) -> test(Config, fun testDeepTConstr/3).
testDeepTConstr(Config, Rule, Opts) ->
asn1_test_lib:compile_all(["TConstrChoice", "TConstr"], Config,
[Rule|Opts]),
testDeepTConstr:main(Rule).
testInvokeMod(Config) -> test(Config, fun testInvokeMod/3).
testInvokeMod(Config, Rule, Opts) ->
asn1_test_lib:compile("PrimStrings", Config, [Rule|Opts]),
{ok, _Result2} = 'PrimStrings':encode('Bs1', [1, 0, 1, 0]).
testExport(Config) ->
{error, {asn1, _Reason}} =
asn1ct:compile(filename:join(?config(data_dir, Config),
"IllegalExport"),
[{outdir, ?config(case_dir, Config)}]).
testImport(Config) ->
test(Config, fun testImport/3).
testImport(Config, Rule, Opts) ->
{error, _} = asn1ct:compile(filename:join(?config(data_dir, Config),
"ImportsFrom"),
[Rule, {outdir, ?config(priv_dir, Config)}
|Opts]).
testMegaco(Config) -> test(Config, fun testMegaco/3).
testMegaco(Config, Rule, Opts) ->
{ok, Module1, Module2} = testMegaco:compile(Config, Rule, Opts),
ok = testMegaco:main(Module1, Config),
ok = testMegaco:main(Module2, Config).
testMvrasn6(Config) -> test(Config, fun testMvrasn6/3).
testMvrasn6(Config, Rule, Opts) ->
asn1_test_lib:compile_all(["Mvrasn-21-4", "Mvrasn-20-6", "Mvrasn-19-6",
"Mvrasn-15-6", "Mvrasn-18-6", "Mvrasn-14-6",
"Mvrasn-11-6"], Config, [Rule|Opts]).
testContextSwitchingTypes(Config) ->
test(Config, fun testContextSwitchingTypes/3).
testContextSwitchingTypes(Config, Rule, Opts) ->
asn1_test_lib:compile("ContextSwitchingTypes", Config, [Rule|Opts]),
testContextSwitchingTypes:test(Config).
testTypeValueNotation(Config) -> test(Config, fun testTypeValueNotation/3).
testTypeValueNotation(Config, Rule, Opts) ->
asn1_test_lib:compile_all(["SeqTypeRefPrim", "ValueTest"], Config,
[Rule|Opts]),
testTypeValueNotation:main(Rule, Opts).
testOpenTypeImplicitTag(Config) ->
test(Config, fun testOpenTypeImplicitTag/3).
testOpenTypeImplicitTag(Config, Rule, Opts) ->
asn1_test_lib:compile("OpenTypeImplicitTag", Config, [Rule|Opts]),
testOpenTypeImplicitTag:main(Rule).
duplicate_tags(Config) ->
DataDir = ?config(data_dir, Config),
CaseDir = ?config(case_dir, Config),
{error, {asn1, [{error, {type, _, _, 'SeqOpt1Imp',
{asn1, {duplicates_of_the_tags, _}}}}]}} =
asn1ct:compile(filename:join(DataDir, "SeqOptional2"),
[abs, {outdir, CaseDir}]).
rtUI(Config) -> test(Config, fun rtUI/3).
rtUI(Config, Rule, Opts) ->
asn1_test_lib:compile("Prim", Config, [Rule|Opts]),
{ok, _} = asn1rt:info('Prim').
testROSE(Config) -> test(Config, fun testROSE/3).
testROSE(Config, Rule, Opts) ->
asn1_test_lib:compile("Remote-Operations-Merged.set.asn1", Config,
[Rule|Opts]).
testINSTANCE_OF(Config) -> test(Config, fun testINSTANCE_OF/3).
testINSTANCE_OF(Config, Rule, Opts) ->
asn1_test_lib:compile("INSTANCEOF.asn1", Config, [Rule|Opts]),
testINSTANCE_OF:main(Rule).
testTCAP(Config) ->
test(Config, fun testTCAP/3).
testTCAP(Config, Rule, Opts) ->
testTCAP:compile(Config, [Rule|Opts]),
testTCAP:test(Rule, Config),
case Rule of
ber ->
testTCAP:compile_asn1config(Config, [Rule, asn1config]),
testTCAP:test_asn1config();
_ -> ok
end.
testDER(Config) ->
test(Config, fun testDER/3, [ber]).
testDER(Config, Rule, Opts) ->
asn1_test_lib:compile("DERSpec", Config, [Rule, der|Opts]),
testDER:test(),
asn1_test_lib:compile("ParamBasic", Config, [Rule, der|Opts]),
testParamBasic:main(der),
asn1_test_lib:compile("Default", Config, [Rule, der|Opts]),
testSeqSetDefaultVal:main(Rule).
specialized_decodes(Config) ->
test(Config, fun specialized_decodes/3, [ber]).
specialized_decodes(Config, Rule, Opts) ->
asn1_test_lib:compile_all(["PartialDecSeq.asn",
"PartialDecSeq2.asn",
"PartialDecSeq3.asn",
"PartialDecMyHTTP.asn",
"MEDIA-GATEWAY-CONTROL.asn",
"P-Record"],
Config, [Rule, asn1config|Opts]),
test_partial_incomplete_decode:test(Config),
test_selective_decode:test().
special_decode_performance(Config) ->
test(Config, fun special_decode_performance/3, [ber]).
special_decode_performance(Config, Rule, Opts) ->
Files = ["MEDIA-GATEWAY-CONTROL", "PartialDecSeq"],
asn1_test_lib:compile_all(Files, Config, [Rule, asn1config|Opts]),
test_special_decode_performance:go(all).
test_driver_load(Config) ->
test(Config, fun test_driver_load/3, [per]).
test_driver_load(Config, Rule, Opts) ->
asn1_test_lib:compile("P-Record", Config, [Rule|Opts]),
test_driver_load:test(5).
test_ParamTypeInfObj(Config) ->
asn1_test_lib:compile("IN-CS-1-Datatypes", Config, [ber]).
test_WS_ParamClass(Config) -> test(Config, fun test_WS_ParamClass/3).
test_WS_ParamClass(Config, Rule, Opts) ->
asn1_test_lib:compile("InformationFramework", Config, [Rule|Opts]),
?only_ber(testWSParamClass:main(Rule)),
ok.
test_Defed_ObjectIdentifier(Config) ->
test(Config, fun test_Defed_ObjectIdentifier/3).
test_Defed_ObjectIdentifier(Config, Rule, Opts) ->
asn1_test_lib:compile("UsefulDefinitions", Config, [Rule|Opts]).
testSelectionType(Config) -> test(Config, fun testSelectionType/3).
testSelectionType(Config, Rule, Opts) ->
asn1_test_lib:compile("SelectionType", Config, [Rule|Opts]),
{ok, _} = testSelectionTypes:test().
testSSLspecs(Config) ->
test(Config, fun testSSLspecs/3, [ber]).
testSSLspecs(Config, Rule, Opts) ->
ok = testSSLspecs:compile(Config,
[Rule, compact_bit_string, der|Opts]),
testSSLspecs:run(Rule),
ok = testSSLspecs:compile_combined(Config, Rule),
ok = testSSLspecs:run_combined(Rule).
testNortel(Config) -> test(Config, fun testNortel/3).
testNortel(Config, Rule, Opts) ->
asn1_test_lib:compile("Nortel", Config, [Rule|Opts]).
test_undecoded_rest(Config) -> test(Config, fun test_undecoded_rest/3).
test_undecoded_rest(Config, Rule, Opts) ->
asn1_test_lib:compile("P-Record", Config, [Rule|Opts]),
ok = test_undecoded_rest:test([], Config),
asn1_test_lib:compile("P-Record", Config, [Rule,undec_rest|Opts]),
test_undecoded_rest:test(undec_rest, Config).
testTcapsystem(Config) ->
test(Config, fun testTcapsystem/3).
testTcapsystem(Config, Rule, Opts) ->
testTcapsystem:compile(Config, [Rule|Opts]).
testNBAPsystem(Config) -> test(Config, fun testNBAPsystem/3, [per]).
testNBAPsystem(Config, Rule, Opts) ->
testNBAPsystem:compile(Config, [Rule|Opts]),
testNBAPsystem:test(Rule, Config).
test_compile_options(Config) ->
ok = test_compile_options:wrong_path(Config),
ok = test_compile_options:path(Config),
ok = test_compile_options:noobj(Config),
ok = test_compile_options:record_name_prefix(Config),
ok = test_compile_options:verbose(Config),
ok = test_compile_options:warnings_as_errors(Config).
testDoubleEllipses(Config) -> test(Config, fun testDoubleEllipses/3).
testDoubleEllipses(Config, Rule, Opts) ->
asn1_test_lib:compile("DoubleEllipses", Config, [Rule|Opts]),
testDoubleEllipses:main(Rule).
test_modified_x420(Config) ->
test(Config, fun test_modified_x420/3, [ber]).
test_modified_x420(Config, Rule, Opts) ->
Files = [filename:join(modified_x420, F) || F <- ["PKCS7",
"InformationFramework",
"AuthenticationFramework"]],
asn1_test_lib:compile_all(Files, Config, [Rule,der|Opts]),
test_modified_x420:test(Config).
testX420() ->
[{timetrap,{minutes,90}}].
testX420(Config) ->
case erlang:system_info(system_architecture) of
"sparc-sun-solaris2.10" ->
{skip,"Too slow for an old Sparc"};
_ ->
test(Config, fun testX420/3, [ber])
end.
testX420(Config, Rule, Opts) ->
testX420:compile(Rule, [der|Opts], Config),
ok = testX420:ticket7759(Rule, Config),
testX420:compile(Rule, Opts, Config).
test_x691(Config) ->
test(Config, fun test_x691/3, [per, uper]).
test_x691(Config, Rule, Opts) ->
Files = ["P-RecordA1", "P-RecordA2", "P-RecordA3"],
asn1_test_lib:compile_all(Files, Config, [Rule|Opts]),
test_x691:cases(Rule, case Rule of
uper -> unaligned;
_ -> aligned
end),
asn1_test_lib:ticket_7708(Config, []),
asn1_test_lib:ticket_7763(Config).
ticket_6143(Config) ->
ok = test_compile_options:ticket_6143(Config).
testExtensionAdditionGroup(Config) ->
%% FIXME problems with automatic tags [ber_bin], [ber_bin, optimize]
test(Config, fun testExtensionAdditionGroup/3, [per, uper]).
testExtensionAdditionGroup(Config, Rule, Opts) ->
asn1_test_lib:compile("Extension-Addition-Group", Config, [Rule|Opts]),
asn1_test_lib:compile_erlang("extensionAdditionGroup", Config,
[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]).
% parse_modules() ->
% ["ImportsFrom"].
per_modules() ->
[X || X <- test_modules()].
ber_modules() ->
[X || X <- test_modules(),
X =/= "CommonDataTypes",
X =/= "DS-EquipmentUser-CommonFunctionOrig-TransmissionPath",
X =/= "H323-MESSAGES",
X =/= "H235-SECURITY-MESSAGES",
X =/= "MULTIMEDIA-SYSTEM-CONTROL"].
test_modules() ->
["BitStr",
"CAP",
"CommonDataTypes",
"Constraints",
"ContextSwitchingTypes",
"DS-EquipmentUser-CommonFunctionOrig-TransmissionPath",
"Enum",
"From",
"H235-SECURITY-MESSAGES",
"H323-MESSAGES",
"Import",
"Int",
"MAP-commonDataTypes",
"Null",
"NullTest",
"Octetstr",
"One",
"P-Record",
"P",
"Person",
"PrimStrings",
"Real",
"XSeq",
"XSeqOf",
"XSet",
"XSetOf",
"String",
"SwCDR",
"Time",
"SeqSetLib", % must be compiled before Seq and Set
"Seq",
"Set",
"SetOf",
"SeqOf",
"Prim",
"Cho",
"Def",
"Opt",
"ELDAPv3",
"LDAP"].
test_OTP_9688(Config) ->
PrivDir = ?config(case_dir, Config),
Data = "
OTP-9688 DEFINITIONS ::= BEGIN
foo INTEGER ::= 1
bar INTEGER ::= 42
Baz ::= INTEGER {x-y-z1(foo), x-y-z2(bar)}
Qux ::= SEQUENCE {flerpInfo SEQUENCE {x INTEGER (-10 | -9 | (0..4))} OPTIONAL}
END
",
File = filename:join(PrivDir, "OTP-9688.asn1"),
ok = file:write_file(File, Data),
%% Does it compile with changes to asn1ct_check and asn1ct_gen_per_rt2ct?
%% (see ticket)
ok = asn1ct:compile(File, [{outdir, PrivDir}]).
timer_compile(Config, Rule, Opts) ->
asn1_test_lib:compile_all(["H235-SECURITY-MESSAGES", "H323-MESSAGES"],
Config, [Rule|Opts]).
testTimer_ber(Config) ->
timer_compile(Config,ber,[]),
testTimer:go(Config,ber).
testTimer_per(Config) ->
timer_compile(Config,per,[]),
testTimer:go(Config,per).
testTimer_uper(Config) ->
timer_compile(Config,uper,[]),
{comment,_} = testTimer:go(Config,uper).
%% Test of multiple-line comment, OTP-8043
testComment(suite) -> [];
testComment(Config) ->
asn1_test_lib:compile("Comment", Config, []),
{ok,Enc} = asn1_wrapper:encode('Comment','Seq',{'Seq',12,true}),
{ok,{'Seq',12,true}} = asn1_wrapper:decode('Comment','Seq',Enc),
ok.
testName2Number(suite) -> [];
testName2Number(Config) ->
N2NOptions = [{n2n,Type} || Type <- ['CauseMisc', 'CauseProtocol',
'CauseRadioNetwork',
'CauseTransport','CauseNas']],
asn1_test_lib:compile("S1AP-IEs", Config, N2NOptions),
0 = 'S1AP-IEs':name2num_CauseMisc('control-processing-overload'),
'unknown-PLMN' = 'S1AP-IEs':num2name_CauseMisc(5),
%% OTP-10144
%% Test that n2n option generates name2num and num2name functions supporting
%% values not within the extension root if the enumeration type has an
%% extension marker.
N2NOptionsExt = [{n2n, 'NoExt'}, {n2n, 'Ext'}, {n2n, 'Ext2'}],
asn1_test_lib:compile("EnumN2N", Config, N2NOptionsExt),
%% Previously, name2num and num2name was not generated if the type didn't
%% have an extension marker:
0 = 'EnumN2N':name2num_NoExt('blue'),
2 = 'EnumN2N':name2num_NoExt('green'),
blue = 'EnumN2N':num2name_NoExt(0),
green = 'EnumN2N':num2name_NoExt(2),
%% Test enumeration extension:
7 = 'EnumN2N':name2num_Ext2('orange'),
orange = 'EnumN2N':num2name_Ext2(7),
%% 7 is not defined in Ext, only in Ext2.
{asn1_enum, 7} = 'EnumN2N':num2name_Ext(7),
7 = 'EnumN2N':name2num_Ext({asn1_enum, 7}),
42 = 'EnumN2N':name2num_Ext2({asn1_enum, 42}),
ok.
ticket_7407(Config) ->
asn1_test_lib:compile("EUTRA-extract-7407", Config, [uper]),
asn1_test_lib:ticket_7407_code(true),
asn1_test_lib:compile("EUTRA-extract-7407", Config,
[uper, no_final_padding]),
asn1_test_lib:ticket_7407_code(false).
smp(suite) -> [];
smp(Config) ->
case erlang:system_info(smp_support) of
true ->
NumOfProcs = erlang:system_info(schedulers),
io:format("smp starting ~p workers\n",[NumOfProcs]),
Msg = {initiatingMessage, testNBAPsystem:cell_setup_req_msg()},
ok = testNBAPsystem:compile(Config, [per]),
enc_dec(NumOfProcs,Msg,2),
N = 10000,
{Time1,ok} = timer:tc(?MODULE,enc_dec,[NumOfProcs,Msg, N]),
{Time1S,ok} = timer:tc(?MODULE,enc_dec,[1, Msg, NumOfProcs * N]),
ok = testNBAPsystem:compile(Config, [ber]),
{Time3,ok} = timer:tc(?MODULE,enc_dec,[NumOfProcs,Msg, N]),
{Time3S,ok} = timer:tc(?MODULE,enc_dec,[1, Msg, NumOfProcs * N]),
{comment,lists:flatten(
io_lib:format(
"Encode/decode time parallell with ~p cores: ~p [microsecs]~n"
"Encode/decode time sequential: ~p [microsecs]",
[NumOfProcs,Time1+Time3,Time1S+Time3S]))};
false ->
{skipped,"No smp support"}
end.
per_performance(Config) ->
PrivDir = proplists:get_value(priv_dir, Config),
NifDir = filename:join(PrivDir,"nif"),
ErlDir = filename:join(PrivDir,"erl"),
file:make_dir(NifDir),file:make_dir(ErlDir),
Msg = {initiatingMessage, testNBAPsystem:cell_setup_req_msg()},
ok = testNBAPsystem:compile([{priv_dir,NifDir}|Config], [per]),
ok = testNBAPsystem:compile([{priv_dir,ErlDir}|Config], [per]),
Modules = ['NBAP-CommonDataTypes',
'NBAP-Constants',
'NBAP-Containers',
'NBAP-IEs',
'NBAP-PDU-Contents',
'NBAP-PDU-Discriptions'],
PreNif = fun() ->
code:add_patha(NifDir),
lists:foreach(fun(M) ->
code:purge(M),
code:load_file(M)
end,Modules)
end,
PreErl = fun() ->
code:add_patha(ErlDir),
lists:foreach(fun(M) ->
code:purge(M),
code:load_file(M)
end,Modules)
end,
Func = fun() ->
element(1,timer:tc(
asn1_wrapper,encode,['NBAP-PDU-Discriptions',
'NBAP-PDU',
Msg]))
end,
nif_vs_erlang_performance({{{PreNif,Func},{PreErl,Func}},100000,32}).
ber_performance(Config) ->
Msg = {initiatingMessage, testNBAPsystem:cell_setup_req_msg()},
ok = testNBAPsystem:compile(Config, [ber]),
BerFun = fun() ->
{ok,B} = asn1_wrapper:encode('NBAP-PDU-Discriptions',
'NBAP-PDU', Msg),
asn1_wrapper:decode(
'NBAP-PDU-Discriptions',
'NBAP-PDU',
B)
end,
nif_vs_erlang_performance({BerFun,100000,32}).
cert_pem_performance(Config) when is_list(Config) ->
cert_pem_performance({100000, 32});
cert_pem_performance({N,S}) ->
nif_vs_erlang_performance({fun pem_performance:cert_pem/0,N,S}).
dsa_pem_performance(Config) when is_list(Config) ->
dsa_pem_performance({100000, 32});
dsa_pem_performance({N,S}) ->
nif_vs_erlang_performance({fun pem_performance:dsa_pem/0,N,S}).
nif_vs_erlang_performance({{TC1,TC2},N,Sched}) ->
random:seed({123,456,789}),
io:format("Running a ~p sample with ~p max procs...~n~n",[N,Sched]),
{True,False} = exec(TC1,TC2,Sched,N+1),
io:format("~ndone!~n"),
io:format("~n"),TStats = print_stats(strip(True,N div 20)),
io:format("~n"),FStats = print_stats(strip(False,N div 20)),
Str = io_lib:format("~nNifs are ~.3f% faster than erlang!~n",
[(element(2,FStats) - element(2,TStats)) /
element(2,FStats) * 100]),
io:format(Str),
{comment, lists:flatten(Str)};
nif_vs_erlang_performance({T,N,Sched}) ->
PTC1 = fun() ->
application:set_env(asn1, nif_loadable, true)
end,
PTC2 = fun() ->
application:set_env(asn1, nif_loadable, false)
end,
TC = fun() ->
element(1,timer:tc(T))
end,
nif_vs_erlang_performance({{{PTC1,TC},{PTC2,TC}},N,Sched}).
print_stats(Data) ->
Length = length(Data),
Mean = lists:sum(Data) / Length,
Variance = lists:foldl(fun(N,Acc) -> math:pow(N - Mean, 2)+Acc end, 0, Data),
StdDev = math:sqrt(Variance / Length),
Median = lists:nth(round(Length/2),Data),
Min = lists:min(Data),
Max = lists:max(Data),
if Length < 20 ->
io:format("Data: ~w~n",[Data]);
true ->
ok
end,
io:format("Length: ~p~nMean: ~p~nStdDev: ~p~nMedian: ~p~nMin: ~p~nMax: ~p~n",
[Length,Mean,StdDev,Median,Min,Max]),
{Length,Mean,StdDev,Median,Min,Max}.
collect(Acc) ->
receive
{Tag,Val} ->
Prev = proplists:get_value(Tag,Acc,[]),
collect(lists:keystore(Tag,1,Acc,{Tag,[Val|Prev]}))
after 100 ->
Acc
end.
exec(One,Two,Max,N) ->
exec(One,Two,Max,N,{[],[]}).
exec(_,_,_,1,{D1,D2}) ->
{lists:flatten(D1),lists:flatten(D2)};
exec({PreOne,One} = O,{PreTwo,Two} = T,MaxProcs, N, {D1,D2}) ->
Num = random:uniform(round(N/2)),
if Num rem 3 == 0 ->
timer:sleep(Num rem 1000);
true ->
ok
end,
Procs = random:uniform(MaxProcs),
io:format("\tBatch: ~p items in ~p processes, ~p left~n",[Num,Procs,N-Num]),
if Num rem 2 == 1 ->
erlang:garbage_collect(),
PreOne(),
MoreOne = pexec(One, Num, Procs, []),
erlang:garbage_collect(),
PreTwo(),
MoreTwo = pexec(Two, Num, Procs, []);
true ->
erlang:garbage_collect(),
PreTwo(),
MoreTwo = pexec(Two, Num, Procs, []),
erlang:garbage_collect(),
PreOne(),
MoreOne = pexec(One, Num, Procs, [])
end,
exec(O,T,MaxProcs,N-Num,{[MoreOne|D1],
[MoreTwo|D2]}).
pexec(_Fun, _, 0, []) ->
[];
pexec(Fun, _, 0, [{Ref,Pid}|Rest]) ->
receive
{data,D} ->
[D|pexec(Fun,0,0,[{Ref,Pid}|Rest])];
{'DOWN', Ref, process, Pid, normal} ->
pexec(Fun, 0,0,Rest)
end;
pexec(Fun, 0, 1, AccProcs) ->
pexec(Fun, 0, 0, AccProcs);
pexec(Fun, N, 1, AccProcs) ->
[Fun()|pexec(Fun, N - 1, 1, AccProcs)];
pexec(Fun, N, Procs, AccProcs) ->
S = self(),
Pid = spawn(fun() ->
S ! {data,pexec(Fun,N,1,[])}
end),
Ref = erlang:monitor(process, Pid),
pexec(Fun, N, Procs - 1, [{Ref,Pid}|AccProcs]).
strip(Data,Num) ->
{_,R} = lists:split(Num,lists:sort(Data)),
element(2,lists:split(Num,lists:reverse(R))).
faster(A,B) ->
(B - A)/B * 100.
enc_dec(1, Msg, N) ->
worker_loop(N, Msg);
enc_dec(NumOfProcs,Msg, N) ->
pforeach(fun(_) ->
worker_loop(N, Msg)
end, [I || I <- lists:seq(1,NumOfProcs)]).
worker_loop(0, _Msg) ->
ok;
worker_loop(N, Msg) ->
{ok,B}=asn1_wrapper:encode('NBAP-PDU-Discriptions',
'NBAP-PDU',
Msg),
{ok,_Msg}=asn1_wrapper:decode('NBAP-PDU-Discriptions',
'NBAP-PDU',
B),
worker_loop(N - 1, Msg).
pforeach(Fun, List) ->
pforeach(Fun, List, []).
pforeach(Fun, [], [{Pid,Ref}|Pids]) ->
receive
{'DOWN', Ref, process, Pid, normal} ->
pforeach(Fun, [], Pids)
end;
pforeach(Fun, [H|T], Pids) ->
Pid = spawn(fun() -> Fun(H) end),
Ref = erlang:monitor(process, Pid),
pforeach(Fun, T, [{Pid, Ref}|Pids]);
pforeach(_Fun,[],[]) ->
ok.
-record('InitiatingMessage',{procedureCode,criticality,value}).
-record('Iu-ReleaseCommand',{first,second}).
ticket7904(Config) ->
asn1_test_lib:compile("RANAPextract1", Config, [per]),
Val1 = #'InitiatingMessage'{procedureCode=1,
criticality=ignore,
value=#'Iu-ReleaseCommand'{
first=13,
second=true}},
{ok,_} = 'RANAPextract1':encode('InitiatingMessage', Val1),
{ok,_} = 'RANAPextract1':encode('InitiatingMessage', Val1).