aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/asn1/c_src/asn1_erl_nif.c5
-rw-r--r--lib/asn1/doc/src/notes.xml29
-rw-r--r--lib/asn1/test/asn1_SUITE.erl13
-rw-r--r--lib/asn1/test/testX420.erl2
-rw-r--r--lib/asn1/test/test_modified_x420.erl22
-rw-r--r--lib/compiler/src/beam_asm.erl2
-rw-r--r--lib/compiler/src/beam_disasm.erl7
-rw-r--r--lib/compiler/src/beam_receive.erl2
-rw-r--r--lib/compiler/src/beam_type.erl23
-rw-r--r--lib/compiler/src/beam_validator.erl14
-rw-r--r--lib/compiler/src/compile.erl6
-rw-r--r--lib/compiler/src/core_lint.erl2
-rw-r--r--lib/compiler/src/sys_core_fold.erl9
-rw-r--r--lib/compiler/test/Makefile1
-rw-r--r--lib/compiler/test/core_fold_SUITE.erl50
-rw-r--r--lib/compiler/test/unused_multiple_values_error.core11
-rw-r--r--lib/erl_interface/src/decode/decode_fun.c39
-rw-r--r--lib/erl_interface/src/decode/decode_pid.c10
-rw-r--r--lib/erl_interface/src/decode/decode_port.c10
-rw-r--r--lib/erl_interface/src/decode/decode_ref.c23
-rw-r--r--lib/erl_interface/src/decode/decode_skip.c3
-rw-r--r--lib/erl_interface/src/decode/decode_trace.c28
-rw-r--r--lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c33
-rw-r--r--lib/kernel/doc/src/specs.xml1
-rw-r--r--lib/kernel/src/inet6_tcp_dist.erl8
-rw-r--r--lib/kernel/src/inet_tcp_dist.erl8
-rw-r--r--lib/kernel/vsn.mk2
-rw-r--r--lib/odbc/src/odbc.erl4
-rw-r--r--lib/odbc/test/odbc_query_SUITE.erl67
-rw-r--r--lib/odbc/vsn.mk2
-rw-r--r--lib/sasl/src/sasl.appup.src16
-rw-r--r--lib/snmp/.gitignore4
-rw-r--r--lib/snmp/doc/src/notes.xml75
-rw-r--r--lib/snmp/src/app/snmp.appup.src8
-rw-r--r--lib/snmp/src/compile/snmpc.erl69
-rw-r--r--lib/snmp/src/compile/snmpc_lib.erl42
-rw-r--r--lib/snmp/src/compile/snmpc_mib_gram.yrl48
-rw-r--r--lib/snmp/test/snmp_compiler_test.erl55
-rw-r--r--lib/snmp/test/snmp_test_data/OTP10799-MIB.mib75
-rw-r--r--lib/snmp/test/snmp_test_data/OTP10808-MIB.mib137
-rw-r--r--lib/snmp/test/test-mibs/ALARM-MIB.mib1214
-rw-r--r--lib/snmp/test/test-mibs/RFC1271-MIB.mib3
-rw-r--r--lib/snmp/test/test-mibs/RMON2-MIB.mib2
-rw-r--r--lib/snmp/vsn.mk4
-rw-r--r--lib/stdlib/src/erl_lint.erl19
-rw-r--r--lib/stdlib/src/eval_bits.erl64
-rw-r--r--lib/stdlib/src/shell.erl4
-rw-r--r--lib/stdlib/test/erl_eval_SUITE.erl48
-rw-r--r--lib/stdlib/test/erl_lint_SUITE.erl112
-rw-r--r--lib/stdlib/vsn.mk2
-rw-r--r--lib/test_server/src/test_server.erl44
-rw-r--r--lib/test_server/src/test_server_ctrl.erl173
-rw-r--r--lib/test_server/src/test_server_gl.erl23
-rw-r--r--lib/test_server/src/test_server_h.erl2
-rw-r--r--lib/test_server/src/test_server_io.erl6
-rw-r--r--lib/test_server/src/test_server_node.erl12
-rw-r--r--lib/test_server/src/test_server_sup.erl14
-rw-r--r--lib/tools/src/cover.erl48
-rw-r--r--lib/tools/test/cover_SUITE.erl17
-rw-r--r--lib/tools/test/cover_SUITE_data/compile_beam/v.erl7
-rw-r--r--lib/tools/test/cover_SUITE_data/compile_beam/z.erl1
-rw-r--r--lib/tools/vsn.mk2
62 files changed, 2469 insertions, 317 deletions
diff --git a/lib/asn1/c_src/asn1_erl_nif.c b/lib/asn1/c_src/asn1_erl_nif.c
index e7e5f5f2f5..b3dd312fed 100644
--- a/lib/asn1/c_src/asn1_erl_nif.c
+++ b/lib/asn1/c_src/asn1_erl_nif.c
@@ -1130,8 +1130,8 @@ int ber_encode_length(size_t size, mem_chunk_t **curr, unsigned int *count) {
(*curr)->curr -= 1;
(*count)++;
} else {
- int chunks = size / 256 + 1;
- if (ber_check_memory(curr, chunks + 1))
+ int chunks = 0;
+ if (ber_check_memory(curr, 8))
return ASN1_ERROR;
while (size > 0)
@@ -1140,6 +1140,7 @@ int ber_encode_length(size_t size, mem_chunk_t **curr, unsigned int *count) {
size >>= 8;
(*curr)->curr -= 1;
(*count)++;
+ chunks++;
}
*(*curr)->curr = chunks | 0x80;
diff --git a/lib/asn1/doc/src/notes.xml b/lib/asn1/doc/src/notes.xml
index da0812f000..5e21b926a8 100644
--- a/lib/asn1/doc/src/notes.xml
+++ b/lib/asn1/doc/src/notes.xml
@@ -98,6 +98,35 @@
</section>
+<section><title>Asn1 1.8.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ ASN.1 decoders generated with the options <c>-bber_bin
+ +optimize +nif</c> would decode open types with a size
+ larger than 511 incorrectly. That bug could cause
+ decoding by <c>public_key</c> to fail. The bug was in the
+ NIF library <c>asn1_erl_nif.so</c>; therefore there is no
+ need re-compile ASN.1 specifications that had the
+ problem.</p>
+ <p>
+ Own Id: OTP-10805 Aux Id: seq12244 </p>
+ </item>
+ <item>
+ <p>
+ Encoding SEQUENCEs with multiple extension addition
+ groups with optional values could fail (depending both on
+ the specification and whether all values were provided).</p>
+ <p>
+ Own Id: OTP-10811 Aux Id: OTP-10664 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Asn1 1.8</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/asn1/test/asn1_SUITE.erl b/lib/asn1/test/asn1_SUITE.erl
index 644cba8c3c..be9b82cddf 100644
--- a/lib/asn1/test/asn1_SUITE.erl
+++ b/lib/asn1/test/asn1_SUITE.erl
@@ -1043,17 +1043,24 @@ testDoubleEllipses(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, [der]),
- test_modified_x420:test_io(Config).
+ asn1_test_lib:compile_all(Files, Config, [Rule,der|Opts]),
+ test_modified_x420:test(Config).
testX420() ->
[{timetrap,{minutes,90}}].
testX420(Config) ->
- test(Config, fun testX420/3, [ber]).
+ 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),
diff --git a/lib/asn1/test/testX420.erl b/lib/asn1/test/testX420.erl
index 52b20a2c70..045660a8e2 100644
--- a/lib/asn1/test/testX420.erl
+++ b/lib/asn1/test/testX420.erl
@@ -37,7 +37,7 @@ compile_loop(Erule, [Spec|Specs], Options, Config)
when Erule =:= ber; Erule =:= per ->
CaseDir = ?config(case_dir, Config),
asn1_test_lib:compile(filename:join([x420, Spec]), Config,
- [Erule, {i, CaseDir}]),
+ [Erule, {i, CaseDir} | Options]),
compile_loop(Erule, Specs, Options, Config);
compile_loop(_Erule, _Specs, _Options, _Config) ->
ok.
diff --git a/lib/asn1/test/test_modified_x420.erl b/lib/asn1/test/test_modified_x420.erl
index 2e9dfeee87..ae9d1989fb 100644
--- a/lib/asn1/test/test_modified_x420.erl
+++ b/lib/asn1/test/test_modified_x420.erl
@@ -18,27 +18,21 @@
%%
%%
-module(test_modified_x420).
-
-%-compile(export_all).
--export([test_io/1]).
+-export([test/1]).
-include_lib("test_server/include/test_server.hrl").
-test_io(Config) ->
- io:format("~p~n~n", [catch test(Config)]).
-
test(Config) ->
- ?line DataDir = ?config(data_dir,Config),
-% ?line OutDir = ?config(priv_dir,Config),
+ DataDir = ?config(data_dir,Config),
- ?line Der = read_pem(filename:join([DataDir,modified_x420,"p7_signed_data.pem"])),
- ?line {ok, {_,_,SignedData}} = 'PKCS7':decode('ContentInfo', Der),
- ?line {ok,_} = 'PKCS7':decode('SignedData', SignedData).
+ Der = read_pem(filename:join([DataDir,modified_x420,"p7_signed_data.pem"])),
+ {ok,{_,_,SignedData}} = asn1_wrapper:decode('PKCS7', 'ContentInfo', Der),
+ {ok,_} = asn1_wrapper:decode('PKCS7', 'SignedData', SignedData).
read_pem(File) ->
- ?line {ok, Bin} = file:read_file(File),
- ?line ssl_base64:join_decode(lists:flatten(extract_base64(Bin))).
-
+ {ok,Bin} = file:read_file(File),
+ Der = base64:mime_decode(lists:flatten(extract_base64(Bin))),
+ binary_to_list(Der).
extract_base64(Binary) ->
diff --git a/lib/compiler/src/beam_asm.erl b/lib/compiler/src/beam_asm.erl
index a7c8508321..98967e651f 100644
--- a/lib/compiler/src/beam_asm.erl
+++ b/lib/compiler/src/beam_asm.erl
@@ -387,7 +387,7 @@ encode_arg({list, List}, Dict0) ->
{L, Dict} = encode_list(List, Dict0, []),
{[encode(?tag_z, 1), encode(?tag_u, length(List))|L], Dict};
encode_arg({float, Float}, Dict) when is_float(Float) ->
- {[encode(?tag_z, 0),<<Float:64/float>>], Dict};
+ encode_arg({literal,Float}, Dict);
encode_arg({fr,Fr}, Dict) ->
{[encode(?tag_z, 2),encode(?tag_u, Fr)], Dict};
encode_arg({field_flags,Flags0}, Dict) ->
diff --git a/lib/compiler/src/beam_disasm.erl b/lib/compiler/src/beam_disasm.erl
index 62bdc74cc8..67d756c45c 100644
--- a/lib/compiler/src/beam_disasm.erl
+++ b/lib/compiler/src/beam_disasm.erl
@@ -512,7 +512,12 @@ decode_z_tagged(Tag,B,Bs,Literals) when (B band 16#08) =:= 0 ->
decode_alloc_list(Bs, Literals);
4 -> % literal
{{u,LitIndex},RestBs} = decode_arg(Bs),
- {{literal,gb_trees:get(LitIndex, Literals)},RestBs};
+ case gb_trees:get(LitIndex, Literals) of
+ Float when is_float(Float) ->
+ {{float,Float},RestBs};
+ Literal ->
+ {{literal,Literal},RestBs}
+ end;
_ ->
?exit({decode_z_tagged,{invalid_extended_tag,N}})
end;
diff --git a/lib/compiler/src/beam_receive.erl b/lib/compiler/src/beam_receive.erl
index 0bb527aeb9..3dd5ed182e 100644
--- a/lib/compiler/src/beam_receive.erl
+++ b/lib/compiler/src/beam_receive.erl
@@ -249,7 +249,7 @@ opt_ref_used(Is, RefReg, Fail, D) ->
Done = gb_sets:singleton(Fail),
Regs = regs_init_x0(),
try
- opt_ref_used_1(Is, RefReg, D, Done, Regs),
+ _ = opt_ref_used_1(Is, RefReg, D, Done, Regs),
true
catch
throw:not_used ->
diff --git a/lib/compiler/src/beam_type.erl b/lib/compiler/src/beam_type.erl
index 7392f99fb6..372923a5cf 100644
--- a/lib/compiler/src/beam_type.erl
+++ b/lib/compiler/src/beam_type.erl
@@ -142,9 +142,11 @@ simplify_float(Is0, Ts0) ->
throw:not_possible -> not_possible
end.
-simplify_float_1([{set,[D0],[A],{alloc,_,{gc_bif,'-',{f,0}}}}=I|Is]=Is0, Ts0, Rs0, Acc0) ->
- case tdb_find(A, Ts0) of
+simplify_float_1([{set,[D0],[A0],{alloc,_,{gc_bif,'-',{f,0}}}}=I|Is]=Is0,
+ Ts0, Rs0, Acc0) ->
+ case tdb_find(A0, Ts0) of
float ->
+ A = coerce_to_float(A0),
{Rs1,Acc1} = load_reg(A, Ts0, Rs0, Acc0),
{D,Rs} = find_dest(D0, Rs1),
Areg = fetch_reg(A, Rs),
@@ -156,13 +158,16 @@ simplify_float_1([{set,[D0],[A],{alloc,_,{gc_bif,'-',{f,0}}}}=I|Is]=Is0, Ts0, Rs
{Rs,Acc} = flush(Rs0, Is0, Acc0),
simplify_float_1(Is, Ts, Rs, [I|checkerror(Acc)])
end;
-simplify_float_1([{set,[D0],[A,B],{alloc,_,{gc_bif,Op0,{f,0}}}}=I|Is]=Is0, Ts0, Rs0, Acc0) ->
- case float_op(Op0, A, B, Ts0) of
+simplify_float_1([{set,[D0],[A0,B0],{alloc,_,{gc_bif,Op0,{f,0}}}}=I|Is]=Is0,
+ Ts0, Rs0, Acc0) ->
+ case float_op(Op0, A0, B0, Ts0) of
no ->
Ts = update(I, Ts0),
{Rs,Acc} = flush(Rs0, Is0, Acc0),
simplify_float_1(Is, Ts, Rs, [I|checkerror(Acc)]);
{yes,Op} ->
+ A = coerce_to_float(A0),
+ B = coerce_to_float(B0),
{Rs1,Acc1} = load_reg(A, Ts0, Rs0, Acc0),
{Rs2,Acc2} = load_reg(B, Ts0, Rs1, Acc1),
{D,Rs} = find_dest(D0, Rs2),
@@ -187,6 +192,16 @@ simplify_float_1([], Ts, Rs, Acc0) ->
Is = opt_fmoves(Is0, []),
{Is,Ts}.
+coerce_to_float({integer,I}=Int) ->
+ try float(I) of
+ F ->
+ {float,F}
+ catch _:_ ->
+ %% Let the overflow happen at run-time.
+ Int
+ end;
+coerce_to_float(Other) -> Other.
+
opt_fmoves([{set,[{x,_}=R],[{fr,_}]=Src,fmove}=I1,
{set,[_]=Dst,[{x,_}=R],move}=I2|Is], Acc) ->
case beam_utils:is_killed_block(R, Is) of
diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl
index 58aba0b9cc..eb72290306 100644
--- a/lib/compiler/src/beam_validator.erl
+++ b/lib/compiler/src/beam_validator.erl
@@ -649,7 +649,8 @@ valfun_4(send, Vst) ->
call(send, 2, Vst);
valfun_4({set_tuple_element,Src,Tuple,I}, Vst) ->
assert_term(Src, Vst),
- assert_type({tuple_element,I+1}, Tuple, Vst);
+ assert_type({tuple_element,I+1}, Tuple, Vst),
+ Vst;
%% Match instructions.
valfun_4({select_val,Src,{f,Fail},{list,Choices}}, Vst) ->
assert_term(Src, Vst),
@@ -1044,7 +1045,7 @@ float_op(Src, Dst, Vst0) ->
assert_fls(Fls, Vst) ->
case get_fls(Vst) of
- Fls -> Vst;
+ Fls -> ok;
OtherFls -> error({bad_floating_point_state,OtherFls})
end.
@@ -1120,7 +1121,7 @@ bsm_match_state(Slots) ->
{match_context,0,Slots}.
bsm_validate_context(Reg, Vst) ->
- bsm_get_context(Reg, Vst),
+ _ = bsm_get_context(Reg, Vst),
ok.
bsm_get_context({x,X}=Reg, #vst{current=#st{x=Xs}}=_Vst) when is_integer(X) ->
@@ -1133,7 +1134,7 @@ bsm_get_context(Reg, _) -> error({bad_source,Reg}).
bsm_save(Reg, {atom,start}, Vst) ->
%% Save point refering to where the match started.
%% It is always valid. But don't forget to validate the context register.
- bsm_get_context(Reg, Vst),
+ bsm_validate_context(Reg, Vst),
Vst;
bsm_save(Reg, SavePoint, Vst) ->
case bsm_get_context(Reg, Vst) of
@@ -1146,7 +1147,7 @@ bsm_save(Reg, SavePoint, Vst) ->
bsm_restore(Reg, {atom,start}, Vst) ->
%% (Mostly) automatic save point refering to where the match started.
%% It is always valid. But don't forget to validate the context register.
- bsm_get_context(Reg, Vst),
+ bsm_validate_context(Reg, Vst),
Vst;
bsm_restore(Reg, SavePoint, Vst) ->
case bsm_get_context(Reg, Vst) of
@@ -1312,8 +1313,7 @@ assert_term(Src, Vst) ->
%%
assert_type(WantedType, Term, Vst) ->
- assert_type(WantedType, get_term_type(Term, Vst)),
- Vst.
+ assert_type(WantedType, get_term_type(Term, Vst)).
assert_type(Correct, Correct) -> ok;
assert_type(float, {float,_}) -> ok;
diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl
index d2baf51edd..497af2b52c 100644
--- a/lib/compiler/src/compile.erl
+++ b/lib/compiler/src/compile.erl
@@ -683,7 +683,7 @@ binary_passes() ->
%% Remove the target file so we don't have an old one if the compilation fail.
remove_file(St) ->
- file:delete(St#compile.ofile),
+ _ = file:delete(St#compile.ofile),
{ok,St}.
-record(asm_module, {module,
@@ -1092,7 +1092,7 @@ makedep_output(#compile{code=Code,options=Opts,ofile=Ofile}=St) ->
io:fwrite(Output1, "~ts", [Code]),
%% Close the file if relevant.
if
- CloseOutput -> file:close(Output1);
+ CloseOutput -> ok = file:close(Output1);
true -> ok
end,
{ok,St}
@@ -1231,7 +1231,7 @@ encrypt(des3_cbc=Mode, {K1,K2,K3, IVec}, Bin0) ->
random_bytes(N) ->
{A,B,C} = now(),
- random:seed(A, B, C),
+ _ = random:seed(A, B, C),
random_bytes_1(N, []).
random_bytes_1(0, Acc) -> Acc;
diff --git a/lib/compiler/src/core_lint.erl b/lib/compiler/src/core_lint.erl
index 8b688df830..1e8983f594 100644
--- a/lib/compiler/src/core_lint.erl
+++ b/lib/compiler/src/core_lint.erl
@@ -309,7 +309,7 @@ expr(#c_fun{vars=Vs,body=B}, Def, Rt, St0) ->
{Vvs,St1} = variable_list(Vs, St0),
return_match(Rt, 1, body(B, union(Vvs, Def), any, St1));
expr(#c_seq{arg=Arg,body=B}, Def, Rt, St0) ->
- St1 = expr(Arg, Def, any, St0), %Ignore values
+ St1 = expr(Arg, Def, 1, St0),
body(B, Def, Rt, St1);
expr(#c_let{vars=Vs,arg=Arg,body=B}, Def, Rt, St0) ->
St1 = body(Arg, Def, let_varcount(Vs), St0), %This is a body
diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl
index d5fec0c869..cda3f7d81e 100644
--- a/lib/compiler/src/sys_core_fold.erl
+++ b/lib/compiler/src/sys_core_fold.erl
@@ -132,7 +132,12 @@ body(Body, Sub) ->
body(#c_values{anno=A,es=Es0}, Ctxt, Sub) ->
Es1 = expr_list(Es0, Ctxt, Sub),
- #c_values{anno=A,es=Es1};
+ case Ctxt of
+ value ->
+ #c_values{anno=A,es=Es1};
+ effect ->
+ make_effect_seq(Es1, Sub)
+ end;
body(E, Ctxt, Sub) ->
?ASSERT(verify_scope(E, Sub)),
expr(E, Ctxt, Sub).
@@ -1272,6 +1277,8 @@ eval_element(Call, #c_literal{val=Pos}, #c_var{name=V}, Types)
true ->
eval_failure(Call, badarg)
end;
+ {ok,_} ->
+ eval_failure(Call, badarg);
error ->
Call
end;
diff --git a/lib/compiler/test/Makefile b/lib/compiler/test/Makefile
index b9c5be09ce..51b3064589 100644
--- a/lib/compiler/test/Makefile
+++ b/lib/compiler/test/Makefile
@@ -75,6 +75,7 @@ INLINE= \
CORE_MODULES = \
bs_shadowed_size_var \
+ unused_multiple_values_error \
nested_call_in_case
diff --git a/lib/compiler/test/core_fold_SUITE.erl b/lib/compiler/test/core_fold_SUITE.erl
index 53a65d8d17..abc9ab6a72 100644
--- a/lib/compiler/test/core_fold_SUITE.erl
+++ b/lib/compiler/test/core_fold_SUITE.erl
@@ -21,7 +21,8 @@
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2,
t_element/1,setelement/1,t_length/1,append/1,t_apply/1,bifs/1,
- eq/1,nested_call_in_case/1,guard_try_catch/1,coverage/1]).
+ eq/1,nested_call_in_case/1,guard_try_catch/1,coverage/1,
+ unused_multiple_values_error/1,unused_multiple_values/1]).
-export([foo/0,foo/1,foo/2,foo/3]).
@@ -36,7 +37,8 @@ all() ->
groups() ->
[{p,test_lib:parallel(),
[t_element,setelement,t_length,append,t_apply,bifs,
- eq,nested_call_in_case,guard_try_catch,coverage]}].
+ eq,nested_call_in_case,guard_try_catch,coverage,
+ unused_multiple_values_error,unused_multiple_values]}].
init_per_suite(Config) ->
@@ -69,6 +71,9 @@ t_element(Config) when is_list(Config) ->
?line {'EXIT',{badarg,_}} = (catch element(5, {a,b,c,d})),
?line {'EXIT',{badarg,_}} = (catch element(5, {a,b,X,d})),
?line {'EXIT',{badarg,_}} = (catch element(5.0, {a,b,X,d})),
+ {'EXIT',{badarg,_}} = (catch element(2, not_a_tuple)),
+ {'EXIT',{badarg,_}} = (catch element(2, [])),
+ {'EXIT',{badarg,_}} = (catch element(2, Tuple == 3)),
case id({a,b,c}) of
{_,_,_}=Tup ->
?line {'EXIT',{badarg,_}} = (catch element(4, Tup))
@@ -89,6 +94,9 @@ setelement(Config) when is_list(Config) ->
?line {'EXIT',{badarg,_}} = (catch setelement_crash({a,b,c,d,e,f})),
?line error = setelement_crash_2({a,b,c,d,e,f}, <<42>>),
+
+ {'EXIT',{badarg,_}} = (catch setelement(1, not_a_tuple, New)),
+
ok.
setelement_crash(Tuple) ->
@@ -283,3 +291,41 @@ cover_is_safe_bool_expr(X) ->
end.
id(I) -> I.
+
+unused_multiple_values_error(Config) when is_list(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ Dir = filename:dirname(code:which(?MODULE)),
+ Core = filename:join(Dir, "unused_multiple_values_error"),
+ Opts = [no_copt,clint,return,from_core,{outdir,PrivDir}
+ |test_lib:opt_opts(?MODULE)],
+ {error,[{unused_multiple_values_error,
+ [{core_lint,{return_mismatch,{hello,1}}}]}],
+ []} = c:c(Core, Opts),
+ ok.
+
+unused_multiple_values(Config) when is_list(Config) ->
+ put(unused_multiple_values, []),
+ [false] = test_unused_multiple_values(false),
+ [b,a,{a,b},false] = test_unused_multiple_values({a,b}),
+ ok.
+
+test_unused_multiple_values(X) ->
+ ok = do_unused_multiple_values(X),
+ get(unused_multiple_values).
+
+do_unused_multiple_values(X) ->
+ case do_something(X) of
+ false ->
+ A = false;
+ Res ->
+ {A,B} = Res,
+ do_something(A),
+ do_something(B)
+ end,
+ _ThisShouldNotFail = A,
+ ok.
+
+do_something(I) ->
+ put(unused_multiple_values,
+ [I|get(unused_multiple_values)]),
+ I.
diff --git a/lib/compiler/test/unused_multiple_values_error.core b/lib/compiler/test/unused_multiple_values_error.core
new file mode 100644
index 0000000000..e06587c936
--- /dev/null
+++ b/lib/compiler/test/unused_multiple_values_error.core
@@ -0,0 +1,11 @@
+module 'unused_multiple_values_error' ['hello'/1]
+ attributes []
+'hello'/1 =
+ fun (_cor0) ->
+ do
+ case _cor0 of
+ <_cor0> when 'true' ->
+ <'ok','ok'>
+ end
+ 'ok'
+end
diff --git a/lib/erl_interface/src/decode/decode_fun.c b/lib/erl_interface/src/decode/decode_fun.c
index c4667822e5..2adaedb825 100644
--- a/lib/erl_interface/src/decode/decode_fun.c
+++ b/lib/erl_interface/src/decode/decode_fun.c
@@ -30,6 +30,25 @@ int ei_decode_fun(const char *buf, int *index, erlang_fun *p)
const char *s = buf + *index;
const char *s0 = s;
int i, ix, ix0, n;
+ erlang_pid* p_pid;
+ char* p_module;
+ enum erlang_char_encoding* p_module_org_enc;
+ long* p_index;
+ long* p_uniq;
+ long* p_old_index;
+
+ if (p != NULL) {
+ p_pid = &p->pid;
+ p_module = &p->module[0];
+ p_module_org_enc = &p->module_org_enc;
+ p_index = &p->index;
+ p_uniq = &p->uniq;
+ p_old_index = &p->old_index;
+ }
+ else {
+ p_pid = NULL; p_module = NULL; p_module_org_enc = NULL;
+ p_index = NULL; p_uniq = NULL; p_old_index = NULL;
+ }
switch (get8(s)) {
case ERL_FUN_EXT:
@@ -39,17 +58,17 @@ int ei_decode_fun(const char *buf, int *index, erlang_fun *p)
n = get32be(s);
/* then the pid */
ix = 0;
- if (ei_decode_pid(s, &ix, (p == NULL ? (erlang_pid*)NULL : &p->pid)) < 0)
+ if (ei_decode_pid(s, &ix, p_pid) < 0)
return -1;
/* then the module (atom) */
- if (ei_decode_atom_as(s, &ix, (p == NULL ? (char*)NULL : p->module),
- MAXATOMLEN_UTF8, ERLANG_UTF8, &p->module_org_enc, NULL) < 0)
+ if (ei_decode_atom_as(s, &ix, p_module, MAXATOMLEN_UTF8, ERLANG_UTF8,
+ p_module_org_enc, NULL) < 0)
return -1;
/* then the index */
- if (ei_decode_long(s, &ix, (p == NULL ? (long*)NULL : &p->index)) < 0)
+ if (ei_decode_long(s, &ix, p_index) < 0)
return -1;
/* then the uniq */
- if (ei_decode_long(s, &ix, (p == NULL ? (long*)NULL : &p->uniq)) < 0)
+ if (ei_decode_long(s, &ix, p_uniq) < 0)
return -1;
/* finally the free vars */
ix0 = ix;
@@ -85,17 +104,17 @@ int ei_decode_fun(const char *buf, int *index, erlang_fun *p)
if (p != NULL) p->n_free_vars = i;
/* then the module (atom) */
ix = 0;
- if (ei_decode_atom_as(s, &ix, (p == NULL ? (char*)NULL : p->module),
- MAXATOMLEN_UTF8, ERLANG_UTF8, &p->module_org_enc, NULL) < 0)
+ if (ei_decode_atom_as(s, &ix, p_module, MAXATOMLEN_UTF8, ERLANG_UTF8,
+ p_module_org_enc, NULL) < 0)
return -1;
/* then the old_index */
- if (ei_decode_long(s, &ix, (p == NULL ? (long*)NULL : &p->old_index)) < 0)
+ if (ei_decode_long(s, &ix, p_old_index) < 0)
return -1;
/* then the old_uniq */
- if (ei_decode_long(s, &ix, (p == NULL ? (long*)NULL : &p->uniq)) < 0)
+ if (ei_decode_long(s, &ix, p_uniq) < 0)
return -1;
/* the the pid */
- if (ei_decode_pid(s, &ix, (p == NULL ? (erlang_pid*)NULL : &p->pid)) < 0)
+ if (ei_decode_pid(s, &ix, p_pid) < 0)
return -1;
/* finally the free vars */
s += ix;
diff --git a/lib/erl_interface/src/decode/decode_pid.c b/lib/erl_interface/src/decode/decode_pid.c
index 67ce7e05f9..d429fb2fd8 100644
--- a/lib/erl_interface/src/decode/decode_pid.c
+++ b/lib/erl_interface/src/decode/decode_pid.c
@@ -29,16 +29,16 @@ int ei_decode_pid(const char *buf, int *index, erlang_pid *p)
if (get8(s) != ERL_PID_EXT) return -1;
- /* first the nodename */
- if (get_atom(&s, p->node, &p->node_org_enc) < 0) return -1;
-
- /* now the numbers: num (4), serial (4), creation (1) */
if (p) {
+ if (get_atom(&s, p->node, &p->node_org_enc) < 0) return -1;
p->num = get32be(s) & 0x7fff; /* 15 bits */
p->serial = get32be(s) & 0x1fff; /* 13 bits */
p->creation = get8(s) & 0x03; /* 2 bits */
}
- else s+= 9;
+ else {
+ if (get_atom(&s, NULL, NULL) < 0) return -1;
+ s+= 9;
+ }
*index += s-s0;
diff --git a/lib/erl_interface/src/decode/decode_port.c b/lib/erl_interface/src/decode/decode_port.c
index 2d1b46e705..7a691f0be6 100644
--- a/lib/erl_interface/src/decode/decode_port.c
+++ b/lib/erl_interface/src/decode/decode_port.c
@@ -28,15 +28,15 @@ int ei_decode_port(const char *buf, int *index, erlang_port *p)
if (get8(s) != ERL_PORT_EXT) return -1;
- /* first the nodename */
- if (get_atom(&s, p->node, &p->node_org_enc) < 0) return -1;
-
- /* now the numbers: num (4), creation (1) */
if (p) {
+ if (get_atom(&s, p->node, &p->node_org_enc) < 0) return -1;
p->id = get32be(s) & 0x0fffffff /* 28 bits */;
p->creation = get8(s) & 0x03;
}
- else s += 5;
+ else {
+ if (get_atom(&s, NULL, NULL) < 0) return -1;
+ s += 5;
+ }
*index += s-s0;
diff --git a/lib/erl_interface/src/decode/decode_ref.c b/lib/erl_interface/src/decode/decode_ref.c
index 579371ed7d..01e3061cb4 100644
--- a/lib/erl_interface/src/decode/decode_ref.c
+++ b/lib/erl_interface/src/decode/decode_ref.c
@@ -30,17 +30,16 @@ int ei_decode_ref(const char *buf, int *index, erlang_ref *p)
switch (get8(s)) {
case ERL_REFERENCE_EXT:
-
- /* nodename */
- if (get_atom(&s, p->node, &p->node_org_enc) < 0) return -1;
-
- /* now the numbers: num (4), creation (1) */
if (p) {
+ if (get_atom(&s, p->node, &p->node_org_enc) < 0) return -1;
p->n[0] = get32be(s);
p->len = 1;
p->creation = get8(s) & 0x03;
}
- else s += 5;
+ else {
+ if (get_atom(&s, NULL, NULL) < 0) return -1;
+ s += 5;
+ }
*index += s-s0;
@@ -50,16 +49,16 @@ int ei_decode_ref(const char *buf, int *index, erlang_ref *p)
case ERL_NEW_REFERENCE_EXT:
/* first the integer count */
count = get16be(s);
- if (p) p->len = count;
- /* then the nodename */
- if (get_atom(&s, p->node, &p->node_org_enc) < 0) return -1;
-
- /* creation */
if (p) {
+ p->len = count;
+ if (get_atom(&s, p->node, &p->node_org_enc) < 0) return -1;
p->creation = get8(s) & 0x03;
}
- else s += 1;
+ else {
+ if (get_atom(&s, NULL, NULL) < 0) return -1;
+ s += 1;
+ }
/* finally the id integers */
if (p) {
diff --git a/lib/erl_interface/src/decode/decode_skip.c b/lib/erl_interface/src/decode/decode_skip.c
index f6c5d861ab..e2bfe1f802 100644
--- a/lib/erl_interface/src/decode/decode_skip.c
+++ b/lib/erl_interface/src/decode/decode_skip.c
@@ -30,7 +30,8 @@ int ei_skip_term(const char* buf, int* index)
switch (ty) {
case ERL_ATOM_EXT:
/* FIXME: what if some weird locale is in use? */
- if (ei_decode_atom(buf, index, NULL) < 0) return -1;
+ if (ei_decode_atom_as(buf, index, NULL, MAXATOMLEN_UTF8, (ERLANG_LATIN1|ERLANG_UTF8),
+ NULL, NULL) < 0) return -1;
break;
case ERL_PID_EXT:
if (ei_decode_pid(buf, index, NULL) < 0) return -1;
diff --git a/lib/erl_interface/src/decode/decode_trace.c b/lib/erl_interface/src/decode/decode_trace.c
index ebaa78e29e..88fb3451ec 100644
--- a/lib/erl_interface/src/decode/decode_trace.c
+++ b/lib/erl_interface/src/decode/decode_trace.c
@@ -22,18 +22,30 @@
int ei_decode_trace(const char *buf, int *index, erlang_trace *p)
{
int arity = 0;
- int tindex = *index;
-
- /* use a temporary index if any function should fail */
+ int tindex = *index; /* use a temporary index if any function should fail */
+ long *p_flags, *p_label, *p_serial, *p_prev;
+ erlang_pid *p_from;
+
+ if (p != NULL) {
+ p_flags = &p->flags;
+ p_label = &p->label;
+ p_serial = &p->serial;
+ p_prev = &p->prev;
+ p_from = &p->from;
+ }
+ else {
+ p_flags = p_label = p_serial = p_prev = NULL;
+ p_from = NULL;
+ }
/* { Flags, Label, Serial, FromPid, Prev } */
if (ei_decode_tuple_header(buf, &tindex, &arity)
|| (arity != 5)
- || ei_decode_long(buf, &tindex, &p->flags)
- || ei_decode_long(buf, &tindex, &p->label)
- || ei_decode_long(buf, &tindex, &p->serial)
- || ei_decode_pid( buf, &tindex, &p->from)
- || ei_decode_long(buf, &tindex, &p->prev)) return -1;
+ || ei_decode_long(buf, &tindex, p_flags)
+ || ei_decode_long(buf, &tindex, p_label)
+ || ei_decode_long(buf, &tindex, p_serial)
+ || ei_decode_pid( buf, &tindex, p_from)
+ || ei_decode_long(buf, &tindex, p_prev)) return -1;
/* index is updated by the functions we called */
diff --git a/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c b/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c
index b3f0807765..317e5edecd 100644
--- a/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c
+++ b/lib/erl_interface/test/ei_decode_encode_SUITE_data/ei_decode_encode_test.c
@@ -52,7 +52,8 @@ typedef struct
int ei_decode_my_atom(const char *buf, int *index, my_atom* a)
{
- return ei_decode_atom_as(buf, index, a->name, sizeof(a->name), ERLANG_UTF8, &a->enc, NULL);
+ return ei_decode_atom_as(buf, index, (a ? a->name : NULL), sizeof(a->name),
+ ERLANG_UTF8, (a ? &a->enc : NULL), NULL);
}
int ei_encode_my_atom(char *buf, int *index, my_atom* a)
{
@@ -77,7 +78,7 @@ void decode_encode(struct Type* t, void* obj)
MESSAGE("ei_decode_%s, arg is type %s", t->name, t->type);
buf = read_packet(NULL);
- err = t->ei_decode_fp(buf+1, &size1, obj);
+ err = t->ei_decode_fp(buf+1, &size1, NULL);
if (err != 0) {
if (err != -1) {
fail("decode returned non zero but not -1");
@@ -96,7 +97,35 @@ void decode_encode(struct Type* t, void* obj)
return;
}
+ err = t->ei_decode_fp(buf+1, &size2, obj);
+ if (err != 0) {
+ if (err != -1) {
+ fail("decode returned non zero but not -1");
+ } else {
+ fail("decode returned non zero");
+ }
+ return;
+ }
+ if (size1 != size2) {
+ MESSAGE("size1 = %d, size2 = %d\n",size1,size2);
+ fail("decode sizes differs");
+ return;
+ }
+
+ size2 = 0;
+ err = ei_skip_term(buf+1, &size2);
+ if (err != 0) {
+ fail("ei_skip_term returned non zero");
+ return;
+ }
+ if (size1 != size2) {
+ MESSAGE("size1 = %d, size2 = %d\n",size1,size2);
+ fail("skip size differs");
+ return;
+ }
+
MESSAGE("ei_encode_%s buf is NULL, arg is type %s", t->name, t->type);
+ size2 = 0;
err = t->ei_encode_fp(NULL, &size2, obj);
if (err != 0) {
if (err != -1) {
diff --git a/lib/kernel/doc/src/specs.xml b/lib/kernel/doc/src/specs.xml
index b41addaa0c..813bb06e1f 100644
--- a/lib/kernel/doc/src/specs.xml
+++ b/lib/kernel/doc/src/specs.xml
@@ -29,5 +29,4 @@
<xi:include href="../specs/specs_user.xml"/>
<xi:include href="../specs/specs_wrap_log_reader.xml"/>
<xi:include href="../specs/specs_zlib_stub.xml"/>
- <xi:include href="../specs/specs_packages.xml"/>
</specs>
diff --git a/lib/kernel/src/inet6_tcp_dist.erl b/lib/kernel/src/inet6_tcp_dist.erl
index b9c4fa607c..2315a56582 100644
--- a/lib/kernel/src/inet6_tcp_dist.erl
+++ b/lib/kernel/src/inet6_tcp_dist.erl
@@ -71,8 +71,12 @@ listen(Name) ->
{ok, Socket} ->
TcpAddress = get_tcp_address(Socket),
{_,Port} = TcpAddress#net_address.address,
- {ok, Creation} = erl_epmd:register_node(Name, Port),
- {ok, {Socket, TcpAddress, Creation}};
+ case erl_epmd:register_node(Name, Port) of
+ {ok, Creation} ->
+ {ok, {Socket, TcpAddress, Creation}};
+ Error ->
+ Error
+ end;
Error ->
Error
end.
diff --git a/lib/kernel/src/inet_tcp_dist.erl b/lib/kernel/src/inet_tcp_dist.erl
index 7f935c2b36..70f3c87723 100644
--- a/lib/kernel/src/inet_tcp_dist.erl
+++ b/lib/kernel/src/inet_tcp_dist.erl
@@ -67,8 +67,12 @@ listen(Name) ->
{ok, Socket} ->
TcpAddress = get_tcp_address(Socket),
{_,Port} = TcpAddress#net_address.address,
- {ok, Creation} = erl_epmd:register_node(Name, Port),
- {ok, {Socket, TcpAddress, Creation}};
+ case erl_epmd:register_node(Name, Port) of
+ {ok, Creation} ->
+ {ok, {Socket, TcpAddress, Creation}};
+ Error ->
+ Error
+ end;
Error ->
Error
end.
diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk
index 46a991eb38..b6cf4407d2 100644
--- a/lib/kernel/vsn.mk
+++ b/lib/kernel/vsn.mk
@@ -1 +1 @@
-KERNEL_VSN = 2.16
+KERNEL_VSN = 2.16.1
diff --git a/lib/odbc/src/odbc.erl b/lib/odbc/src/odbc.erl
index 3eabec9ec3..dde96907e5 100644
--- a/lib/odbc/src/odbc.erl
+++ b/lib/odbc/src/odbc.erl
@@ -902,7 +902,9 @@ param_values(Params) ->
[{_, Values} | _] ->
Values;
[{_, _, Values} | _] ->
- Values
+ Values;
+ [] ->
+ []
end.
%%-------------------------------------------------------------------------
diff --git a/lib/odbc/test/odbc_query_SUITE.erl b/lib/odbc/test/odbc_query_SUITE.erl
index 1852678b4b..61253b29aa 100644
--- a/lib/odbc/test/odbc_query_SUITE.erl
+++ b/lib/odbc/test/odbc_query_SUITE.erl
@@ -63,7 +63,8 @@ groups() ->
param_insert_numeric, {group, param_insert_string},
param_insert_float, param_insert_real,
param_insert_double, param_insert_mix, param_update,
- param_delete, param_select]},
+ param_delete, param_select,
+ param_select_empty_params, param_delete_empty_params]},
{param_integers, [],
[param_insert_tiny_int, param_insert_small_int,
param_insert_int, param_insert_integer]},
@@ -1345,6 +1346,70 @@ param_select(Config) when is_list(Config) ->
ok.
%%-------------------------------------------------------------------------
+param_select_empty_params(doc) ->
+ ["Test parameterized select query with no parameters."];
+param_select_empty_params(suite) ->
+ [];
+param_select_empty_params(Config) when is_list(Config) ->
+ Ref = ?config(connection_ref, Config),
+ Table = ?config(tableName, Config),
+
+ {updated, _} =
+ odbc:sql_query(Ref,
+ "CREATE TABLE " ++ Table ++
+ " (ID INTEGER, DATA CHARACTER VARYING(10),"
+ " PRIMARY KEY(ID))"),
+
+ {updated, Count} = odbc:param_query(Ref, "INSERT INTO " ++ Table ++
+ "(ID, DATA) VALUES(?, ?)",
+ [{sql_integer, [1, 2, 3]},
+ {{sql_varchar, 10},
+ ["foo", "bar", "foo"]}]),
+
+ true = odbc_test_lib:check_row_count(3, Count),
+
+ SelectResult = ?RDBMS:param_select(),
+
+ SelectResult = odbc:param_query(Ref, "SELECT * FROM " ++ Table ++
+ " WHERE DATA = \'foo\'",
+ []),
+ ok.
+
+%%-------------------------------------------------------------------------
+param_delete_empty_params(doc) ->
+ ["Test parameterized delete query with no parameters."];
+param_delete_empty_params(suite) ->
+ [];
+param_delete_empty_params(Config) when is_list(Config) ->
+ Ref = ?config(connection_ref, Config),
+ Table = ?config(tableName, Config),
+
+ {updated, _} =
+ odbc:sql_query(Ref,
+ "CREATE TABLE " ++ Table ++
+ " (ID INTEGER, DATA CHARACTER VARYING(10),"
+ " PRIMARY KEY(ID))"),
+
+ {updated, Count} = odbc:param_query(Ref, "INSERT INTO " ++ Table ++
+ "(ID, DATA) VALUES(?, ?)",
+ [{sql_integer, [1, 2, 3]},
+ {{sql_varchar, 10},
+ ["foo", "bar", "baz"]}]),
+ true = odbc_test_lib:check_row_count(3, Count),
+
+ {updated, NewCount} = odbc:param_query(Ref, "DELETE FROM " ++ Table ++
+ " WHERE ID = 1 OR ID = 2",
+ []),
+
+ true = odbc_test_lib:check_row_count(2, NewCount),
+
+ UpdateResult = ?RDBMS:param_delete(),
+
+ UpdateResult =
+ odbc:sql_query(Ref, "SELECT * FROM " ++ Table),
+ ok.
+
+%%-------------------------------------------------------------------------
describe_integer(doc) ->
["Test describe_table/[2,3] for integer columns."];
describe_integer(suite) ->
diff --git a/lib/odbc/vsn.mk b/lib/odbc/vsn.mk
index 585b92b2d2..b3ffff2cf8 100644
--- a/lib/odbc/vsn.mk
+++ b/lib/odbc/vsn.mk
@@ -1 +1 @@
-ODBC_VSN = 2.10.14
+ODBC_VSN = 2.10.15
diff --git a/lib/sasl/src/sasl.appup.src b/lib/sasl/src/sasl.appup.src
index ce4aa1f8f8..a4a38ee40a 100644
--- a/lib/sasl/src/sasl.appup.src
+++ b/lib/sasl/src/sasl.appup.src
@@ -1,7 +1,7 @@
%% -*- erlang -*-
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1999-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
@@ -17,11 +17,13 @@
%% %CopyrightEnd%
{"%VSN%",
%% Up from - max two major revisions back
- [{<<"2\\.2(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R15
- {<<"2\\.1\\.10(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R14B04 (and later?)
- {<<"2\\.1\\.[6-9](\\.[0-9]+)*">>,[restart_new_emulator]}],%% R13B-R14B03
+ [{<<"2\\.3(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R16
+ {<<"2\\.2(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R15
+ {<<"2\\.1\\.10(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R14B04
+ {<<"2\\.1\\.9\\.[24](\\.[0-9]+)*">>,[restart_new_emulator]}],%% R14B-R14B03
%% Down to - max two major revisions back
- [{<<"2\\.2(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R15
- {<<"2\\.1\\.10(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R14B04 (and later?)
- {<<"2\\.1\\.[6-9](\\.[0-9]+)*">>,[restart_new_emulator]}] %% R13B-R14B03
+ [{<<"2\\.3(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R16
+ {<<"2\\.2(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R15
+ {<<"2\\.1\\.10(\\.[0-9]+)*">>,[restart_new_emulator]}, %% R14B04
+ {<<"2\\.1\\.9\\.[24](\\.[0-9]+)*">>,[restart_new_emulator]}] %% R14B-R14B03
}.
diff --git a/lib/snmp/.gitignore b/lib/snmp/.gitignore
new file mode 100644
index 0000000000..b82d23e7bd
--- /dev/null
+++ b/lib/snmp/.gitignore
@@ -0,0 +1,4 @@
+# Match at any level.
+
+*.BKP
+
diff --git a/lib/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml
index 5b94dcb051..5222922848 100644
--- a/lib/snmp/doc/src/notes.xml
+++ b/lib/snmp/doc/src/notes.xml
@@ -34,6 +34,79 @@
<section>
+ <title>SNMP Development Toolkit 4.23.1</title>
+ <p>Version 4.23.1 supports code replacement in runtime from/to
+ version 4.23. </p>
+
+ <section>
+ <title>Improvements and new features</title>
+ <p>-</p>
+
+<!--
+ <list type="bulleted">
+ <item>
+ <p>[agent] Errors in <c>vacmAccessTable</c> RowStatus handling.
+ There are problems with the handling of vacmAccessTableStatus
+ that cause some SNMP test suites to report errors.
+ Most notably, erroneous set operations frequently cause "genErr"
+ errors to be returned. These "genErr" errors are usually caused
+ by badmatch exceptions coming from
+ <c>{ok, Row} = snmpa_vacm:get_row(RowIndex)</c>
+ if the row does not exist. </p>
+ <p>The semantics of the RowStatus handling in that table has
+ been adjusted to be compliant with the RowStatus
+ textual description of SNPMv2-TC MIB. </p>
+ <p>Stefan Zegenhagen</p>
+ <p>Own Id: OTP-10164</p>
+ </item>
+ </list>
+-->
+
+ </section>
+
+ <section>
+ <title>Fixed Bugs and Malfunctions</title>
+<!--
+ <p>-</p>
+-->
+
+ <list type="bulleted">
+ <item>
+ <p>[compiler] Now handles MIBs importing the pesudotype BITS. </p>
+ <p>Own Id: OTP-10799</p>
+ </item>
+
+ <item>
+ <p>[compiler] The MIB compiler could not handle a table index
+ that was defined later in the MIB. </p>
+ <p>Own Id: OTP-10808</p>
+ </item>
+
+ </list>
+
+ </section>
+
+ <section>
+ <title>Incompatibilities</title>
+ <p>-</p>
+
+<!--
+ <list type="bulleted">
+ <item>
+ <p>[manager] The old Addr-and-Port based API functions, previously
+ long deprecated and marked for deletion in R16B, has now been
+ removed. </p>
+ <p>Own Id: OTP-10027</p>
+ </item>
+
+ </list>
+-->
+ </section>
+
+ </section> <!-- 4.23.1 -->
+
+
+ <section>
<title>SNMP Development Toolkit 4.23</title>
<!--
<p>Version 4.23 supports code replacement in runtime from/to
@@ -69,7 +142,6 @@
</item>
</list>
-
</section>
<section>
@@ -90,7 +162,6 @@
</list>
-->
-
</section>
<section>
diff --git a/lib/snmp/src/app/snmp.appup.src b/lib/snmp/src/app/snmp.appup.src
index a6abf8439a..4c5f14da90 100644
--- a/lib/snmp/src/app/snmp.appup.src
+++ b/lib/snmp/src/app/snmp.appup.src
@@ -22,11 +22,19 @@
%% ----- U p g r a d e -------------------------------------------------------
[
+ {"4.23",
+ [
+ ]
+ }
],
%% ------D o w n g r a d e ---------------------------------------------------
[
+ {"4.23",
+ [
+ ]
+ }
]
}.
diff --git a/lib/snmp/src/compile/snmpc.erl b/lib/snmp/src/compile/snmpc.erl
index 5e6b81f1ec..d94810bc0a 100644
--- a/lib/snmp/src/compile/snmpc.erl
+++ b/lib/snmp/src/compile/snmpc.erl
@@ -516,7 +516,7 @@ definitions_loop([{#mc_object_type{name = NameOfTable,
fields = FieldList},
Sline}|ColsEtc],
Data) ->
- ?vlog("defloop -> "
+ ?vlog("defloop(~w) -> "
"[object_type(sequence_of),object_type(type,[1]),sequence]:"
"~n NameOfTable: ~p"
"~n SeqName: ~p"
@@ -535,7 +535,8 @@ definitions_loop([{#mc_object_type{name = NameOfTable,
"~n Eline: ~p"
"~n FieldList: ~p"
"~n Sline: ~p",
- [NameOfTable,SeqName,Taccess,Kind,Tstatus,
+ [?LINE,
+ NameOfTable,SeqName,Taccess,Kind,Tstatus,
Tindex,Tunits,Tline,
NameOfEntry,TEline,IndexingInfo,Estatus,Eunits,Ref,Eline,
FieldList,Sline]),
@@ -562,8 +563,9 @@ definitions_loop([{#mc_object_type{name = NameOfTable,
units = Eunits},
{ColMEs, RestObjs} =
define_cols(ColsEtc, 1, FieldList, NameOfEntry, NameOfTable, []),
+ AfterIdxTypes = after_indexes_type(IndexingInfo, RestObjs),
TableInfo = snmpc_lib:make_table_info(Eline, NameOfTable,
- IndexingInfo, ColMEs),
+ IndexingInfo, AfterIdxTypes, ColMEs),
snmpc_lib:add_cdata(#cdata.mes,
[TableEntryME,
TableME#me{assocList=[{table_info,
@@ -595,7 +597,7 @@ definitions_loop([{#mc_object_type{name = NameOfTable,
Sline}|ColsEtc],
#dldata{relaxed_row_name_assign_check = true} = Data)
when is_integer(Idx) andalso (Idx > 1) ->
- ?vlog("defloop -> "
+ ?vlog("defloop(~w) -> "
"[object_type(sequence_of),object_type(type,[~w]),sequence]:"
"~n NameOfTable: ~p"
"~n SeqName: ~p"
@@ -614,7 +616,8 @@ definitions_loop([{#mc_object_type{name = NameOfTable,
"~n Eline: ~p"
"~n FieldList: ~p"
"~n Sline: ~p",
- [Idx,
+ [?LINE,
+ Idx,
NameOfTable,SeqName,Taccess,Kind,Tstatus,
Tindex,Tunits,Tline,
NameOfEntry,TEline,IndexingInfo,Estatus,Eunits,Ref,Eline,
@@ -644,8 +647,9 @@ definitions_loop([{#mc_object_type{name = NameOfTable,
units = Eunits},
{ColMEs, RestObjs} =
define_cols(ColsEtc, 1, FieldList, NameOfEntry, NameOfTable, []),
+ AfterIdxTypes = after_indexes_type(IndexingInfo, RestObjs),
TableInfo = snmpc_lib:make_table_info(Eline, NameOfTable,
- IndexingInfo, ColMEs),
+ IndexingInfo, AfterIdxTypes, ColMEs),
snmpc_lib:add_cdata(#cdata.mes,
[TableEntryME,
TableME#me{assocList=[{table_info,
@@ -673,7 +677,7 @@ definitions_loop([{#mc_object_type{name = NameOfTable,
{#mc_sequence{name = SeqName,
fields = FieldList}, Sline}|ColsEtc],
Data) ->
- ?vlog("defloop -> "
+ ?vlog("defloop(~w) -> "
"[object_type(sequence_of),object_type(type),sequence(fieldList)]:"
"~n NameOfTable: ~p"
"~n SeqName: ~p"
@@ -692,7 +696,8 @@ definitions_loop([{#mc_object_type{name = NameOfTable,
"~n Eline: ~p"
"~n FieldList: ~p"
"~n Sline: ~p",
- [NameOfTable,SeqName,Taccess,Kind,Tstatus,
+ [?LINE,
+ NameOfTable,SeqName,Taccess,Kind,Tstatus,
Tindex,Tunits,Tline,
NameOfEntry,IndexingInfo,Estatus,BadOID,Eunits,Ref,Eline,
FieldList,Sline]),
@@ -720,8 +725,9 @@ definitions_loop([{#mc_object_type{name = NameOfTable,
units = Eunits},
{ColMEs, RestObjs} =
define_cols(ColsEtc, 1, FieldList, NameOfEntry, NameOfTable, []),
+ AfterIdxTypes = after_indexes_type(IndexingInfo, RestObjs),
TableInfo = snmpc_lib:make_table_info(Eline, NameOfTable,
- IndexingInfo, ColMEs),
+ IndexingInfo, AfterIdxTypes, ColMEs),
snmpc_lib:add_cdata(#cdata.mes,
[TableEntryME,
TableME#me{assocList=[{table_info,
@@ -813,7 +819,7 @@ definitions_loop([{#mc_module_identity{name = NewVarName,
"~n Desc: ~p"
"~n Revs0: ~p"
"~n Parent: ~p"
- "~n SubIndex: ~p",
+ "~n SubIndex: ~w",
[NewVarName, LU, Org, CI, Desc, Revs0, Parent, SubIndex], Line),
ensure_macro_imported('MODULE-IDENTITY', Line),
snmpc_lib:register_oid(Line, NewVarName, Parent, SubIndex),
@@ -839,7 +845,7 @@ definitions_loop([{#mc_internal{name = NewVarName,
"~n NewVarName: ~p"
"~n Macro: ~p"
"~n Parent: ~p"
- "~n SubIndex: ~p",
+ "~n SubIndex: ~w",
[NewVarName, Macro, Parent, SubIndex], Line),
ensure_macro_imported(Macro, Line),
snmpc_lib:register_oid(Line, NewVarName, Parent, SubIndex),
@@ -1205,6 +1211,12 @@ safe_elem(N,T) ->
X -> X
end.
+
+%% An table index is either:
+%% a) part of the table
+%% b) not part of the table and defined *before* the table
+%% c) not part of the table and defined *after* the table
+
%% A correct column
define_cols([{#mc_object_type{name = NameOfCol,
syntax = Type1,
@@ -1379,14 +1391,45 @@ define_cols(Rest, _SubIndex,_,_,_,ColMEs) ->
snmpc_lib:print_error("Corrupt table definition.",[]),
{ColMEs,Rest}.
+
+%% Table indexes can either be:
+%% a) part of the table (a column)
+%% b) not part of the table and defined *before* the table
+%% c) not part of the table and defined *after* the table
+
+after_indexes_type({indexes, Indexes}, Objs) ->
+ after_indexes_type2(Indexes, Objs);
+after_indexes_type(_, _) ->
+ [].
+
+after_indexes_type2(Indexes, Objs) ->
+ after_indexes_type2(Indexes, Objs, []).
+
+after_indexes_type2([], _Objs, IndexesASN1types) ->
+ IndexesASN1types;
+after_indexes_type2([Index|Indexes], Objs, Acc) ->
+ Acc2 = after_indexes_type3(Index, Objs, Acc),
+ after_indexes_type2(Indexes, Objs, Acc2).
+
+after_indexes_type3(_Index, [], Acc) ->
+ Acc;
+after_indexes_type3(Index,
+ [{#mc_object_type{name = Index,
+ syntax = Syntax},_}|_], Acc) ->
+ ASN1 = snmpc_lib:make_ASN1type(Syntax),
+ [{Index, ASN1}|Acc];
+after_indexes_type3(Index, [_|Objs], Acc) ->
+ after_indexes_type3(Index, Objs, Acc).
+
+
+
ensure_macro_imported(dummy, _Line) -> ok;
ensure_macro_imported(Macro, Line) ->
Macros = (get(cdata))#cdata.imported_macros,
case lists:member(Macro, Macros) of
true -> ok;
false ->
- snmpc_lib:print_error("Macro ~p not imported.", [Macro],
- Line)
+ snmpc_lib:print_error("Macro ~p not imported.", [Macro], Line)
end.
test_table(NameOfTable, Taccess, Kind, _Tindex, Tline) ->
diff --git a/lib/snmp/src/compile/snmpc_lib.erl b/lib/snmp/src/compile/snmpc_lib.erl
index c7eae307e8..5a661cf194 100644
--- a/lib/snmp/src/compile/snmpc_lib.erl
+++ b/lib/snmp/src/compile/snmpc_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1997-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,7 +24,7 @@
-compile({no_auto_import,[error/2]}).
-export([test_father/4, make_ASN1type/1, import/1, makeInternalNode2/2,
is_consistent/1, resolve_defval/1, make_variable_info/1,
- check_trap_name/3, make_table_info/4, get_final_mib/2, set_dir/2,
+ check_trap_name/3, make_table_info/5, get_final_mib/2, set_dir/2,
look_at/1, add_cdata/2,
check_object_group/4, check_notification_group/4,
check_notification/3,
@@ -240,7 +240,10 @@ import_mib({{'SNMPv2-SMI', ImportsFromMib},Line}) ->
aliasname = 'Opaque'},
#asn1_type{bertype = 'Counter64',
aliasname = 'Counter64',
- lo = 0, hi = 18446744073709551615}],
+ lo = 0, hi = 18446744073709551615},
+ #asn1_type{bertype = 'BITS',
+ aliasname = 'BITS'}
+ ],
Macros = ['MODULE-IDENTITY','OBJECT-IDENTITY','OBJECT-TYPE',
'NOTIFICATION-TYPE'],
import_built_in_loop(ImportsFromMib,Nodes,Types,Macros,'SNMPv2-SMI',Line);
@@ -704,7 +707,8 @@ check_trap_name(EnterpriseName, Line, MEs) ->
%% This information is needed to be able to create default instrumentation
%% functions for tables.
%%----------------------------------------------------------------------
-make_table_info(Line, TableName, {augments, SrcTableEntry}, ColumnMEs) ->
+
+make_table_info(Line, TableName, {augments, SrcTableEntry}, _, ColumnMEs) ->
ColMEs = lists:keysort(#me.oid, ColumnMEs),
Nbr_of_Cols = length(ColMEs),
MEs = ColMEs ++ (get(cdata))#cdata.mes,
@@ -723,16 +727,18 @@ make_table_info(Line, TableName, {augments, SrcTableEntry}, ColumnMEs) ->
first_accessible = FirstAcc,
not_accessible = NoAccs,
index_types = Aug};
-make_table_info(Line, TableName, {indexes, []}, _ColumnMEs) ->
+make_table_info(Line, TableName, {indexes, []}, _, _ColumnMEs) ->
print_error("Table ~w lacks indexes.", [TableName],Line),
#table_info{};
-make_table_info(Line, TableName, {indexes, Indexes}, ColumnMEs) ->
+make_table_info(Line, TableName, {indexes, Indexes}, AfterIdxTypes,
+ ColumnMEs) ->
ColMEs = lists:keysort(#me.oid, ColumnMEs),
NonImpliedIndexes = lists:map(fun non_implied_name/1, Indexes),
test_read_create_access(ColMEs, Line, dummy),
NonIndexCol = test_index_positions(Line, NonImpliedIndexes, ColMEs),
Nbr_of_Cols = length(ColMEs),
- ASN1Indexes = find_asn1_types_for_indexes(Indexes, ColMEs, Line),
+ ASN1Indexes = find_asn1_types_for_indexes(Indexes,
+ AfterIdxTypes, ColMEs, Line),
FA = first_accessible(TableName, ColMEs),
StatCol = find_status_col(Line, TableName, ColMEs),
NoAccs = list_not_accessible(NonIndexCol,ColMEs),
@@ -816,11 +822,17 @@ get_defvals(ColMEs) ->
lists:filter(fun drop_undefined/1,
lists:map(fun column_and_defval/1, ColMEs))).
-find_asn1_types_for_indexes(Indexes, ColMEs,Line) ->
- MEs = ColMEs ++ (get(cdata))#cdata.mes,
+find_asn1_types_for_indexes(Indexes, AfterIdxTypes, ColMEs, Line) ->
+ ?vtrace("find_asn1_types_for_indexes -> "
+ "~n Indexes: ~p"
+ "~n ColMEs: ~p"
+ "~n Line: ~p", [Indexes, ColMEs, Line]),
+ MEs = ColMEs ++ (get(cdata))#cdata.mes ++
+ [#me{aliasname = Idx, asn1_type = Type} || {Idx, Type} <-
+ AfterIdxTypes],
test_implied(Indexes, Line),
lists:map(fun (ColumnName) ->
- translate_type(get_asn1_type(ColumnName, MEs,Line))
+ translate_type(get_asn1_type(ColumnName, MEs, Line))
end,
Indexes).
@@ -846,7 +858,11 @@ column_and_defval(#me{oid = Oid, assocList = AssocList}) ->
end.
%% returns: an asn1_type if ColME is an indexfield, otherwise undefined.
-get_asn1_type({implied,ColumnName}, MEs, Line) ->
+get_asn1_type({implied, ColumnName}, MEs, Line) ->
+ ?vtrace("get_asn1_type(implied) -> "
+ "~n ColumnName: ~p"
+ "~n MEs: ~p"
+ "~n Line: ~p", [ColumnName, MEs, Line]),
case lookup(ColumnName, MEs) of
{value,#me{asn1_type=A}} when A#asn1_type.bertype =:=
'OCTET STRING' ->
@@ -859,6 +875,10 @@ get_asn1_type({implied,ColumnName}, MEs, Line) ->
[Shit], Line)
end;
get_asn1_type(ColumnName, MEs, Line) ->
+ ?vtrace("get_asn1_type -> "
+ "~n ColumnName: ~p"
+ "~n MEs: ~p"
+ "~n Line: ~p", [ColumnName, MEs, Line]),
case lookup(ColumnName, MEs) of
{value,ME} -> ME#me.asn1_type;
false -> error("Can't find object ~p. Used as INDEX in table.",
diff --git a/lib/snmp/src/compile/snmpc_mib_gram.yrl b/lib/snmp/src/compile/snmpc_mib_gram.yrl
index 74b9ddaa25..4fd504e34b 100644
--- a/lib/snmp/src/compile/snmpc_mib_gram.yrl
+++ b/lib/snmp/src/compile/snmpc_mib_gram.yrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1996-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
@@ -244,16 +244,36 @@ listofdefinitions -> definition : ['$1'] .
listofdefinitions -> listofdefinitions definition : ['$2' | '$1'].
import -> '$empty' : [].
-import -> 'IMPORTS' imports ';' : '$2'.
-
-imports -> imports_from_one_mib : ['$1'].
-imports -> imports_from_one_mib imports : ['$1' | '$2'].
+import -> 'IMPORTS' imports ';' :
+%% i("import ->"
+%% "~n imports: ~p", ['$2']),
+ '$2'.
+
+imports -> imports_from_one_mib :
+%% i("imports ->"
+%% "~n imports_from_one_mib: ~p", ['$1']),
+ ['$1'].
+imports -> imports_from_one_mib imports :
+%% i("imports ->"
+%% "~n imports_from_one_mib: ~p"
+%% "~n imports: ~p", ['$1', '$2']),
+ ['$1' | '$2'].
imports_from_one_mib -> listofimports 'FROM' variable :
+%% i("imports_from_one_mib ->"
+%% "~n listofimports: ~p"
+%% "~n variable: ~p", ['$1', '$3']),
{{val('$3'), lreverse(imports_from_one_mib, '$1')}, line_of('$2')}.
-listofimports -> import_stuff : ['$1'].
-listofimports -> listofimports ',' import_stuff : ['$3' | '$1'].
+listofimports -> import_stuff :
+%% i("listofimports ->"
+%% "~n import_stuff: ~p", ['$1']),
+ ['$1'].
+listofimports -> listofimports ',' import_stuff :
+%% i("listofimports ->"
+%% "~n listofimports: ~p"
+%% "~n import_stuff: ~p", ['$1', '$3']),
+ ['$3' | '$1'].
import_stuff -> 'OBJECT-TYPE' : {builtin, 'OBJECT-TYPE'}.
import_stuff -> 'TRAP-TYPE' : {builtin, 'TRAP-TYPE'}.
@@ -314,6 +334,8 @@ import_stuff -> 'TDomain'
: ensure_ver(2,'$1'), {builtin, 'TDomain'}.
import_stuff -> 'TAddress'
: ensure_ver(2,'$1'), {builtin, 'TAddress'}.
+import_stuff -> 'BITS'
+ : ensure_ver(2,'$1'), {builtin, 'BITS'}.
traptype -> objectname 'TRAP-TYPE' 'ENTERPRISE' objectname varpart
description referpart implies integer :
@@ -748,7 +770,7 @@ statusv1(Tok) ->
obsolete -> obsolete;
deprecated -> deprecated;
Else -> return_error(line_of(Tok),
- "syntax error before: " ++ atom_to_list(Else))
+ "(statusv1) syntax error before: " ++ atom_to_list(Else))
end.
statusv2(Tok) ->
@@ -757,7 +779,7 @@ statusv2(Tok) ->
deprecated -> deprecated;
obsolete -> obsolete;
Else -> return_error(line_of(Tok),
- "syntax error before: " ++ atom_to_list(Else))
+ "(statusv2) syntax error before: " ++ atom_to_list(Else))
end.
ac_status(Tok) ->
@@ -765,7 +787,7 @@ ac_status(Tok) ->
current -> current;
obsolete -> obsolete;
Else -> return_error(line_of(Tok),
- "syntax error before: " ++ atom_to_list(Else))
+ "(ac_status) syntax error before: " ++ atom_to_list(Else))
end.
accessv1(Tok) ->
@@ -775,7 +797,7 @@ accessv1(Tok) ->
'write-only' -> 'write-only';
'not-accessible' -> 'not-accessible';
Else -> return_error(line_of(Tok),
- "syntax error before: " ++ atom_to_list(Else))
+ "(accessv1) syntax error before: " ++ atom_to_list(Else))
end.
accessv2(Tok) ->
@@ -786,7 +808,7 @@ accessv2(Tok) ->
'read-write' -> 'read-write';
'read-create' -> 'read-create';
Else -> return_error(line_of(Tok),
- "syntax error before: " ++ atom_to_list(Else))
+ "(accessv2) syntax error before: " ++ atom_to_list(Else))
end.
ac_access(Tok) ->
@@ -798,7 +820,7 @@ ac_access(Tok) ->
'read-create' -> 'read-create';
'write-only' -> 'write-only'; % for backward-compatibility only
Else -> return_error(line_of(Tok),
- "syntax error before: " ++ atom_to_list(Else))
+ "(ac_access) syntax error before: " ++ atom_to_list(Else))
end.
%% ---------------------------------------------------------------------
diff --git a/lib/snmp/test/snmp_compiler_test.erl b/lib/snmp/test/snmp_compiler_test.erl
index 257fc47952..1840d37dfd 100644
--- a/lib/snmp/test/snmp_compiler_test.erl
+++ b/lib/snmp/test/snmp_compiler_test.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2003-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
@@ -53,7 +53,9 @@
otp_6150/1,
otp_8574/1,
- otp_8595/1
+ otp_8595/1,
+ otp_10799/1,
+ otp_10808/1
]).
@@ -132,7 +134,7 @@ all() ->
].
groups() ->
- [{tickets, [], [otp_6150, otp_8574, otp_8595]}].
+ [{tickets, [], [otp_6150, otp_8574, otp_8595, otp_10799, otp_10808]}].
init_per_group(_GroupName, Config) ->
Config.
@@ -326,13 +328,14 @@ warnings_as_errors(Config) when is_list(Config) ->
otp_6150(suite) ->
[];
otp_6150(Config) when is_list(Config) ->
- put(tname,otp_6150),
+ put(tname, otp6150),
p("starting with Config: ~p~n", [Config]),
Dir = ?config(case_top_dir, Config),
MibDir = ?config(mib_dir, Config),
MibFile = join(MibDir, "ERICSSON-TOP-MIB.mib"),
- ?line {ok, Mib} = snmpc:compile(MibFile, [{outdir, Dir}, {verbosity, trace}]),
+ ?line {ok, Mib} =
+ snmpc:compile(MibFile, [{outdir, Dir}, {verbosity, trace}]),
io:format("otp_6150 -> Mib: ~n~p~n", [Mib]),
ok.
@@ -342,7 +345,7 @@ otp_6150(Config) when is_list(Config) ->
otp_8574(suite) ->
[];
otp_8574(Config) when is_list(Config) ->
- put(tname,otp_8574),
+ put(tname, otp8574),
p("starting with Config: ~p~n", [Config]),
Dir = ?config(case_top_dir, Config),
@@ -375,7 +378,7 @@ otp_8574(Config) when is_list(Config) ->
otp_8595(suite) ->
[];
otp_8595(Config) when is_list(Config) ->
- put(tname,otp_8595),
+ put(tname, otp8595),
p("starting with Config: ~p~n", [Config]),
Dir = ?config(case_top_dir, Config),
@@ -385,7 +388,43 @@ otp_8595(Config) when is_list(Config) ->
snmpc:compile(MibFile, [{outdir, Dir},
{verbosity, trace},
{group_check, false}]),
- io:format("otp_8595 -> Mib: ~n~p~n", [Mib]),
+ p("Mib: ~n~p~n", [Mib]),
+ ok.
+
+
+%%======================================================================
+
+otp_10799(suite) ->
+ [];
+otp_10799(Config) when is_list(Config) ->
+ put(tname, otp10799),
+ p("starting with Config: ~p~n", [Config]),
+
+ Dir = ?config(case_top_dir, Config),
+ MibDir = ?config(mib_dir, Config),
+ MibFile = join(MibDir, "OTP10799-MIB.mib"),
+ ?line {ok, Mib} =
+ snmpc:compile(MibFile, [{outdir, Dir}, {verbosity, trace}]),
+ p("Mib: ~n~p~n", [Mib]),
+ ok.
+
+
+%%======================================================================
+
+otp_10808(suite) ->
+ [];
+otp_10808(Config) when is_list(Config) ->
+ put(tname, otp10808),
+ p("starting with Config: ~p~n", [Config]),
+
+ Dir = ?config(case_top_dir, Config),
+ MibDir = ?config(mib_dir, Config),
+ MibFile = join(MibDir, "OTP10808-MIB.mib"),
+ ?line {ok, Mib} =
+ snmpc:compile(MibFile, [{outdir, Dir},
+ {verbosity, trace},
+ {group_check, false}]),
+ p("Mib: ~n~p~n", [Mib]),
ok.
diff --git a/lib/snmp/test/snmp_test_data/OTP10799-MIB.mib b/lib/snmp/test/snmp_test_data/OTP10799-MIB.mib
new file mode 100644
index 0000000000..f47bcfd7da
--- /dev/null
+++ b/lib/snmp/test/snmp_test_data/OTP10799-MIB.mib
@@ -0,0 +1,75 @@
+OTP10799-MIB DEFINITIONS ::= BEGIN
+
+IMPORTS
+ MODULE-IDENTITY, OBJECT-TYPE, snmpModules, mib-2, BITS
+ FROM SNMPv2-SMI
+ MODULE-COMPLIANCE, OBJECT-GROUP
+ FROM SNMPv2-CONF
+ ;
+
+otp10799MIB MODULE-IDENTITY
+ LAST-UPDATED "1004210000Z"
+ ORGANIZATION ""
+ CONTACT-INFO
+ ""
+ DESCRIPTION
+ "Test mib for OTP-10799"
+ ::= { snmpModules 1 }
+
+
+-- Administrative assignments ****************************************
+
+otp10799MIBObjects OBJECT IDENTIFIER ::= { otp10799MIB 1 }
+otp10799MIBConformance OBJECT IDENTIFIER ::= { otp10799MIB 2 }
+
+--
+
+test OBJECT IDENTIFIER ::= { mib-2 16 }
+
+bits1 OBJECT-TYPE
+ SYNTAX BITS {
+ b0(0),
+ b1(1),
+ b2(2),
+ b3(3),
+ b4(4),
+ b5(5),
+ b6(6),
+ b7(7)
+ }
+ MAX-ACCESS read-write
+ STATUS current
+ DESCRIPTION
+ ""
+ ::= { test 1 }
+
+-- Conformance Information *******************************************
+
+otp10799MIBCompliances OBJECT IDENTIFIER
+ ::= { otp10799MIBConformance 1 }
+otp10799MIBGroups OBJECT IDENTIFIER
+ ::= { otp10799MIBConformance 2 }
+
+-- Compliance statements
+
+otp10799MIBCompliance MODULE-COMPLIANCE
+ STATUS current
+ DESCRIPTION
+ "The compliance statement for SNMP engines which
+ implement the SNMP-COMMUNITY-MIB."
+
+ MODULE -- this module
+ MANDATORY-GROUPS { otp10799Group }
+
+ ::= { otp10799Compliances 1 }
+
+otp10799Group OBJECT-GROUP
+ OBJECTS {
+ bits1
+ }
+ STATUS current
+ DESCRIPTION
+ "A group."
+ ::= { otp10799MIBGroups 1 }
+
+END
diff --git a/lib/snmp/test/snmp_test_data/OTP10808-MIB.mib b/lib/snmp/test/snmp_test_data/OTP10808-MIB.mib
new file mode 100644
index 0000000000..99c099e316
--- /dev/null
+++ b/lib/snmp/test/snmp_test_data/OTP10808-MIB.mib
@@ -0,0 +1,137 @@
+OTP10808-MIB DEFINITIONS ::= BEGIN
+
+IMPORTS
+ MODULE-IDENTITY, OBJECT-TYPE, enterprises, IpAddress FROM SNMPv2-SMI
+ RowStatus FROM SNMPv2-TC
+ ;
+
+otp10808MIB MODULE-IDENTITY
+ LAST-UPDATED "1004200000Z"
+ ORGANIZATION "Erlang/OTP"
+ CONTACT-INFO "www.erlang.org"
+ DESCRIPTION "The MIB module is used for testing a compiler feature"
+ ::= { otpSnmp 1 }
+
+ericsson OBJECT IDENTIFIER ::= { enterprises 193 }
+otp OBJECT IDENTIFIER ::= { ericsson 19 }
+otpApplications OBJECT IDENTIFIER ::= { otp 3 }
+otpSnmp OBJECT IDENTIFIER ::= { otpApplications 3 }
+
+testMIBObjects OBJECT IDENTIFIER ::= { otp10808MIB 1 }
+
+testMIBObjectGroup OBJECT IDENTIFIER ::= { testMIBObjects 1 }
+
+-- Example Table 1
+
+example-Table1 OBJECT-TYPE
+ SYNTAX SEQUENCE OF ExampleEntry1
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION "Example table 1"
+ ::= { testMIBObjectGroup 1 }
+
+example-Entry1 OBJECT-TYPE
+ SYNTAX ExampleEntry1
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION "Example table 1 entry"
+ INDEX { exampleIndex2, exampleIndex1 }
+ ::= { example-Table1 1 }
+
+ExampleEntry1 ::= SEQUENCE {
+ exampleIndex1 INTEGER,
+ exampleColumn1 OCTET STRING,
+ exampleNotAccessible1 OCTET STRING,
+ exampleRowStatus1 RowStatus
+}
+
+exampleIndex1 OBJECT-TYPE
+ SYNTAX INTEGER (1..100)
+ MAX-ACCESS read-write
+ STATUS current
+ DESCRIPTION "The second index for this entry."
+ ::= { example-Entry1 1 }
+
+exampleColumn1 OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-write
+ STATUS current
+ DESCRIPTION
+ "Example table column"
+ ::= { example-Entry1 2 }
+
+exampleNotAccessible1 OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "Example table column"
+ ::= { example-Entry1 3 }
+
+exampleRowStatus1 OBJECT-TYPE
+ SYNTAX RowStatus
+ MAX-ACCESS read-write
+ STATUS current
+ DESCRIPTION
+ "Example table RowStatus"
+ ::= { example-Entry1 4 }
+
+
+-- Example Table 2
+
+example-Table2 OBJECT-TYPE
+ SYNTAX SEQUENCE OF ExampleEntry2
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION "Example table 2"
+ ::= { testMIBObjectGroup 2 }
+
+example-Entry2 OBJECT-TYPE
+ SYNTAX ExampleEntry2
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION "Example table entry"
+ INDEX { exampleIndex2 }
+ ::= { example-Table2 1 }
+
+ExampleEntry2 ::= SEQUENCE {
+ exampleIndex2 INTEGER,
+ exampleColumn2 OCTET STRING,
+ exampleNotAccessible2 OCTET STRING,
+ exampleRowStatus2 RowStatus
+}
+
+exampleIndex2 OBJECT-TYPE
+ SYNTAX INTEGER (1..100)
+ MAX-ACCESS read-write
+ STATUS current
+ DESCRIPTION
+ "The index for this entry of table 2
+ (and first index of table 1)."
+ ::= { example-Entry2 1 }
+
+exampleColumn2 OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-write
+ STATUS current
+ DESCRIPTION
+ "Example table column"
+ ::= { example-Entry2 2 }
+
+exampleNotAccessible2 OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "Example table column"
+ ::= { example-Entry2 3 }
+
+exampleRowStatus2 OBJECT-TYPE
+ SYNTAX RowStatus
+ MAX-ACCESS read-write
+ STATUS current
+ DESCRIPTION
+ "Example table RowStatus"
+ ::= { example-Entry2 4 }
+
+END
diff --git a/lib/snmp/test/test-mibs/ALARM-MIB.mib b/lib/snmp/test/test-mibs/ALARM-MIB.mib
new file mode 100644
index 0000000000..18e43d4b4b
--- /dev/null
+++ b/lib/snmp/test/test-mibs/ALARM-MIB.mib
@@ -0,0 +1,1214 @@
+ALARM-MIB DEFINITIONS ::= BEGIN
+
+IMPORTS
+ MODULE-IDENTITY, OBJECT-TYPE, NOTIFICATION-TYPE,
+ Integer32, Unsigned32, Gauge32,
+ TimeTicks, Counter32, Counter64,
+ IpAddress, Opaque, mib-2,
+ zeroDotZero
+ FROM SNMPv2-SMI -- [RFC2578]
+ DateAndTime,
+ RowStatus, RowPointer,
+ TEXTUAL-CONVENTION
+ FROM SNMPv2-TC -- [RFC2579]
+ SnmpAdminString
+ FROM SNMP-FRAMEWORK-MIB -- [RFC3411]
+ InetAddressType, InetAddress
+ FROM INET-ADDRESS-MIB -- [RFC3291]
+ MODULE-COMPLIANCE, OBJECT-GROUP,
+ NOTIFICATION-GROUP
+ FROM SNMPv2-CONF -- [RFC2580]
+ ZeroBasedCounter32
+ FROM RMON2-MIB; -- [RFC2021]
+
+ alarmMIB MODULE-IDENTITY
+ LAST-UPDATED "200409090000Z" -- September 09, 2004
+ ORGANIZATION "IETF Distributed Management Working Group"
+ CONTACT-INFO
+ "WG EMail: [email protected]
+ Subscribe: [email protected]
+ http://www.ietf.org/html.charters/disman-charter.html
+
+
+
+
+ Chair: Randy Presuhn
+
+ Editors: Sharon Chisholm
+ Nortel Networks
+ PO Box 3511 Station C
+ Ottawa, Ont. K1Y 4H7
+ Canada
+
+ Dan Romascanu
+ Avaya
+ Atidim Technology Park, Bldg. #3
+ Tel Aviv, 61131
+ Israel
+ Tel: +972-3-645-8414
+ DESCRIPTION
+ "The MIB module describes a generic solution
+ to model alarms and to store the current list
+ of active alarms.
+
+ Copyright (C) The Internet Society (2004). The
+ initial version of this MIB module was published
+ in RFC 3877. For full legal notices see the RFC
+ itself. Supplementary information may be available on:
+ http://www.ietf.org/copyrights/ianamib.html"
+ REVISION "200409090000Z" -- September 09, 2004
+ DESCRIPTION
+ "Initial version, published as RFC 3877."
+ ::= { mib-2 118 }
+
+alarmObjects OBJECT IDENTIFIER ::= { alarmMIB 1 }
+
+alarmNotifications OBJECT IDENTIFIER ::= { alarmMIB 0 }
+
+alarmModel OBJECT IDENTIFIER ::= { alarmObjects 1 }
+
+alarmActive OBJECT IDENTIFIER ::= { alarmObjects 2 }
+
+alarmClear OBJECT IDENTIFIER ::= { alarmObjects 3 }
+
+-- Textual Conventions
+
+ -- ResourceId is intended to be a general textual convention
+ -- that can be used outside of the set of MIBs related to
+ -- Alarm Management.
+
+
+
+
+
+ResourceId ::= TEXTUAL-CONVENTION
+ STATUS current
+ DESCRIPTION
+ "A unique identifier for this resource.
+
+ The type of the resource can be determined by looking
+ at the OID that describes the resource.
+
+ Resources must be identified in a consistent manner.
+ For example, if this resource is an interface, this
+ object MUST point to an ifIndex and if this resource
+ is a physical entity [RFC2737], then this MUST point
+ to an entPhysicalDescr, given that entPhysicalIndex
+ is not accessible. In general, the value is the
+ name of the instance of the first accessible columnar
+ object in the conceptual row of a table that is
+ meaningful for this resource type, which SHOULD
+ be defined in an IETF standard MIB."
+ SYNTAX OBJECT IDENTIFIER
+
+ -- LocalSnmpEngineOrZeroLenStr is intended to be a general
+ -- textual convention that can be used outside of the set of
+ -- MIBs related to Alarm Management.
+
+ LocalSnmpEngineOrZeroLenStr ::= TEXTUAL-CONVENTION
+ STATUS current
+ DESCRIPTION
+ "An SNMP Engine ID or a zero-length string. The
+ instantiation of this textual convention will provide
+ guidance on when this will be an SNMP Engine ID and
+ when it will be a zero lengths string"
+ SYNTAX OCTET STRING (SIZE(0 | 5..32))
+
+-- Alarm Model
+
+alarmModelLastChanged OBJECT-TYPE
+ SYNTAX TimeTicks
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The value of sysUpTime at the time of the last
+ creation, deletion or modification of an entry in
+ the alarmModelTable.
+
+ If the number and content of entries has been unchanged
+ since the last re-initialization of the local network
+ management subsystem, then the value of this object
+ MUST be zero."
+
+
+
+
+ ::= { alarmModel 1 }
+
+alarmModelTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF AlarmModelEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A table of information about possible alarms on the system,
+ and how they have been modelled."
+ ::= { alarmModel 2 }
+
+alarmModelEntry OBJECT-TYPE
+ SYNTAX AlarmModelEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "Entries appear in this table for each possible alarm state.
+ This table MUST be persistent across system reboots."
+ INDEX { alarmListName, alarmModelIndex, alarmModelState }
+ ::= { alarmModelTable 1 }
+
+AlarmModelEntry ::= SEQUENCE {
+ alarmModelIndex Unsigned32,
+ alarmModelState Unsigned32,
+ alarmModelNotificationId OBJECT IDENTIFIER,
+ alarmModelVarbindIndex Unsigned32,
+ alarmModelVarbindValue Integer32,
+ alarmModelDescription SnmpAdminString,
+ alarmModelSpecificPointer RowPointer,
+ alarmModelVarbindSubtree OBJECT IDENTIFIER,
+ alarmModelResourcePrefix OBJECT IDENTIFIER,
+ alarmModelRowStatus RowStatus
+ }
+
+alarmModelIndex OBJECT-TYPE
+ SYNTAX Unsigned32 (1..4294967295)
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "An integer that acts as an alarm Id
+ to uniquely identify each alarm
+ within the named alarm list. "
+ ::= { alarmModelEntry 1 }
+
+alarmModelState OBJECT-TYPE
+ SYNTAX Unsigned32 (1..4294967295)
+ MAX-ACCESS not-accessible
+ STATUS current
+
+
+
+
+ DESCRIPTION
+ "A value of 1 MUST indicate a clear alarm state.
+ The value of this object MUST be less than the
+ alarmModelState of more severe alarm states for
+ this alarm. The value of this object MUST be more
+ than the alarmModelState of less severe alarm states
+ for this alarm."
+ ::= { alarmModelEntry 2 }
+
+alarmModelNotificationId OBJECT-TYPE
+ SYNTAX OBJECT IDENTIFIER
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The NOTIFICATION-TYPE object identifier of this alarm
+ state transition. If there is no notification associated
+ with this alarm state, the value of this object MUST be
+ '0.0'"
+ DEFVAL { zeroDotZero }
+ ::= { alarmModelEntry 3 }
+
+alarmModelVarbindIndex OBJECT-TYPE
+ SYNTAX Unsigned32
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The index into the varbind listing of the notification
+ indicated by alarmModelNotificationId which helps
+ signal that the given alarm has changed state.
+ If there is no applicable varbind, the value of this
+ object MUST be zero.
+
+ Note that the value of alarmModelVarbindIndex acknowledges
+ the existence of the first two obligatory varbinds in
+ the InformRequest-PDU and SNMPv2-Trap-PDU (sysUpTime.0
+ and snmpTrapOID.0). That is, a value of 2 refers to
+ the snmpTrapOID.0.
+
+ If the incoming notification is instead an SNMPv1 Trap-PDU,
+ then an appropriate value for sysUpTime.0 or snmpTrapOID.0
+ shall be determined by using the rules in section 3.1 of
+ [RFC3584]"
+ DEFVAL { 0 }
+ ::= { alarmModelEntry 4 }
+
+alarmModelVarbindValue OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-create
+
+
+
+
+ STATUS current
+ DESCRIPTION
+ "The value that the varbind indicated by
+ alarmModelVarbindIndex takes to indicate
+ that the alarm has entered this state.
+
+ If alarmModelVarbindIndex has a value of 0, so
+ MUST alarmModelVarbindValue.
+ "
+ DEFVAL { 0 }
+ ::= { alarmModelEntry 5 }
+
+alarmModelDescription OBJECT-TYPE
+ SYNTAX SnmpAdminString
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "A brief description of this alarm and state suitable
+ to display to operators."
+ DEFVAL { "" }
+ ::= { alarmModelEntry 6 }
+
+alarmModelSpecificPointer OBJECT-TYPE
+ SYNTAX RowPointer
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "If no additional, model-specific Alarm MIB is supported by
+ the system the value of this object is `0.0'and attempts
+ to set it to any other value MUST be rejected appropriately.
+
+ When a model-specific Alarm MIB is supported, this object
+ MUST refer to the first accessible object in a corresponding
+ row of the model definition in one of these model-specific
+ MIB and attempts to set this object to { 0 0 } or any other
+ value MUST be rejected appropriately."
+ DEFVAL { zeroDotZero }
+ ::= { alarmModelEntry 7 }
+
+ alarmModelVarbindSubtree OBJECT-TYPE
+ SYNTAX OBJECT IDENTIFIER
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The name portion of each VarBind in the notification,
+ in order, is compared to the value of this object.
+ If the name is equal to or a subtree of the value
+ of this object, for purposes of computing the value
+
+
+
+
+ of AlarmActiveResourceID the 'prefix' will be the
+ matching portion, and the 'indexes' will be any
+ remainder. The examination of varbinds ends with
+ the first match. If the value of this object is 0.0,
+ then the first varbind, or in the case of v2, the
+ first varbind after the timestamp and the trap
+ OID, will always be matched.
+ "
+ DEFVAL { zeroDotZero }
+ ::= { alarmModelEntry 8 }
+
+ alarmModelResourcePrefix OBJECT-TYPE
+ SYNTAX OBJECT IDENTIFIER
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The value of AlarmActiveResourceId is computed
+ by appending any indexes extracted in accordance
+ with the description of alarmModelVarbindSubtree
+ onto the value of this object. If this object's
+ value is 0.0, then the 'prefix' extracted is used
+ instead.
+ "
+ DEFVAL { zeroDotZero }
+ ::= { alarmModelEntry 9 }
+
+alarmModelRowStatus OBJECT-TYPE
+ SYNTAX RowStatus
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "Control for creating and deleting entries. Entries may be
+ modified while active. Alarms whose alarmModelRowStatus is
+ not active will not appear in either the alarmActiveTable
+ or the alarmClearTable. Setting this object to notInService
+ cannot be used as an alarm suppression mechanism. Entries
+ that are notInService will disappear as described in RFC2579.
+
+ This row can not be modified while it is being
+ referenced by a value of alarmActiveModelPointer. In these
+ cases, an error of `inconsistentValue' will be returned to
+ the manager.
+
+ This entry may be deleted while it is being
+ referenced by a value of alarmActiveModelPointer. This results
+ in the deletion of this entry and entries in the active alarms
+ referencing this entry via an alarmActiveModelPointer.
+
+
+
+
+
+ As all read-create objects in this table have a DEFVAL clause,
+ there is no requirement that any object be explicitly set
+ before this row can become active. Note that a row consisting
+ only of default values is not very meaningful."
+ ::= { alarmModelEntry 10 }
+
+-- Active Alarm Table --
+
+alarmActiveLastChanged OBJECT-TYPE
+ SYNTAX TimeTicks
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The value of sysUpTime at the time of the last
+ creation or deletion of an entry in the alarmActiveTable.
+ If the number of entries has been unchanged since the
+ last re-initialization of the local network management
+ subsystem, then this object contains a zero value."
+ ::= { alarmActive 1 }
+
+ alarmActiveOverflow OBJECT-TYPE
+ SYNTAX Counter32
+ UNITS "active alarms"
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of active alarms that have not been put into
+ the alarmActiveTable since system restart as a result
+ of extreme resource constraints."
+ ::= { alarmActive 5 }
+
+alarmActiveTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF AlarmActiveEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A table of Active Alarms entries."
+ ::= { alarmActive 2 }
+
+alarmActiveEntry OBJECT-TYPE
+ SYNTAX AlarmActiveEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "Entries appear in this table when alarms are raised. They
+ are removed when the alarm is cleared.
+
+ If under extreme resource constraint the system is unable to
+
+
+
+
+ add any more entries into this table, then the
+ alarmActiveOverflow statistic will be increased by one."
+ INDEX { alarmListName, alarmActiveDateAndTime,
+ alarmActiveIndex }
+ ::= { alarmActiveTable 1 }
+
+AlarmActiveEntry ::= SEQUENCE {
+ alarmListName SnmpAdminString,
+ alarmActiveDateAndTime DateAndTime,
+ alarmActiveIndex Unsigned32,
+ alarmActiveEngineID LocalSnmpEngineOrZeroLenStr,
+ alarmActiveEngineAddressType InetAddressType,
+ alarmActiveEngineAddress InetAddress,
+ alarmActiveContextName SnmpAdminString,
+ alarmActiveVariables Unsigned32,
+ alarmActiveNotificationID OBJECT IDENTIFIER,
+ alarmActiveResourceId ResourceId,
+ alarmActiveDescription SnmpAdminString,
+ alarmActiveLogPointer RowPointer,
+ alarmActiveModelPointer RowPointer,
+ alarmActiveSpecificPointer RowPointer }
+
+alarmListName OBJECT-TYPE
+ SYNTAX SnmpAdminString (SIZE(0..32))
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "The name of the list of alarms. This SHOULD be the same as
+ nlmLogName if the Notification Log MIB [RFC3014] is supported.
+ This SHOULD be the same as, or contain as a prefix, the
+ applicable snmpNotifyFilterProfileName if the
+ SNMP-NOTIFICATION-MIB DEFINITIONS [RFC3413] is supported.
+
+ An implementation may allow multiple named alarm lists, up to
+ some implementation-specific limit (which may be none). A
+ zero-length list name is reserved for creation and deletion
+ by the managed system, and MUST be used as the default log
+ name by systems that do not support named alarm lists."
+ ::= { alarmActiveEntry 1 }
+
+alarmActiveDateAndTime OBJECT-TYPE
+ SYNTAX DateAndTime
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "The local date and time when the error occurred.
+
+ This object facilitates retrieving all instances of
+
+
+
+
+ alarms that have been raised or have changed state
+ since a given point in time.
+
+ Implementations MUST include the offset from UTC,
+ if available. Implementation in environments in which
+ the UTC offset is not available is NOT RECOMMENDED."
+ ::= { alarmActiveEntry 2 }
+
+alarmActiveIndex OBJECT-TYPE
+ SYNTAX Unsigned32 (1..4294967295)
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A strictly monotonically increasing integer which
+ acts as the index of entries within the named alarm
+ list. It wraps back to 1 after it reaches its
+ maximum value."
+ ::= { alarmActiveEntry 3 }
+
+alarmActiveEngineID OBJECT-TYPE
+ SYNTAX LocalSnmpEngineOrZeroLenStr
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The identification of the SNMP engine at which the alarm
+ originated. If the alarm is from an SNMPv1 system this
+ object is a zero length string."
+ ::= { alarmActiveEntry 4 }
+
+alarmActiveEngineAddressType OBJECT-TYPE
+ SYNTAX InetAddressType
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "This object indicates what type of address is stored in
+ the alarmActiveEngineAddress object - IPv4, IPv6, DNS, etc."
+ ::= { alarmActiveEntry 5 }
+
+alarmActiveEngineAddress OBJECT-TYPE
+ SYNTAX InetAddress
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The address of the SNMP engine on which the alarm is
+ occurring.
+
+ This object MUST always be instantiated, even if the list
+ can contain alarms from only one engine."
+
+
+
+
+ ::= { alarmActiveEntry 6 }
+
+alarmActiveContextName OBJECT-TYPE
+ SYNTAX SnmpAdminString (SIZE(0..32))
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The name of the SNMP MIB context from which the alarm came.
+ For SNMPv1 alarms this is the community string from the Trap.
+ Note that care MUST be taken when selecting community
+ strings to ensure that these can be represented as a
+ well-formed SnmpAdminString. Community or Context names
+ that are not well-formed SnmpAdminStrings will be mapped
+ to zero length strings.
+
+ If the alarm's source SNMP engine is known not to support
+ multiple contexts, this object is a zero length string."
+ ::= { alarmActiveEntry 7 }
+
+alarmActiveVariables OBJECT-TYPE
+ SYNTAX Unsigned32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The number of variables in alarmActiveVariableTable for this
+ alarm."
+ ::= { alarmActiveEntry 8 }
+
+alarmActiveNotificationID OBJECT-TYPE
+ SYNTAX OBJECT IDENTIFIER
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The NOTIFICATION-TYPE object identifier of the alarm
+ state transition that is occurring."
+ ::= { alarmActiveEntry 9 }
+
+alarmActiveResourceId OBJECT-TYPE
+ SYNTAX ResourceId
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "This object identifies the resource under alarm.
+
+ If there is no corresponding resource, then
+ the value of this object MUST be 0.0."
+ ::= { alarmActiveEntry 10 }
+
+
+
+
+
+alarmActiveDescription OBJECT-TYPE
+ SYNTAX SnmpAdminString
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "This object provides a textual description of the
+ active alarm. This text is generated dynamically by the
+ notification generator to provide useful information
+ to the human operator. This information SHOULD
+ provide information allowing the operator to locate
+ the resource for which this alarm is being generated.
+ This information is not intended for consumption by
+ automated tools."
+ ::= { alarmActiveEntry 11 }
+
+alarmActiveLogPointer OBJECT-TYPE
+ SYNTAX RowPointer
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "A pointer to the corresponding row in a
+ notification logging MIB where the state change
+ notification for this active alarm is logged.
+ If no log entry applies to this active alarm,
+ then this object MUST have the value of 0.0"
+ ::= { alarmActiveEntry 12 }
+
+alarmActiveModelPointer OBJECT-TYPE
+ SYNTAX RowPointer
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "A pointer to the corresponding row in the
+ alarmModelTable for this active alarm. This
+ points not only to the alarm model being
+ instantiated, but also to the specific alarm
+ state that is active."
+ ::= { alarmActiveEntry 13 }
+
+alarmActiveSpecificPointer OBJECT-TYPE
+ SYNTAX RowPointer
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "If no additional, model-specific, Alarm MIB is supported by
+ the system this object is `0.0'. When a model-specific Alarm
+ MIB is supported, this object is the instance pointer to the
+ specific model-specific active alarm list."
+
+
+
+
+ ::= { alarmActiveEntry 14 }
+
+-- Active Alarm Variable Table --
+
+alarmActiveVariableTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF AlarmActiveVariableEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A table of variables to go with active alarm entries."
+ ::= { alarmActive 3 }
+
+alarmActiveVariableEntry OBJECT-TYPE
+ SYNTAX AlarmActiveVariableEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "Entries appear in this table when there are variables in
+ the varbind list of a corresponding alarm in
+ alarmActiveTable.
+
+ Entries appear in this table as though
+ the trap/notification had been transported using a
+ SNMPv2-Trap-PDU, as defined in [RFC3416] - i.e., the
+ alarmActiveVariableIndex 1 will always be sysUpTime
+ and alarmActiveVariableIndex 2 will always be
+ snmpTrapOID.
+
+ If the incoming notification is instead an SNMPv1 Trap-PDU and
+ the value of alarmModelVarbindIndex is 1 or 2, an appropriate
+ value for sysUpTime.0 or snmpTrapOID.0 shall be determined
+ by using the rules in section 3.1 of [RFC3584]."
+ INDEX { alarmListName, alarmActiveIndex,
+ alarmActiveVariableIndex }
+ ::= { alarmActiveVariableTable 1 }
+
+AlarmActiveVariableEntry ::= SEQUENCE {
+ alarmActiveVariableIndex Unsigned32,
+ alarmActiveVariableID OBJECT IDENTIFIER,
+ alarmActiveVariableValueType INTEGER,
+ alarmActiveVariableCounter32Val Counter32,
+ alarmActiveVariableUnsigned32Val Unsigned32,
+ alarmActiveVariableTimeTicksVal TimeTicks,
+ alarmActiveVariableInteger32Val Integer32,
+ alarmActiveVariableOctetStringVal OCTET STRING,
+ alarmActiveVariableIpAddressVal IpAddress,
+ alarmActiveVariableOidVal OBJECT IDENTIFIER,
+ alarmActiveVariableCounter64Val Counter64,
+
+
+
+
+ alarmActiveVariableOpaqueVal Opaque }
+
+alarmActiveVariableIndex OBJECT-TYPE
+ SYNTAX Unsigned32 (1..4294967295)
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A strictly monotonically increasing integer, starting at
+ 1 for a given alarmActiveIndex, for indexing variables
+ within the active alarm variable list. "
+ ::= { alarmActiveVariableEntry 1 }
+
+alarmActiveVariableID OBJECT-TYPE
+ SYNTAX OBJECT IDENTIFIER
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The alarm variable's object identifier."
+ ::= { alarmActiveVariableEntry 2 }
+
+alarmActiveVariableValueType OBJECT-TYPE
+ SYNTAX INTEGER {
+ counter32(1),
+ unsigned32(2),
+ timeTicks(3),
+ integer32(4),
+ ipAddress(5),
+ octetString(6),
+ objectId(7),
+ counter64(8),
+ opaque(9)
+ }
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The type of the value. One and only one of the value
+ objects that follow is used for a given row in this table,
+ based on this type."
+ ::= { alarmActiveVariableEntry 3 }
+
+alarmActiveVariableCounter32Val OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The value when alarmActiveVariableType is 'counter32'."
+ ::= { alarmActiveVariableEntry 4 }
+
+
+
+
+
+alarmActiveVariableUnsigned32Val OBJECT-TYPE
+ SYNTAX Unsigned32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The value when alarmActiveVariableType is 'unsigned32'."
+ ::= { alarmActiveVariableEntry 5 }
+
+alarmActiveVariableTimeTicksVal OBJECT-TYPE
+ SYNTAX TimeTicks
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The value when alarmActiveVariableType is 'timeTicks'."
+ ::= { alarmActiveVariableEntry 6 }
+
+alarmActiveVariableInteger32Val OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The value when alarmActiveVariableType is 'integer32'."
+ ::= { alarmActiveVariableEntry 7 }
+
+alarmActiveVariableOctetStringVal OBJECT-TYPE
+ SYNTAX OCTET STRING (SIZE(0..65535))
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The value when alarmActiveVariableType is 'octetString'."
+ ::= { alarmActiveVariableEntry 8 }
+
+alarmActiveVariableIpAddressVal OBJECT-TYPE
+ SYNTAX IpAddress
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The value when alarmActiveVariableType is 'ipAddress'."
+ ::= { alarmActiveVariableEntry 9 }
+
+alarmActiveVariableOidVal OBJECT-TYPE
+ SYNTAX OBJECT IDENTIFIER
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The value when alarmActiveVariableType is 'objectId'."
+ ::= { alarmActiveVariableEntry 10 }
+
+
+
+
+
+alarmActiveVariableCounter64Val OBJECT-TYPE
+ SYNTAX Counter64
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The value when alarmActiveVariableType is 'counter64'."
+ ::= { alarmActiveVariableEntry 11 }
+
+alarmActiveVariableOpaqueVal OBJECT-TYPE
+ SYNTAX Opaque
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The value when alarmActiveVariableType is 'opaque'.
+
+ Note that although RFC2578 [RFC2578] forbids the use
+ of Opaque in 'standard' MIB modules, this particular
+ usage is driven by the need to be able to accurately
+ represent any well-formed notification, and justified
+ by the need for backward compatibility."
+ ::= { alarmActiveVariableEntry 12 }
+
+-- Statistics --
+
+alarmActiveStatsTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF AlarmActiveStatsEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "This table represents the alarm statistics
+ information."
+ ::= { alarmActive 4 }
+
+alarmActiveStatsEntry OBJECT-TYPE
+ SYNTAX AlarmActiveStatsEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "Statistics on the current active alarms."
+ INDEX { alarmListName }
+
+ ::= { alarmActiveStatsTable 1 }
+
+AlarmActiveStatsEntry ::=
+ SEQUENCE {
+ alarmActiveStatsActiveCurrent Gauge32,
+ alarmActiveStatsActives ZeroBasedCounter32,
+ alarmActiveStatsLastRaise TimeTicks,
+
+
+
+
+ alarmActiveStatsLastClear TimeTicks
+ }
+
+alarmActiveStatsActiveCurrent OBJECT-TYPE
+ SYNTAX Gauge32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The total number of currently active alarms on the system."
+ ::= { alarmActiveStatsEntry 1 }
+
+alarmActiveStatsActives OBJECT-TYPE
+ SYNTAX ZeroBasedCounter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The total number of active alarms since system restarted."
+ ::= { alarmActiveStatsEntry 2 }
+
+alarmActiveStatsLastRaise OBJECT-TYPE
+ SYNTAX TimeTicks
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The value of sysUpTime at the time of the last
+ alarm raise for this alarm list.
+ If no alarm raises have occurred since the
+ last re-initialization of the local network management
+ subsystem, then this object contains a zero value."
+ ::= { alarmActiveStatsEntry 3 }
+
+alarmActiveStatsLastClear OBJECT-TYPE
+ SYNTAX TimeTicks
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The value of sysUpTime at the time of the last
+ alarm clear for this alarm list.
+ If no alarm clears have occurred since the
+ last re-initialization of the local network management
+ subsystem, then this object contains a zero value."
+ ::= { alarmActiveStatsEntry 4 }
+
+-- Alarm Clear
+
+alarmClearMaximum OBJECT-TYPE
+ SYNTAX Unsigned32
+ MAX-ACCESS read-write
+
+
+
+
+ STATUS current
+ DESCRIPTION
+ "This object specifies the maximum number of cleared
+ alarms to store in the alarmClearTable. When this
+ number is reached, the cleared alarms with the
+ earliest clear time will be removed from the table."
+ ::= { alarmClear 1 }
+
+alarmClearTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF AlarmClearEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "This table contains information on
+ cleared alarms."
+ ::= { alarmClear 2 }
+
+alarmClearEntry OBJECT-TYPE
+ SYNTAX AlarmClearEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "Information on a cleared alarm."
+ INDEX { alarmListName, alarmClearDateAndTime,
+alarmClearIndex }
+
+ ::= { alarmClearTable 1 }
+
+AlarmClearEntry ::=
+ SEQUENCE {
+ alarmClearIndex Unsigned32,
+ alarmClearDateAndTime DateAndTime,
+ alarmClearEngineID LocalSnmpEngineOrZeroLenStr,
+ alarmClearEngineAddressType InetAddressType,
+ alarmClearEngineAddress InetAddress,
+ alarmClearContextName SnmpAdminString,
+ alarmClearNotificationID OBJECT IDENTIFIER,
+ alarmClearResourceId ResourceId,
+ alarmClearLogIndex Unsigned32,
+ alarmClearModelPointer RowPointer
+ }
+
+alarmClearIndex OBJECT-TYPE
+ SYNTAX Unsigned32 (1..4294967295)
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "An integer which acts as the index of entries within
+
+
+
+
+ the named alarm list. It wraps back to 1 after it
+ reaches its maximum value.
+
+ This object has the same value as the alarmActiveIndex that
+ this alarm instance had when it was active."
+ ::= { alarmClearEntry 1 }
+
+alarmClearDateAndTime OBJECT-TYPE
+ SYNTAX DateAndTime
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "The local date and time when the alarm cleared.
+
+ This object facilitates retrieving all instances of
+ alarms that have been cleared since a given point in time.
+
+ Implementations MUST include the offset from UTC,
+ if available. Implementation in environments in which
+ the UTC offset is not available is NOT RECOMMENDED."
+ ::= { alarmClearEntry 2 }
+
+alarmClearEngineID OBJECT-TYPE
+ SYNTAX LocalSnmpEngineOrZeroLenStr
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The identification of the SNMP engine at which the alarm
+ originated. If the alarm is from an SNMPv1 system this
+ object is a zero length string."
+ ::= { alarmClearEntry 3 }
+
+alarmClearEngineAddressType OBJECT-TYPE
+ SYNTAX InetAddressType
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "This object indicates what type of address is stored in
+ the alarmActiveEngineAddress object - IPv4, IPv6, DNS, etc."
+ ::= { alarmClearEntry 4 }
+
+alarmClearEngineAddress OBJECT-TYPE
+ SYNTAX InetAddress
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The Address of the SNMP engine on which the alarm was
+ occurring. This is used to identify the source of an SNMPv1
+
+
+
+
+ trap, since an alarmActiveEngineId cannot be extracted from the
+ SNMPv1 trap PDU.
+
+ This object MUST always be instantiated, even if the list
+ can contain alarms from only one engine."
+ ::= { alarmClearEntry 5 }
+
+alarmClearContextName OBJECT-TYPE
+ SYNTAX SnmpAdminString (SIZE(0..32))
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The name of the SNMP MIB context from which the alarm came.
+ For SNMPv1 traps this is the community string from the Trap.
+ Note that care needs to be taken when selecting community
+ strings to ensure that these can be represented as a
+ well-formed SnmpAdminString. Community or Context names
+ that are not well-formed SnmpAdminStrings will be mapped
+ to zero length strings.
+
+ If the alarm's source SNMP engine is known not to support
+ multiple contexts, this object is a zero length string."
+ ::= { alarmClearEntry 6 }
+
+alarmClearNotificationID OBJECT-TYPE
+ SYNTAX OBJECT IDENTIFIER
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The NOTIFICATION-TYPE object identifier of the alarm
+ clear."
+ ::= { alarmClearEntry 7 }
+
+alarmClearResourceId OBJECT-TYPE
+ SYNTAX ResourceId
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "This object identifies the resource that was under alarm.
+
+ If there is no corresponding resource, then
+ the value of this object MUST be 0.0."
+ ::= { alarmClearEntry 8 }
+
+alarmClearLogIndex OBJECT-TYPE
+ SYNTAX Unsigned32 (0..4294967295)
+ MAX-ACCESS read-only
+ STATUS current
+
+
+
+
+ DESCRIPTION
+ "This number MUST be the same as the log index of the
+ applicable row in the notification log MIB, if it exists.
+ If no log index applies to the trap, then this object
+ MUST have the value of 0."
+ ::= { alarmClearEntry 9 }
+
+alarmClearModelPointer OBJECT-TYPE
+ SYNTAX RowPointer
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "A pointer to the corresponding row in the
+ alarmModelTable for this cleared alarm."
+ ::= { alarmClearEntry 10 }
+
+-- Notifications
+
+alarmActiveState NOTIFICATION-TYPE
+ OBJECTS { alarmActiveModelPointer,
+ alarmActiveResourceId }
+ STATUS current
+ DESCRIPTION
+ "An instance of the alarm indicated by
+ alarmActiveModelPointer has been raised
+ against the entity indicated by
+ alarmActiveResourceId.
+
+ The agent must throttle the generation of
+ consecutive alarmActiveState traps so that there is at
+ least a two-second gap between traps of this
+ type against the same alarmActiveModelPointer and
+ alarmActiveResourceId. When traps are throttled,
+ they are dropped, not queued for sending at a future time.
+
+ A management application should periodically check
+ the value of alarmActiveLastChanged to detect any
+ missed alarmActiveState notification-events, e.g.,
+ due to throttling or transmission loss."
+ ::= { alarmNotifications 2 }
+
+alarmClearState NOTIFICATION-TYPE
+ OBJECTS { alarmActiveModelPointer,
+ alarmActiveResourceId }
+ STATUS current
+ DESCRIPTION
+ "An instance of the alarm indicated by
+ alarmActiveModelPointer has been cleared against
+
+
+
+
+ the entity indicated by alarmActiveResourceId.
+
+ The agent must throttle the generation of
+ consecutive alarmActiveClear traps so that there is at
+ least a two-second gap between traps of this
+ type against the same alarmActiveModelPointer and
+ alarmActiveResourceId. When traps are throttled,
+ they are dropped, not queued for sending at a future time.
+
+ A management application should periodically check
+ the value of alarmActiveLastChanged to detect any
+ missed alarmClearState notification-events, e.g.,
+ due to throttling or transmission loss."
+ ::= { alarmNotifications 3 }
+
+-- Conformance
+
+alarmConformance OBJECT IDENTIFIER ::= { alarmMIB 2 }
+
+alarmCompliances OBJECT IDENTIFIER ::= { alarmConformance 1 }
+
+alarmCompliance MODULE-COMPLIANCE
+ STATUS current
+ DESCRIPTION
+ "The compliance statement for systems supporting
+ the Alarm MIB."
+ MODULE -- this module
+ MANDATORY-GROUPS {
+ alarmActiveGroup,
+ alarmModelGroup
+ }
+ GROUP alarmActiveStatsGroup
+ DESCRIPTION
+ "This group is optional."
+ GROUP alarmClearGroup
+ DESCRIPTION
+ "This group is optional."
+ GROUP alarmNotificationsGroup
+ DESCRIPTION
+ "This group is optional."
+ ::= { alarmCompliances 1 }
+
+alarmGroups OBJECT IDENTIFIER ::= { alarmConformance 2 }
+
+alarmModelGroup OBJECT-GROUP
+ OBJECTS {
+ alarmModelLastChanged,
+ alarmModelNotificationId,
+
+
+
+
+ alarmModelVarbindIndex,
+ alarmModelVarbindValue,
+ alarmModelDescription,
+ alarmModelSpecificPointer,
+ alarmModelVarbindSubtree,
+ alarmModelResourcePrefix,
+ alarmModelRowStatus
+ }
+ STATUS current
+ DESCRIPTION
+ "Alarm model group."
+ ::= { alarmGroups 1}
+
+alarmActiveGroup OBJECT-GROUP
+ OBJECTS {
+ alarmActiveLastChanged,
+ alarmActiveOverflow,
+ alarmActiveEngineID,
+ alarmActiveEngineAddressType,
+ alarmActiveEngineAddress,
+ alarmActiveContextName,
+ alarmActiveVariables,
+ alarmActiveNotificationID,
+ alarmActiveResourceId,
+ alarmActiveDescription,
+ alarmActiveLogPointer,
+ alarmActiveModelPointer,
+ alarmActiveSpecificPointer,
+ alarmActiveVariableID,
+ alarmActiveVariableValueType,
+ alarmActiveVariableCounter32Val,
+ alarmActiveVariableUnsigned32Val,
+ alarmActiveVariableTimeTicksVal,
+ alarmActiveVariableInteger32Val,
+ alarmActiveVariableOctetStringVal,
+ alarmActiveVariableIpAddressVal,
+ alarmActiveVariableOidVal,
+ alarmActiveVariableCounter64Val,
+ alarmActiveVariableOpaqueVal
+ }
+ STATUS current
+ DESCRIPTION
+ "Active Alarm list group."
+ ::= { alarmGroups 2}
+
+ alarmActiveStatsGroup OBJECT-GROUP
+ OBJECTS {
+ alarmActiveStatsActives,
+
+
+
+
+ alarmActiveStatsActiveCurrent,
+ alarmActiveStatsLastRaise,
+ alarmActiveStatsLastClear
+ }
+ STATUS current
+ DESCRIPTION
+ "Active alarm summary group."
+ ::= { alarmGroups 3}
+
+alarmClearGroup OBJECT-GROUP
+ OBJECTS {
+ alarmClearMaximum,
+ alarmClearEngineID,
+ alarmClearEngineAddressType,
+ alarmClearEngineAddress,
+ alarmClearContextName,
+ alarmClearNotificationID,
+ alarmClearResourceId,
+ alarmClearLogIndex,
+ alarmClearModelPointer
+ }
+ STATUS current
+ DESCRIPTION
+ "Cleared alarm group."
+ ::= { alarmGroups 4}
+
+alarmNotificationsGroup NOTIFICATION-GROUP
+ NOTIFICATIONS { alarmActiveState, alarmClearState }
+ STATUS current
+ DESCRIPTION
+ "The collection of notifications that can be used to
+ model alarms for faults lacking pre-existing
+ notification definitions."
+ ::= { alarmGroups 6 }
+
+END
diff --git a/lib/snmp/test/test-mibs/RFC1271-MIB.mib b/lib/snmp/test/test-mibs/RFC1271-MIB.mib
index 25778dede8..b1b3367667 100644
--- a/lib/snmp/test/test-mibs/RFC1271-MIB.mib
+++ b/lib/snmp/test/test-mibs/RFC1271-MIB.mib
@@ -3,7 +3,8 @@
IMPORTS
Counter FROM RFC1155-SMI
mib-2,DisplayString FROM RFC1213-MIB
- OBJECT-TYPE FROM RFC-1212;
+ OBJECT-TYPE FROM RFC-1212
+ TimeTicks FROM SNMPv2-SMI;
-- This MIB module uses the extended OBJECT-TYPE macro as
-- defined in [9].
diff --git a/lib/snmp/test/test-mibs/RMON2-MIB.mib b/lib/snmp/test/test-mibs/RMON2-MIB.mib
index 827bb38ff9..50c7e6657a 100644
--- a/lib/snmp/test/test-mibs/RMON2-MIB.mib
+++ b/lib/snmp/test/test-mibs/RMON2-MIB.mib
@@ -1,7 +1,7 @@
RMON2-MIB DEFINITIONS ::= BEGIN
IMPORTS
MODULE-IDENTITY, OBJECT-TYPE, Counter32, Integer32,
- Gauge32, IpAddress, TimeTicks FROM SNMPv2-SMI
+ Gauge32, IpAddress, TimeTicks, BITS FROM SNMPv2-SMI
TEXTUAL-CONVENTION, RowStatus, DisplayString, TimeStamp
FROM SNMPv2-TC
MODULE-COMPLIANCE, OBJECT-GROUP FROM SNMPv2-CONF
diff --git a/lib/snmp/vsn.mk b/lib/snmp/vsn.mk
index 8145e415f3..fb7aa52402 100644
--- a/lib/snmp/vsn.mk
+++ b/lib/snmp/vsn.mk
@@ -2,7 +2,7 @@
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2012. All Rights Reserved.
+# Copyright Ericsson AB 1997-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
@@ -18,6 +18,6 @@
# %CopyrightEnd%
APPLICATION = snmp
-SNMP_VSN = 4.23
+SNMP_VSN = 4.23.1
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(SNMP_VSN)$(PRE_VSN)"
diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl
index deae9640f5..12505b33d1 100644
--- a/lib/stdlib/src/erl_lint.erl
+++ b/lib/stdlib/src/erl_lint.erl
@@ -152,8 +152,6 @@ format_error({attribute,A}) ->
io_lib:format("attribute '~w' after function definitions", [A]);
format_error({missing_qlc_hrl,A}) ->
io_lib:format("qlc:q/~w called, but \"qlc.hrl\" not included", [A]);
-format_error({redefine_import,{bif,{F,A},M}}) ->
- io_lib:format("function ~w/~w already auto-imported from ~w", [F,A,M]);
format_error({redefine_import,{{F,A},M}}) ->
io_lib:format("function ~w/~w already imported from ~w", [F,A,M]);
format_error({bad_inline,{F,A}}) ->
@@ -222,8 +220,6 @@ format_error({removed, MFA, String}) when is_list(String) ->
io_lib:format("~s: ~s", [format_mfa(MFA), String]);
format_error({obsolete_guard, {F, A}}) ->
io_lib:format("~p/~p obsolete", [F, A]);
-format_error({reserved_for_future,K}) ->
- io_lib:format("atom ~w: future reserved keyword - rename or quote", [K]);
format_error({too_many_arguments,Arity}) ->
io_lib:format("too many arguments (~w) - "
"maximum allowed is ~w", [Arity,?MAX_ARGUMENTS]);
@@ -236,11 +232,6 @@ format_error({illegal_guard_local_call, {F,A}}) ->
io_lib:format("call to local/imported function ~w/~w is illegal in guard",
[F,A]);
format_error(illegal_guard_expr) -> "illegal guard expression";
-%% --- exports ---
-format_error({explicit_export,F,A}) ->
- io_lib:format("in this release, the call to ~w/~w must be written "
- "like this: erlang:~w/~w",
- [F,A,F,A]);
%% --- records ---
format_error({undefined_record,T}) ->
io_lib:format("record ~w undefined", [T]);
@@ -278,8 +269,6 @@ format_error({variable_in_record_def,V}) ->
%% --- binaries ---
format_error({undefined_bittype,Type}) ->
io_lib:format("bit type ~w undefined", [Type]);
-format_error({bittype_mismatch,T1,T2,What}) ->
- io_lib:format("bit type mismatch (~s) between ~p and ~p", [What,T1,T2]);
format_error(bittype_unit) ->
"a bit unit size must not be specified unless a size is specified too";
format_error(illegal_bitsize) ->
@@ -1798,11 +1787,9 @@ gexpr({call,Line,{atom,_La,F},As}, Vt, St0) ->
%% BifClash - Function called in guard
case erl_internal:guard_bif(F, A) andalso no_guard_bif_clash(St1,{F,A}) of
true ->
- %% Also check that it is auto-imported.
- case erl_internal:bif(F, A) of
- true -> {Asvt,St1};
- false -> {Asvt,add_error(Line, {explicit_export,F,A}, St1)}
- end;
+ %% Assert that it is auto-imported.
+ true = erl_internal:bif(F, A),
+ {Asvt,St1};
false ->
case is_local_function(St1#lint.locals,{F,A}) orelse
is_imported_function(St1#lint.imports,{F,A}) of
diff --git a/lib/stdlib/src/eval_bits.erl b/lib/stdlib/src/eval_bits.erl
index f40904df1c..e49cbc1fd1 100644
--- a/lib/stdlib/src/eval_bits.erl
+++ b/lib/stdlib/src/eval_bits.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
+%% Copyright Ericsson AB 1999-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
@@ -67,7 +67,8 @@ expr_grp([], Bs0, _Lf, Acc) ->
{value,Acc,Bs0}.
eval_field({bin_element, _, {string, _, S}, default, default}, Bs0, _Fun) ->
- {list_to_binary(S),Bs0};
+ Latin1 = [C band 16#FF || C <- S],
+ {list_to_binary(Latin1),Bs0};
eval_field({bin_element, Line, {string, _, S}, Size0, Options0}, Bs, _Fun) ->
{_Size,[Type,_Unit,_Sign,Endian]} =
make_bit_type(Line, Size0, Options0),
@@ -162,8 +163,10 @@ bin_gen([], Bin, _Bs0, _BBs0, _Mfun, _Efun, false) ->
bin_gen_field({bin_element,_,{string,_,S},default,default},
Bin, Bs, BBs, _Mfun, _Efun) ->
- Bits = list_to_binary(S),
- Size = byte_size(Bits),
+ Bits = try list_to_binary(S)
+ catch _:_ -> <<>>
+ end,
+ Size = length(S),
case Bin of
<<Bits:Size/binary,Rest/bitstring>> ->
{match,Bs,BBs,Rest};
@@ -172,16 +175,42 @@ bin_gen_field({bin_element,_,{string,_,S},default,default},
_ ->
done
end;
+bin_gen_field({bin_element,Line,{string,SLine,S},Size0,Options0},
+ Bin0, Bs0, BBs0, Mfun, Efun) ->
+ {Size1, [Type,{unit,Unit},Sign,Endian]} =
+ make_bit_type(Line, Size0, Options0),
+ match_check_size(Mfun, Size1, BBs0),
+ {value, Size, _BBs} = Efun(Size1, BBs0),
+ F = fun(C, Bin, Bs, BBs) ->
+ bin_gen_field1(Bin, Type, Size, Unit, Sign, Endian,
+ {integer,SLine,C}, Bs, BBs, Mfun)
+ end,
+ bin_gen_field_string(S, Bin0, Bs0, BBs0, F);
bin_gen_field({bin_element,Line,VE,Size0,Options0},
Bin, Bs0, BBs0, Mfun, Efun) ->
{Size1, [Type,{unit,Unit},Sign,Endian]} =
make_bit_type(Line, Size0, Options0),
V = erl_eval:partial_eval(VE),
+ NewV = coerce_to_float(V, Type),
match_check_size(Mfun, Size1, BBs0),
{value, Size, _BBs} = Efun(Size1, BBs0),
+ bin_gen_field1(Bin, Type, Size, Unit, Sign, Endian, NewV, Bs0, BBs0, Mfun).
+
+bin_gen_field_string([], Rest, Bs, BBs, _F) ->
+ {match,Bs,BBs,Rest};
+bin_gen_field_string([C|Cs], Bin0, Bs0, BBs0, Fun) ->
+ case Fun(C, Bin0, Bs0, BBs0) of
+ {match,Bs,BBs,Rest} ->
+ bin_gen_field_string(Cs, Rest, Bs, BBs, Fun);
+ {nomatch,Rest} ->
+ {nomatch,Rest};
+ done ->
+ done
+ end.
+
+bin_gen_field1(Bin, Type, Size, Unit, Sign, Endian, NewV, Bs0, BBs0, Mfun) ->
case catch get_value(Bin, Type, Size, Unit, Sign, Endian) of
{Val,<<_/bitstring>>=Rest} ->
- NewV = coerce_to_float(V, Type),
case catch Mfun(match, {NewV,Val,Bs0}) of
{match,Bs} ->
BBs = add_bin_binding(Mfun, NewV, Bs, BBs0),
@@ -223,20 +252,41 @@ match_bits_1([F|Fs], Bits0, Bs0, BBs0, Mfun, Efun) ->
match_field_1({bin_element,_,{string,_,S},default,default},
Bin, Bs, BBs, _Mfun, _Efun) ->
- Bits = list_to_binary(S),
+ Bits = list_to_binary(S), % fails if there are characters > 255
Size = byte_size(Bits),
<<Bits:Size/binary,Rest/binary-unit:1>> = Bin,
{Bs,BBs,Rest};
+match_field_1({bin_element,Line,{string,SLine,S},Size0,Options0},
+ Bin0, Bs0, BBs0, Mfun, Efun) ->
+ {Size1, [Type,{unit,Unit},Sign,Endian]} =
+ make_bit_type(Line, Size0, Options0),
+ Size2 = erl_eval:partial_eval(Size1),
+ match_check_size(Mfun, Size2, BBs0),
+ {value, Size, _BBs} = Efun(Size2, BBs0),
+ F = fun(C, Bin, Bs, BBs) ->
+ match_field(Bin, Type, Size, Unit, Sign, Endian,
+ {integer,SLine,C}, Bs, BBs, Mfun)
+ end,
+ match_field_string(S, Bin0, Bs0, BBs0, F);
match_field_1({bin_element,Line,VE,Size0,Options0},
Bin, Bs0, BBs0, Mfun, Efun) ->
{Size1, [Type,{unit,Unit},Sign,Endian]} =
make_bit_type(Line, Size0, Options0),
V = erl_eval:partial_eval(VE),
+ NewV = coerce_to_float(V, Type),
Size2 = erl_eval:partial_eval(Size1),
match_check_size(Mfun, Size2, BBs0),
{value, Size, _BBs} = Efun(Size2, BBs0),
+ match_field(Bin, Type, Size, Unit, Sign, Endian, NewV, Bs0, BBs0, Mfun).
+
+match_field_string([], Rest, Bs, BBs, _Fun) ->
+ {Bs,BBs,Rest};
+match_field_string([C|Cs], Bin0, Bs0, BBs0, Fun) ->
+ {Bs,BBs,Bin} = Fun(C, Bin0, Bs0, BBs0),
+ match_field_string(Cs, Bin, Bs, BBs, Fun).
+
+match_field(Bin, Type, Size, Unit, Sign, Endian, NewV, Bs0, BBs0, Mfun) ->
{Val,Rest} = get_value(Bin, Type, Size, Unit, Sign, Endian),
- NewV = coerce_to_float(V, Type),
{match,Bs} = Mfun(match, {NewV,Val,Bs0}),
BBs = add_bin_binding(Mfun, NewV, Bs, BBs0),
{Bs,BBs,Rest}.
diff --git a/lib/stdlib/src/shell.erl b/lib/stdlib/src/shell.erl
index 203d2a4f76..0cd408204e 100644
--- a/lib/stdlib/src/shell.erl
+++ b/lib/stdlib/src/shell.erl
@@ -185,7 +185,7 @@ server(StartSync) ->
%% Check if we're in user restricted mode.
RShErr =
case application:get_env(stdlib, restricted_shell) of
- {ok,RShMod} ->
+ {ok,RShMod} when is_atom(RShMod) ->
io:fwrite(<<"Restricted ">>, []),
case code:ensure_loaded(RShMod) of
{module,RShMod} ->
@@ -193,6 +193,8 @@ server(StartSync) ->
{error,What} ->
{RShMod,What}
end;
+ {ok, Term} ->
+ {Term,not_an_atom};
undefined ->
undefined
end,
diff --git a/lib/stdlib/test/erl_eval_SUITE.erl b/lib/stdlib/test/erl_eval_SUITE.erl
index 04d49770cb..d3c91c7326 100644
--- a/lib/stdlib/test/erl_eval_SUITE.erl
+++ b/lib/stdlib/test/erl_eval_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1998-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,6 +37,7 @@
otp_6977/1,
otp_7550/1,
otp_8133/1,
+ otp_10622/1,
funs/1,
try_catch/1,
eval_expr_5/1,
@@ -79,7 +80,7 @@ all() ->
pattern_expr, match_bin, guard_3, guard_4, lc,
simple_cases, unary_plus, apply_atom, otp_5269,
otp_6539, otp_6543, otp_6787, otp_6977, otp_7550,
- otp_8133, funs, try_catch, eval_expr_5, zero_width].
+ otp_8133, otp_10622, funs, try_catch, eval_expr_5, zero_width].
groups() ->
[].
@@ -960,6 +961,7 @@ otp_8133(Config) when is_list(Config) ->
E = fun(N) ->
if
is_integer(N) -> <<N/integer>>;
+
true -> erlang:error(foo)
end
end,
@@ -980,6 +982,48 @@ otp_8133(Config) when is_list(Config) ->
ok),
ok.
+otp_10622(doc) ->
+ ["OTP-10622. Bugs."];
+otp_10622(suite) ->
+ [];
+otp_10622(Config) when is_list(Config) ->
+ check(fun() -> <<0>> = <<"\x{400}">> end,
+ "<<0>> = <<\"\\x{400}\">>. ",
+ <<0>>),
+ check(fun() -> <<"\x{aa}ff"/utf8>> = <<"\x{aa}ff"/utf8>> end,
+ "<<\"\\x{aa}ff\"/utf8>> = <<\"\\x{aa}ff\"/utf8>>. ",
+ <<"�\xaaff">>),
+ %% The same bug as last example:
+ check(fun() -> case <<"foo"/utf8>> of
+ <<"foo"/utf8>> -> true
+ end
+ end,
+ "case <<\"foo\"/utf8>> of <<\"foo\"/utf8>> -> true end.",
+ true),
+ check(fun() -> <<"\x{400}"/utf8>> = <<"\x{400}"/utf8>> end,
+ "<<\"\\x{400}\"/utf8>> = <<\"\\x{400}\"/utf8>>. ",
+ <<208,128>>),
+ error_check("<<\"\\x{aaa}\">> = <<\"\\x{aaa}\">>.",
+ {badmatch,<<"\xaa">>}),
+
+ check(fun() -> [a || <<"\x{aaa}">> <= <<2703:16>>] end,
+ "[a || <<\"\\x{aaa}\">> <= <<2703:16>>]. ",
+ []),
+ check(fun() -> [a || <<"\x{aa}"/utf8>> <= <<"\x{aa}"/utf8>>] end,
+ "[a || <<\"\\x{aa}\"/utf8>> <= <<\"\\x{aa}\"/utf8>>]. ",
+ [a]),
+ check(fun() -> [a || <<"\x{aa}x"/utf8>> <= <<"\x{aa}y"/utf8>>] end,
+ "[a || <<\"\\x{aa}x\"/utf8>> <= <<\"\\x{aa}y\"/utf8>>]. ",
+ []),
+ check(fun() -> [a || <<"\x{aaa}">> <= <<"\x{aaa}">>] end,
+ "[a || <<\"\\x{aaa}\">> <= <<\"\\x{aaa}\">>]. ",
+ []),
+ check(fun() -> [a || <<"\x{aaa}"/utf8>> <= <<"\x{aaa}"/utf8>>] end,
+ "[a || <<\"\\x{aaa}\"/utf8>> <= <<\"\\x{aaa}\"/utf8>>]. ",
+ [a]),
+
+ ok.
+
funs(doc) ->
["Simple cases, just to cover some code."];
funs(suite) ->
diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl
index 564f27a512..36229b6989 100644
--- a/lib/stdlib/test/erl_lint_SUITE.erl
+++ b/lib/stdlib/test/erl_lint_SUITE.erl
@@ -58,7 +58,8 @@
otp_8051/1,
format_warn/1,
on_load_successful/1, on_load_failing/1,
- too_many_arguments/1
+ too_many_arguments/1,
+ basic_errors/1,bin_syntax_errors/1
]).
% Default timetrap timeout (set in init_per_testcase).
@@ -84,7 +85,7 @@ all() ->
otp_5878, otp_5917, otp_6585, otp_6885, otp_10436, export_all,
bif_clash, behaviour_basic, behaviour_multiple,
otp_7550, otp_8051, format_warn, {group, on_load},
- too_many_arguments].
+ too_many_arguments, basic_errors, bin_syntax_errors].
groups() ->
[{unused_vars_warn, [],
@@ -1351,7 +1352,17 @@ guard(Config) when is_list(Config) ->
(is_record(X, apa)*2)].
">>,
[],
- []}],
+ []},
+ {guard8,
+ <<"t(A) when erlang:is_foobar(A) -> ok;
+ t(A) when A ! ok -> ok;
+ t(A) when A ++ [x] -> ok."
+ >>,
+ [],
+ {errors,[{1,erl_lint,illegal_guard_expr},
+ {2,erl_lint,illegal_guard_expr},
+ {3,erl_lint,illegal_guard_expr}],[]}}
+ ],
?line [] = run(Config, Ts1),
ok.
@@ -1639,6 +1650,7 @@ otp_5276(Config) when is_list(Config) ->
-deprecated([{'_','_',never}]).
-deprecated([{{badly,formed},1}]).
-deprecated([{'_','_',next_major_release}]).
+ -deprecated([{atom_to_list,1}]).
-export([t/0]).
frutt() -> ok.
t() -> ok.
@@ -1649,8 +1661,9 @@ otp_5276(Config) when is_list(Config) ->
{3,erl_lint,{invalid_deprecated,'foo bar'}},
{5,erl_lint,{bad_deprecated,{f,'_'}}},
{8,erl_lint,{invalid_deprecated,{'_','_',never}}},
- {9,erl_lint,{invalid_deprecated,{{badly,formed},1}}}],
- [{12,erl_lint,{unused_function,{frutt,0}}}]}}],
+ {9,erl_lint,{invalid_deprecated,{{badly,formed},1}}},
+ {11,erl_lint,{bad_deprecated,{atom_to_list,1}}}],
+ [{13,erl_lint,{unused_function,{frutt,0}}}]}}],
?line [] = run(Config, Ts),
ok.
@@ -1896,9 +1909,23 @@ otp_5362(Config) when is_list(Config) ->
warn_deprecated_function,
warn_bif_clash]},
{errors,
- [{2,erl_lint,disallowed_nowarn_bif_clash}],[]}}
+ [{2,erl_lint,disallowed_nowarn_bif_clash}],[]}},
- ],
+ {call_deprecated_function,
+ <<"t(X) -> erlang:hash(X, 2000).">>,
+ [],
+ {warnings,
+ [{1,erl_lint,{deprecated,{erlang,hash,2},
+ {erlang,phash2,2},"in a future release"}}]}},
+
+ {call_removed_function,
+ <<"t(X) -> regexp:match(X).">>,
+ [],
+ {warnings,
+ [{1,erl_lint,{removed,{regexp,match,1},
+ "removed in R15; use the re module instead"}}]}}
+
+ ],
?line [] = run(Config, Ts),
ok.
@@ -2971,6 +2998,77 @@ too_many_arguments(Config) when is_list(Config) ->
ok.
+%% Test some basic errors to improve coverage.
+basic_errors(Config) ->
+ Ts = [{redefine_module,
+ <<"-module(redefine_module).">>,
+ [],
+ {errors,[{1,erl_lint,redefine_module}],[]}},
+
+ {attr_after_function,
+ <<"f() -> ok.
+ -attr(x).">>,
+ [],
+ {errors,[{2,erl_lint,{attribute,attr}}],[]}},
+
+ {redefine_function,
+ <<"f() -> ok.
+ f() -> ok.">>,
+ [],
+ {errors,[{2,erl_lint,{redefine_function,{f,0}}}],[]}},
+
+ {redefine_record,
+ <<"-record(r, {a}).
+ -record(r, {a}).
+ f(#r{}) -> ok.">>,
+ [],
+ {errors,[{2,erl_lint,{redefine_record,r}}],[]}},
+
+ {illegal_record_info,
+ <<"f1() -> record_info(42, record).
+ f2() -> record_info(shoe_size, record).">>,
+ [],
+ {errors,[{1,erl_lint,illegal_record_info},
+ {2,erl_lint,illegal_record_info}],[]}},
+
+ {illegal_expr,
+ <<"f() -> a:b.">>,
+ [],
+ {errors,[{1,erl_lint,illegal_expr}],[]}},
+
+ {illegal_pattern,
+ <<"f(A+B) -> ok.">>,
+ [],
+ {errors,[{1,erl_lint,illegal_pattern}],[]}}
+ ],
+ [] = run(Config, Ts),
+ ok.
+
+%% Test binary syntax errors
+bin_syntax_errors(Config) ->
+ Ts = [{bin_syntax_errors,
+ <<"t(<<X:bad_size>>) -> X;
+ t(<<_:(x ! y)/integer>>) -> ok;
+ t(<<X:all/integer>>) -> X;
+ t(<<X/bad_type>>) -> X;
+ t(<<X/unit:8>>) -> X;
+ t(<<X:7/float>>) -> X;
+ t(<< <<_:8>> >>) -> ok;
+ t(<<(x ! y):8/integer>>) -> ok.
+ ">>,
+ [],
+ {error,[{1,erl_lint,illegal_bitsize},
+ {2,erl_lint,illegal_bitsize},
+ {3,erl_lint,illegal_bitsize},
+ {4,erl_lint,{undefined_bittype,bad_type}},
+ {5,erl_lint,bittype_unit},
+ {7,erl_lint,illegal_pattern},
+ {8,erl_lint,illegal_pattern}],
+ [{6,erl_lint,{bad_bitsize,"float"}}]}}
+ ],
+ [] = run(Config, Ts),
+ ok.
+
run(Config, Tests) ->
F = fun({N,P,Ws,E}, BadL) ->
case catch run_test(Config, P, Ws) of
diff --git a/lib/stdlib/vsn.mk b/lib/stdlib/vsn.mk
index 33d7a57cc3..c1467697e3 100644
--- a/lib/stdlib/vsn.mk
+++ b/lib/stdlib/vsn.mk
@@ -1 +1 @@
-STDLIB_VSN = 1.19
+STDLIB_VSN = 1.19.1
diff --git a/lib/test_server/src/test_server.erl b/lib/test_server/src/test_server.erl
index 43330d2c91..4c39c604a2 100644
--- a/lib/test_server/src/test_server.erl
+++ b/lib/test_server/src/test_server.erl
@@ -186,7 +186,7 @@ do_cover_compile1([M|Rest]) ->
{ok,_} ->
ok;
Error ->
- io:fwrite("\nWARNING: Could not cover compile ~w: ~tp\n",
+ io:fwrite("\nWARNING: Could not cover compile ~w: ~p\n",
[M,Error])
end,
code:stick_mod(M),
@@ -196,7 +196,7 @@ do_cover_compile1([M|Rest]) ->
{module,_} ->
do_cover_compile1([M|Rest]);
Error ->
- io:fwrite("\nWARNING: Could not load ~w: ~tp\n",[M,Error]),
+ io:fwrite("\nWARNING: Could not load ~w: ~p\n",[M,Error]),
do_cover_compile1(Rest)
end;
{false,_} ->
@@ -204,7 +204,7 @@ do_cover_compile1([M|Rest]) ->
{ok,_} ->
ok;
Error ->
- io:fwrite("\nWARNING: Could not cover compile ~w: ~tp\n",
+ io:fwrite("\nWARNING: Could not cover compile ~w: ~p\n",
[M,Error])
end,
do_cover_compile1(Rest)
@@ -286,7 +286,7 @@ cover_analyse(Analyse,Modules,Stop) ->
{ok,{M,{Cov,NotCov}}} ->
{M,{Cov,NotCov,DetailsFun(M)}};
Err ->
- io:fwrite("WARNING: Analysis failed for ~w. Reason: ~tp\n",
+ io:fwrite("WARNING: Analysis failed for ~w. Reason: ~p\n",
[M,Err]),
{M,Err}
end
@@ -498,7 +498,7 @@ run_test_case_msgloop(#st{ref=Ref,pid=Pid,end_conf_pid=EndConfPid0}=St0) ->
exit(Pid, kill),
%% here's the only place we know Reason, so we save
%% it as a comment, potentially replacing user data
- Error = lists:flatten(io_lib:format("Aborted: ~tp",
+ Error = lists:flatten(io_lib:format("Aborted: ~p",
[Reason])),
Error1 = lists:flatten([string:strip(S,left) ||
S <- string:tokens(Error,
@@ -742,8 +742,8 @@ call_end_conf(Mod,Func,TCPid,TCExitReason,Loc,Conf,TVal) ->
timer:sleep(1),
group_leader() ! {printout,12,
"WARNING! "
- "~w:end_per_testcase(~w, ~tp)"
- " crashed!\n\tReason: ~tp\n",
+ "~w:end_per_testcase(~w, ~p)"
+ " crashed!\n\tReason: ~p\n",
[Mod,Func,Conf,Why]};
_ ->
ok
@@ -756,8 +756,8 @@ call_end_conf(Mod,Func,TCPid,TCExitReason,Loc,Conf,TVal) ->
Starter ! {self(),{call_end_conf,Data,ok}};
{'EXIT',Pid,Reason} ->
group_leader() ! {printout,12,
- "WARNING! ~w:end_per_testcase(~w, ~tp)"
- " failed!\n\tReason: ~tp\n",
+ "WARNING! ~w:end_per_testcase(~w, ~p)"
+ " failed!\n\tReason: ~p\n",
[Mod,Func,Conf,Reason]},
Starter ! {self(),{call_end_conf,Data,{error,Reason}}};
{'EXIT',_OtherPid,Reason} ->
@@ -802,7 +802,7 @@ spawn_fw_call(Mod,{end_per_testcase,Func},EndConf,Pid,
{Result,E}
end,
group_leader() ! {printout,12,
- "WARNING! ~w:end_per_testcase(~w, ~tp)"
+ "WARNING! ~w:end_per_testcase(~w, ~p)"
" failed!\n\tReason: timetrap timeout"
" after ~w ms!\n", [Mod,Func,EndConf,TVal]},
FailLoc = proplists:get_value(tc_fail_loc, EndConf),
@@ -1180,7 +1180,7 @@ do_init_per_testcase(Mod, Args) ->
Bad ->
group_leader() ! {printout,12,
"ERROR! init_per_testcase has returned "
- "bad elements in Config: ~tp\n",[Bad]},
+ "bad elements in Config: ~p\n",[Bad]},
{skip,{failed,{Mod,init_per_testcase,bad_return}}}
end;
{fail,_Reason}=Res ->
@@ -1197,7 +1197,7 @@ do_init_per_testcase(Mod, Args) ->
FormattedLoc = test_server_sup:format_loc(Line),
group_leader() ! {printout,12,
"ERROR! init_per_testcase thrown!\n"
- "\tLocation: ~ts\n\tReason: ~tp\n",
+ "\tLocation: ~ts\n\tReason: ~p\n",
[FormattedLoc, Other]},
{skip,{failed,{Mod,init_per_testcase,Other}}};
_:Reason0 ->
@@ -1208,7 +1208,7 @@ do_init_per_testcase(Mod, Args) ->
FormattedLoc = test_server_sup:format_loc(Line),
group_leader() ! {printout,12,
"ERROR! init_per_testcase crashed!\n"
- "\tLocation: ~ts\n\tReason: ~tp\n",
+ "\tLocation: ~ts\n\tReason: ~p\n",
[FormattedLoc,Reason]},
{skip,{failed,{Mod,init_per_testcase,Reason}}}
end.
@@ -1249,7 +1249,7 @@ do_end_per_testcase(Mod,EndFunc,Func,Conf) ->
"</font>\n",[Comment0,EndFunc])),
group_leader() ! {printout,12,
"WARNING: ~w thrown!\n"
- "Reason: ~tp\n"
+ "Reason: ~p\n"
"Line: ~ts\n",
[EndFunc, Other,
test_server_sup:format_loc(get_loc())]},
@@ -1271,7 +1271,7 @@ do_end_per_testcase(Mod,EndFunc,Func,Conf) ->
"</font>\n",[Comment0,EndFunc])),
group_leader() ! {printout,12,
"WARNING: ~w crashed!\n"
- "Reason: ~tp\n"
+ "Reason: ~p\n"
"Line: ~ts\n",
[EndFunc, Reason,
test_server_sup:format_loc(get_loc())]},
@@ -1351,7 +1351,7 @@ lookup_config(Key,Config) ->
{value,{Key,Val}} ->
Val;
_ ->
- io:format("Could not find element ~tp in Config.~n",[Key]),
+ io:format("Could not find element ~p in Config.~n",[Key]),
undefined
end.
@@ -1433,7 +1433,7 @@ format(Detail, Format, Args) ->
Str =
case catch io_lib:format(Format,Args) of
{'EXIT',_} ->
- io_lib:format("illegal format; ~tp with args ~tp.\n",
+ io_lib:format("illegal format; ~p with args ~p.\n",
[Format,Args]);
Valid -> Valid
end,
@@ -1564,7 +1564,7 @@ fail(Reason) ->
cast_to_list(X) when is_list(X) -> X;
cast_to_list(X) when is_atom(X) -> atom_to_list(X);
-cast_to_list(X) -> lists:flatten(io_lib:format("~tp", [X])).
+cast_to_list(X) -> lists:flatten(io_lib:format("~p", [X])).
@@ -1735,7 +1735,7 @@ ensure_timetrap(Config) ->
Garbage ->
erase(test_server_default_timetrap),
format("=== WARNING: garbage in "
- "test_server_default_timetrap: ~tp~n",
+ "test_server_default_timetrap: ~p~n",
[Garbage])
end,
DTmo = case lists:keysearch(default_timeout,1,Config) of
@@ -1743,7 +1743,7 @@ ensure_timetrap(Config) ->
_ -> ?DEFAULT_TIMETRAP_SECS
end,
format("=== test_server setting default "
- "timetrap of ~tp seconds~n",
+ "timetrap of ~p seconds~n",
[DTmo]),
put(test_server_default_timetrap, timetrap(seconds(DTmo)))
end.
@@ -1764,7 +1764,7 @@ cancel_default_timetrap(true) ->
Garbage ->
erase(test_server_default_timetrap),
format("=== WARNING: garbage in "
- "test_server_default_timetrap: ~tp~n",
+ "test_server_default_timetrap: ~p~n",
[Garbage]),
error
end.
@@ -1773,7 +1773,7 @@ time_ms({hours,N}, _, _) -> hours(N);
time_ms({minutes,N}, _, _) -> minutes(N);
time_ms({seconds,N}, _, _) -> seconds(N);
time_ms({Other,_N}, _, _) ->
- format("=== ERROR: Invalid time specification: ~tp. "
+ format("=== ERROR: Invalid time specification: ~p. "
"Should be seconds, minutes, or hours.~n", [Other]),
exit({invalid_time_format,Other});
time_ms(Ms, _, _) when is_integer(Ms) -> Ms;
diff --git a/lib/test_server/src/test_server_ctrl.erl b/lib/test_server/src/test_server_ctrl.erl
index e5d75e43c9..70cb6fa220 100644
--- a/lib/test_server/src/test_server_ctrl.erl
+++ b/lib/test_server/src/test_server_ctrl.erl
@@ -92,7 +92,7 @@
-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(unexpected_io_log, "unexpected_io.log.html").
-define(last_file, "last_name").
-define(last_link, "last_link").
-define(last_test, "last_test").
@@ -229,7 +229,7 @@ parse_cmd_line(['SPEC',Spec|Cmds], SpecList, Names, Param, Trc, Cov, TCCB) ->
parse_cmd_line(Cmds, TermList++SpecList, [Name|Names], Param,
Trc, Cov, TCCB);
{error,Reason} ->
- io:format("Can't open ~w: ~tp\n",[Spec, file:format_error(Reason)]),
+ io:format("Can't open ~w: ~p\n",[Spec, file:format_error(Reason)]),
parse_cmd_line(Cmds, SpecList, Names, Param, Trc, Cov, TCCB)
end;
parse_cmd_line(['NAME',Name|Cmds], SpecList, Names, Param, Trc, Cov, TCCB) ->
@@ -1013,7 +1013,7 @@ handle_info({'EXIT',Pid,Reason}, State) ->
killed ->
io:format("Suite ~ts was killed\n", [Name]);
_Other ->
- io:format("Suite ~ts was killed with reason ~tp\n",
+ io:format("Suite ~ts was killed with reason ~p\n",
[Name,Reason])
end,
State2 = State#state{jobs=NewJobs},
@@ -1058,7 +1058,7 @@ handle_info({tcp,_MainSock,<<1,Request/binary>>}, State) ->
%% because the job is finished. Then the above clause ('EXIT') will
%% handle the problem.
io:format("Suite ~ts was killed on remote target with reason"
- " ~tp\n", [Name,Reason]);
+ " ~p\n", [Name,Reason]);
_ ->
ignore
end,
@@ -1192,10 +1192,10 @@ init_tester(Mod, Func, Args, Dir, Name, {_,_,MinLev}=Levels,
{'EXIT',test_suites_done} ->
ok;
{'EXIT',_Pid,Reason} ->
- print(1, "EXIT, reason ~tp", [Reason]);
+ print(1, "EXIT, reason ~p", [Reason]);
{'EXIT',Reason} ->
report_severe_error(Reason),
- print(1, "EXIT, reason ~tp", [Reason])
+ print(1, "EXIT, reason ~p", [Reason])
end,
Time = TimeMy/1000000,
SuccessStr =
@@ -1285,7 +1285,7 @@ do_spec(SpecName, TimetrapSpec) when is_list(SpecName) ->
{ok,TermList} ->
do_spec_list(TermList,TimetrapSpec);
{error,Reason} ->
- io:format("Can't open ~ts: ~tp\n", [SpecName,Reason]),
+ io:format("Can't open ~ts: ~p\n", [SpecName,Reason]),
{error,{cant_open_spec,Reason}}
end.
@@ -1368,7 +1368,7 @@ do_spec_terms([{require_nodenames,NumNames}|Terms], TopCases, SkipList, Config)
do_spec_terms(Terms, TopCases, SkipList,
update_config(Config, {nodenames,NodeNames}));
do_spec_terms([Other|Terms], TopCases, SkipList, Config) ->
- io:format("** WARNING: Spec file contains unknown directive ~tp\n",
+ io:format("** WARNING: Spec file contains unknown directive ~p\n",
[Other]),
do_spec_terms(Terms, TopCases, SkipList, Config).
@@ -1507,7 +1507,7 @@ do_test_cases(TopCases, SkipCases,
FwMod = get_fw_mod(?MODULE),
case collect_all_cases(TopCases, SkipCases) of
{error,Why} ->
- print(1, "Error starting: ~tp", [Why]),
+ print(1, "Error starting: ~p", [Why]),
exit(test_suites_done);
TestSpec0 ->
N = case remove_conf(TestSpec0) of
@@ -1531,6 +1531,7 @@ do_test_cases(TopCases, SkipCases,
TestDescr = "Test " ++ TestName ++ " results",
test_server_sup:framework_call(report, [tests_start,{Test,N}]),
+
{Header,Footer} =
case test_server_sup:framework_call(get_html_wrapper,
[TestDescr,true,TestDir,
@@ -1616,7 +1617,7 @@ do_test_cases(TopCases, SkipCases,
print(major, "=emulator_vsn ~ts", [TI#target_info.version]),
print(major, "=emulator ~ts", [TI#target_info.emulator]),
print(major, "=otp_release ~ts", [TI#target_info.otp_release]),
- print(major, "=started ~ts",
+ print(major, "=started ~s",
[lists:flatten(timestamp_get(""))]),
put(test_server_html_footer, Footer),
@@ -1667,19 +1668,36 @@ start_log_file() ->
MkDirError2 ->
log_file_error(MkDirError2, TestDir)
end,
- ok = write_file(filename:join(Dir, ?last_file), TestDir1 ++ "\n"),
- ok = write_file(?last_file, TestDir1 ++ "\n"),
+ FilenameMode = file:native_name_encoding(),
+ ok = write_file(filename:join(Dir, ?last_file),
+ TestDir1 ++ "\n",
+ FilenameMode),
+ ok = write_file(?last_file, TestDir1 ++ "\n", FilenameMode),
put(test_server_log_dir_base,TestDir1),
MajorName = filename:join(TestDir1, ?suitelog_name),
HtmlName = MajorName ++ ?html_ext,
UnexpectedName = filename:join(TestDir1, ?unexpected_io_log),
- {ok,Major} = open_file(MajorName),
+ {ok,Major} = open_utf8_file(MajorName),
{ok,Html} = open_html_file(HtmlName),
- {ok,Unexpected} = open_file(UnexpectedName),
+ {ok,Unexpected} = open_html_file(UnexpectedName),
test_server_io:set_fd(major, Major),
test_server_io:set_fd(html, Html),
test_server_io:set_fd(unexpected_io, Unexpected),
+ {UnexpHeader,UnexpFooter} =
+ case test_server_sup:framework_call(get_html_wrapper,
+ ["Unexpected I/O log",false,
+ TestDir, undefined],"") of
+ UEmpty when (UEmpty == "") ; (element(2,UEmpty) == "") ->
+ {html_header("Unexpected I/O log"),"\n</body>\n</html>\n"};
+ {basic_html,UH,UF} ->
+ {UH,UF};
+ {xhtml,UH,UF} ->
+ {UH,UF}
+ end,
+ io:put_chars(Unexpected, UnexpHeader++"\n<pre>\n"),
+ put(test_server_unexpected_footer,UnexpFooter),
+
make_html_link(filename:absname(?last_test ++ ?html_ext),
HtmlName, filename:basename(Dir)),
LinkName = filename:join(Dir, ?last_link),
@@ -1892,9 +1910,9 @@ copy_html_file(Src, DestDir) ->
Dest = filename:join(DestDir, filename:basename(Src)),
case file:read_file(Src) of
{ok,Bin} ->
- ok = write_file(Dest, Bin);
+ ok = write_binary_file(Dest, Bin);
{error,_Reason} ->
- io:format("File ~tp: read failed\n", [Src])
+ io:format("File ~ts: read failed\n", [Src])
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -2073,7 +2091,7 @@ run_test_cases(TestSpec, Config, TimetrapData) ->
[OkN,FailedN,SkipStr,OkN+FailedN+AllSkippedN]),
test_server_sup:framework_call(report, [tests_done,
{OkN,FailedN,{UserSkipN,AutoSkipN}}]),
- print(major, "=finished ~ts", [lists:flatten(timestamp_get(""))]),
+ print(major, "=finished ~s", [lists:flatten(timestamp_get(""))]),
print(major, "=failed ~w", [FailedN]),
print(major, "=successful ~w", [OkN]),
print(major, "=user_skipped ~w", [UserSkipN]),
@@ -2609,7 +2627,7 @@ run_test_cases_loop([{conf,Ref,Props,{Mod,Func}}|_Cases]=Cs0,
TimetrapData, Mode, Status2);
Bad ->
print(minor,
- "~n*** ~w returned bad elements in Config: ~tp.~n",
+ "~n*** ~w returned bad elements in Config: ~p.~n",
[Func,Bad]),
Reason = {failed,{Mod,init_per_suite,bad_return}},
Cases2 = skip_cases_upto(Ref, Cases, Reason, conf, CurrMode),
@@ -2624,9 +2642,9 @@ run_test_cases_loop([{conf,Ref,Props,{Mod,Func}}|_Cases]=Cs0,
stop_minor_log_file(),
run_test_cases_loop(Cases, [NewCfg|Config], TimetrapData, Mode, Status2);
{_,{framework_error,{FwMod,FwFunc},Reason},_} ->
- print(minor, "~n*** ~w failed in ~w. Reason: ~tp~n",
+ print(minor, "~n*** ~w failed in ~w. Reason: ~p~n",
[FwMod,FwFunc,Reason]),
- print(1, "~w failed in ~w. Reason: ~tp~n", [FwMod,FwFunc,Reason]),
+ print(1, "~w failed in ~w. Reason: ~p~n", [FwMod,FwFunc,Reason]),
exit(framework_error);
{_,Fail,_} when element(1,Fail) == 'EXIT';
element(1,Fail) == timetrap_timeout;
@@ -2768,9 +2786,9 @@ run_test_cases_loop([{Mod,Func,Args}|Cases], Config, TimetrapData, Mode, Status)
run_init, TimetrapData, Mode) of
%% callback to framework module failed, exit immediately
{_,{framework_error,{FwMod,FwFunc},Reason},_} ->
- print(minor, "~n*** ~w failed in ~w. Reason: ~tp~n",
+ print(minor, "~n*** ~w failed in ~w. Reason: ~p~n",
[FwMod,FwFunc,Reason]),
- print(1, "~w failed in ~w. Reason: ~tp~n", [FwMod,FwFunc,Reason]),
+ print(1, "~w failed in ~w. Reason: ~p~n", [FwMod,FwFunc,Reason]),
stop_minor_log_file(),
exit(framework_error);
%% sequential execution of test case finished
@@ -2942,8 +2960,8 @@ print_conf_time(ConfTime) ->
print_props(_, []) ->
ok;
print_props(true, Props) ->
- print(major, "=group_props ~tp", [Props]),
- print(minor, "Group properties: ~tp~n", [Props]);
+ print(major, "=group_props ~p", [Props]),
+ print(minor, "Group properties: ~p~n", [Props]);
print_props(_, _) ->
ok.
@@ -3094,7 +3112,7 @@ skip_case1(Type, CaseNum, Mod, Func, Comment, Mode) ->
Comment1 = reason_to_string(Comment),
print(major, "~n=case ~w:~w", [Mod,Func]),
- print(major, "=started ~ts", [lists:flatten(timestamp_get(""))]),
+ print(major, "=started ~s", [lists:flatten(timestamp_get(""))]),
print(major, "=result skipped: ~ts", [Comment1]),
print(2,"*** Skipping test case #~w ~w ***", [CaseNum,{Mod,Func}]),
TR = xhtml("<tr valign=\"top\">", ["<tr class=\"",odd_or_even(),"\">"]),
@@ -3292,7 +3310,7 @@ wait_and_resend(Ref, [{_,CurrPid,CaseNum,Mod,Func}|Ps] = Cases, Ok,Skip,Fail) ->
{'EXIT',CurrPid,Reason} when Reason /= normal ->
%% unexpected termination of test case process
{value,{_,_,CaseNum,Mod,Func}} = lists:keysearch(CurrPid, 2, Cases),
- print(1, "Error! Process for test case #~w (~w:~w) died! Reason: ~tp",
+ print(1, "Error! Process for test case #~w (~w:~w) died! Reason: ~p",
[CaseNum, Mod, Func, Reason]),
exit({unexpected_termination,{CaseNum,Mod,Func},{CurrPid,Reason}})
end;
@@ -3431,7 +3449,7 @@ handle_io_and_exits(Main, CurrPid, CaseNum, Mod, Func, Cases) ->
{'EXIT',TCPid,Reason} when Reason /= normal ->
test_server_io:print_buffered(CurrPid),
{value,{_,_,Num,M,F}} = lists:keysearch(TCPid, 2, Cases),
- print(1, "Error! Process for test case #~w (~w:~w) died! Reason: ~tp",
+ print(1, "Error! Process for test case #~w (~w:~w) died! Reason: ~p",
[Num, M, F, Reason]),
exit({unexpected_termination,{Num,M,F},{TCPid,Reason}})
end.
@@ -3546,7 +3564,7 @@ run_test_case1(Ref, Num, Mod, Func, Args, RunInit,
undefined -> "";
Name -> cast_to_list(Name)
end,
- print(major, "=started ~ts", [lists:flatten(timestamp_get(""))]),
+ print(major, "=started ~s", [lists:flatten(timestamp_get(""))]),
{{Col0,Col1},Style} = get_font_style((RunInit==run_init), Mode),
TR = xhtml("<tr valign=\"top\">", ["<tr class=\"",odd_or_even(),"\">"]),
EncMinorBase = uri_encode(MinorBase),
@@ -3573,7 +3591,7 @@ run_test_case1(Ref, Num, Mod, Func, Args, RunInit,
print(minor, "<a name=\"end\"></a>", [], internal_raw),
print(minor, "\n", [], internal_raw),
print_timestamp(minor, "Ended at "),
- print(major, "=ended ~ts", [lists:flatten(timestamp_get(""))]),
+ print(major, "=ended ~s", [lists:flatten(timestamp_get(""))]),
do_unless_parallel(Main, fun() -> file:set_cwd(filename:dirname(TSDir)) end),
@@ -3657,13 +3675,13 @@ run_test_case1(Ref, Num, Mod, Func, Args, RunInit,
{'EXIT',_} = Exit ->
print(minor,
"WARNING: There might be slavenodes left in the"
- " system. I tried to kill them, but I failed: ~tp\n",
+ " system. I tried to kill them, but I failed: ~p\n",
[Exit]);
[] -> ok;
List ->
print(minor, "WARNING: ~w slave nodes in system after test"++
"case. Tried to killed them.~n"++
- " Names:~tp",
+ " Names:~p",
[length(List),List])
end;
false ->
@@ -3752,7 +3770,7 @@ progress(skip, CaseNum, Mod, Func, Loc, Reason, Time,
progress(failed, CaseNum, Mod, Func, Loc, timetrap_timeout, T,
Comment0, {St0,St1}) ->
- print(major, "=result failed: timeout, ~tp", [Loc]),
+ print(major, "=result failed: timeout, ~p", [Loc]),
print(1, "*** FAILED *** ~ts",
[get_info_str(Func, CaseNum, get(test_server_cases))]),
test_server_sup:framework_call(report,
@@ -3778,7 +3796,7 @@ progress(failed, CaseNum, Mod, Func, Loc, timetrap_timeout, T,
progress(failed, CaseNum, Mod, Func, Loc, {testcase_aborted,Reason}, _T,
Comment0, {St0,St1}) ->
- print(major, "=result failed: testcase_aborted, ~tp", [Loc]),
+ print(major, "=result failed: testcase_aborted, ~p", [Loc]),
print(1, "*** FAILED *** ~ts",
[get_info_str(Func, CaseNum, get(test_server_cases))]),
test_server_sup:framework_call(report,
@@ -3799,12 +3817,12 @@ progress(failed, CaseNum, Mod, Func, Loc, {testcase_aborted,Reason}, _T,
[Comment]),
FormatLoc = test_server_sup:format_loc(Loc),
print(minor, "=== location ~ts", [FormatLoc]),
- print(minor, "=== reason = {testcase_aborted,~tp}", [Reason]),
+ print(minor, "=== reason = {testcase_aborted,~p}", [Reason]),
failed;
progress(failed, CaseNum, Mod, Func, unknown, Reason, Time,
Comment0, {St0,St1}) ->
- print(major, "=result failed: ~tp, ~w", [Reason,unknown]),
+ print(major, "=result failed: ~p, ~w", [Reason,unknown]),
print(1, "*** FAILED *** ~ts",
[get_info_str(Func, CaseNum, get(test_server_cases))]),
test_server_sup:framework_call(report, [tc_done,{Mod,Func,
@@ -3812,7 +3830,7 @@ progress(failed, CaseNum, Mod, Func, unknown, Reason, Time,
TimeStr = io_lib:format(if is_float(Time) -> "~.3fs";
true -> "~w"
end, [Time]),
- ErrorReason = lists:flatten(io_lib:format("~tp", [Reason])),
+ ErrorReason = lists:flatten(io_lib:format("~p", [Reason])),
ErrorReason1 = lists:flatten([string:strip(S,left) ||
S <- string:tokens(ErrorReason,[$\n])]),
ErrorReason2 =
@@ -3840,7 +3858,7 @@ progress(failed, CaseNum, Mod, Func, unknown, Reason, Time,
progress(failed, CaseNum, Mod, Func, Loc, Reason, Time,
Comment0, {St0,St1}) ->
- print(major, "=result failed: ~tp, ~tp", [Reason,Loc]),
+ print(major, "=result failed: ~p, ~p", [Reason,Loc]),
print(1, "*** FAILED *** ~ts",
[get_info_str(Func, CaseNum, get(test_server_cases))]),
test_server_sup:framework_call(report, [tc_done,{Mod,Func,
@@ -3885,13 +3903,13 @@ progress(ok, _CaseNum, Mod, Func, _Loc, RetVal, Time,
_ -> "<td>" ++ to_string(Comment0) ++ "</td>"
end
end,
- print(major, "=elapsed ~tp", [Time]),
+ print(major, "=elapsed ~p", [Time]),
print(html,
"<td>" ++ St0 ++ "~.3fs" ++ St1 ++ "</td>"
"<td><font color=\"green\">Ok</font></td>"
"~ts</tr>\n",
[Time,Comment]),
- print(minor, "=== returned value = ~tp", [RetVal]),
+ print(minor, "=== returned value = ~p", [RetVal]),
ok.
%%--------------------------------------------------------------------
@@ -3968,11 +3986,11 @@ print_if_known(Known, {SK,AK}, {SU,AU}) ->
to_string(Term) when is_list(Term) ->
case (catch io_lib:format("~ts", [Term])) of
- {'EXIT',_} -> lists:flatten(io_lib:format("~tp", [Term]));
+ {'EXIT',_} -> lists:flatten(io_lib:format("~p", [Term]));
String -> lists:flatten(String)
end;
to_string(Term) ->
- lists:flatten(io_lib:format("~tp", [Term])).
+ lists:flatten(io_lib:format("~p", [Term])).
get_last_loc(Loc) when is_tuple(Loc) ->
Loc;
@@ -4044,14 +4062,14 @@ format_exception(Reason={_Error,Stack}) when is_list(Stack) ->
undefined ->
case application:get_env(test_server, format_exception) of
{ok,false} ->
- {"~tp",Reason};
+ {"~p",Reason};
_ ->
do_format_exception(Reason)
end;
FW ->
case application:get_env(FW, format_exception) of
{ok,false} ->
- {"~tp",Reason};
+ {"~p",Reason};
_ ->
do_format_exception(Reason)
end
@@ -4066,7 +4084,7 @@ do_format_exception(Reason={Error,Stack}) ->
end,
case catch lib:format_exception(1, error, Error, Stack, StackFun, PF) of
{'EXIT',_} ->
- {"~tp",Reason};
+ {"~p",Reason};
Formatted ->
Formatted1 = re:replace(Formatted, "exception error: ", "", [{return,list}]),
{"~ts",lists:flatten(Formatted1)}
@@ -4175,7 +4193,7 @@ format(Detail, Format, Args) ->
Str =
case catch io_lib:format(Format, Args) of
{'EXIT',_} ->
- io_lib:format("illegal format; ~tp with args ~tp.\n",
+ io_lib:format("illegal format; ~p with args ~p.\n",
[Format,Args]);
Valid -> Valid
end,
@@ -4555,7 +4573,7 @@ collect_files(Dir, Pattern, St) ->
Wc = filename:join([Dir1,Pattern++code:objfile_extension()]),
case catch filelib:wildcard(Wc) of
{'EXIT', Reason} ->
- io:format("Could not collect files: ~tp~n", [Reason]),
+ io:format("Could not collect files: ~p~n", [Reason]),
{error,{collect_fail,Dir,Pattern}};
Mods0 ->
Mods = [{path_to_module(Mod),all} || Mod <- lists:sort(Mods0)],
@@ -4588,16 +4606,16 @@ check_deny([], _DenyList) -> granted;
check_deny(Req, DenyList) -> check_deny([Req], DenyList).
check_deny_req({Req,Val}, DenyList) ->
- %%io:format("ValCheck ~tp=~tp in ~tp\n", [Req,Val,DenyList]),
+ %%io:format("ValCheck ~p=~p in ~p\n", [Req,Val,DenyList]),
case lists:keysearch(Req, 1, DenyList) of
{value,{_Req,DenyVal}} when Val >= DenyVal ->
- {denied,io_lib:format("Requirement ~tp=~tp", [Req,Val])};
+ {denied,io_lib:format("Requirement ~p=~p", [Req,Val])};
_ ->
check_deny_req(Req, DenyList)
end;
check_deny_req(Req, DenyList) ->
case lists:member(Req, DenyList) of
- true -> {denied,io_lib:format("Requirement ~tp", [Req])};
+ true -> {denied,io_lib:format("Requirement ~p", [Req])};
false -> granted
end.
@@ -4698,7 +4716,7 @@ get_target_info() ->
start_node(Name, Type, Options) ->
T = 10 * ?ACCEPT_TIMEOUT * test_server:timetrap_scale_factor(),
- format(minor, "Attempt to start ~w node ~tp with options ~tp",
+ format(minor, "Attempt to start ~w node ~p with options ~p",
[Type, Name, Options]),
case controller_call({start_node,Name,Type,Options}, T) of
{{ok,Nodename}, Host, Cmd, Info, Warning} ->
@@ -4720,16 +4738,16 @@ start_node(Name, Type, Options) ->
{fail,{Ret, Host, Cmd}} ->
format(minor,
"Failed to start node ~tp on ~tp with command: ~tp~n"
- "Reason: ~tp",
+ "Reason: ~p",
[Name, Host, Cmd, Ret]),
{fail,Ret};
{Ret, undefined, undefined} ->
- format(minor, "Failed to start node ~tp: ~tp", [Name,Ret]),
+ format(minor, "Failed to start node ~tp: ~p", [Name,Ret]),
Ret;
{Ret, Host, Cmd} ->
format(minor,
"Failed to start node ~tp on ~tp with command: ~tp~n"
- "Reason: ~tp",
+ "Reason: ~p",
[Name, Host, Cmd, Ret]),
Ret
end.
@@ -4943,11 +4961,11 @@ read_cover_file(CoverFile) ->
case check_cover_file(List, [], [], []) of
{ok,Exclude,Include,Cross} -> {Exclude,Include,Cross};
error ->
- io:fwrite("Faulty format of CoverFile ~tp\n", [CoverFile]),
+ io:fwrite("Faulty format of CoverFile ~p\n", [CoverFile]),
{[],[],[]}
end;
{error,Reason} ->
- io:fwrite("Can't read CoverFile ~ts\nReason: ~tp\n",
+ io:fwrite("Can't read CoverFile ~ts\nReason: ~p\n",
[CoverFile,Reason]),
{[],[],[]}
end.
@@ -5021,7 +5039,8 @@ cover_analyse({App,CoverInfo}, Analyse, AnalyseMods, Stop, TestDir) ->
case length(cover:imported_modules()) of
Imps when Imps > 0 ->
- io:fwrite(CoverLog, "<p>Analysis includes data from ~w imported module(s).\n",
+ io:fwrite(CoverLog,
+ "<p>Analysis includes data from ~w imported module(s).\n",
[Imps]);
_ ->
ok
@@ -5030,8 +5049,8 @@ cover_analyse({App,CoverInfo}, Analyse, AnalyseMods, Stop, TestDir) ->
io:fwrite(CoverLog, "<p>Excluded module(s): <code>~tp</code>\n", [Excluded]),
Coverage = cover_analyse(Analyse, AnalyseMods, Stop),
- write_file(filename:join(TestDir,?raw_coverlog_name),
- term_to_binary(Coverage)),
+ write_binary_file(filename:join(TestDir,?raw_coverlog_name),
+ term_to_binary(Coverage)),
case lists:filter(fun({_M,{_,_,_}}) -> false;
(_) -> true
@@ -5045,7 +5064,8 @@ cover_analyse({App,CoverInfo}, Analyse, AnalyseMods, Stop, TestDir) ->
end,
TotPercent = write_cover_result_table(CoverLog, Coverage),
- write_file(filename:join(TestDir, ?cover_total),term_to_binary(TotPercent)).
+ write_binary_file(filename:join(TestDir, ?cover_total),
+ term_to_binary(TotPercent)).
cover_analyse(Analyse, AnalyseMods, Stop) ->
TestDir = get(test_server_log_dir_base),
@@ -5092,17 +5112,16 @@ cross_cover_analyse(Analyse, TagDirs0) ->
write_cross_cover_info(_Dir,[]) ->
ok;
write_cross_cover_info(Dir,Cross) ->
- {ok,Fd} = open_file(filename:join(Dir,?cross_cover_info)),
- lists:foreach(fun(C) -> io:format(Fd,"~tp.~n",[C]) end, Cross),
- ok = file:close(Fd).
+ write_binary_file(filename:join(Dir,?cross_cover_info),
+ term_to_binary(Cross)).
%% For each test from which there are cross cover analysed
%% modules, write a cross cover log (cross_cover.html).
write_cross_cover_logs([{Tag,Coverage}|T],TagDirMods) ->
case lists:keyfind(Tag,1,TagDirMods) of
{_,Dir,Mods} when Mods=/=[] ->
- write_file(filename:join(Dir,?raw_cross_coverlog_name),
- term_to_binary(Coverage)),
+ write_binary_file(filename:join(Dir,?raw_cross_coverlog_name),
+ term_to_binary(Coverage)),
CoverLogName = filename:join(Dir,?cross_coverlog_name),
{ok,CoverLog} = open_html_file(CoverLogName),
write_coverlog_header(CoverLog),
@@ -5140,8 +5159,9 @@ get_latest_dir([],Latest) ->
Latest.
get_all_cross_info([{_Tag,Dir}|Rest],Acc) ->
- case file:consult(filename:join(Dir,?cross_cover_info)) of
- {ok,TagMods} ->
+ case file:read_file(filename:join(Dir,?cross_cover_info)) of
+ {ok,Bin} ->
+ TagMods = binary_to_term(Bin),
get_all_cross_info(Rest,TagMods++Acc);
_ ->
get_all_cross_info(Rest,Acc)
@@ -5198,7 +5218,7 @@ write_coverlog_header(CoverLog) ->
{'EXIT',Reason} ->
io:format("\n\nERROR: Could not write normal heading in coverlog.\n"
"CoverLog: ~w\n"
- "Reason: ~tp\n",
+ "Reason: ~p\n",
[CoverLog,Reason]),
io:format(CoverLog,"<html><body>\n", []);
_ ->
@@ -5321,17 +5341,24 @@ html_header(Title) ->
"link=\"blue\" vlink=\"purple\" alink=\"red\">\n"].
open_html_file(File) ->
- file:open(File,[write,{encoding,utf8}]).
+ open_utf8_file(File).
write_html_file(File,Content) ->
- file:write_file(File,unicode:characters_to_binary(Content)).
+ write_file(File,Content,utf8).
+%% The 'major' log file, which is a pure text file is also written
+%% with utf8 encoding
+open_utf8_file(File) ->
+ file:open(File,[write,{encoding,utf8}]).
-%% Text files are written with default encoding
-open_file(File) ->
- file:open(File,[write]).
+%% Write a file with specified encoding
+write_file(File,Content,latin1) ->
+ file:write_file(File,Content);
+write_file(File,Content,utf8) ->
+ write_binary_file(File,unicode:characters_to_binary(Content)).
-write_file(File,Content) ->
+%% Write a file with only binary data
+write_binary_file(File,Content) ->
file:write_file(File,Content).
%% Encoding of hyperlinks in HTML files
diff --git a/lib/test_server/src/test_server_gl.erl b/lib/test_server/src/test_server_gl.erl
index 0ab0d58040..766a4537a2 100644
--- a/lib/test_server/src/test_server_gl.erl
+++ b/lib/test_server/src/test_server_gl.erl
@@ -159,7 +159,15 @@ handle_call({print,Detail,Msg,Printer}, {From,_}, St) ->
handle_cast(stop, St) ->
{stop,normal,St}.
-handle_info({'DOWN',Ref,process,_,_}, #st{minor_monitor=Ref}=St) ->
+handle_info({'DOWN',Ref,process,_,Reason}=D, #st{minor_monitor=Ref}=St) ->
+ case Reason of
+ normal -> ok;
+ _ ->
+ Data = io_lib:format("=== WARNING === TC: ~w\n"
+ "Got down from minor Fd ~w: ~w\n\n",
+ [St#st.tc,St#st.minor,D]),
+ test_server_io:print(xxxFrom, unexpected_io, Data)
+ end,
{noreply,St#st{minor=none,minor_monitor=none}};
handle_info({permit_io,Pid}, #st{permit_io=P}=St) ->
{noreply,St#st{permit_io=gb_sets:add(Pid, P)}};
@@ -253,12 +261,19 @@ output_to_file(minor, Data0, From, #st{tc={M,F,A},minor=none}) ->
Data = [io_lib:format("=== ~w:~w/~w\n", [M,F,A]),Data0],
test_server_io:print(From, unexpected_io, Data),
ok;
-output_to_file(minor, Data, From, #st{minor=Fd}) ->
+output_to_file(minor, Data, From, #st{tc=TC,minor=Fd}) ->
try
io:put_chars(Fd, Data)
catch
- _:_ ->
- test_server_io:print(From, unexpected_io, Data)
+ Type:Reason ->
+ Data1 =
+ [io_lib:format("=== ERROR === TC: ~w\n"
+ "Failed to write to minor Fd: ~w\n"
+ "Type: ~w\n"
+ "Reason: ~w\n",
+ [TC,Fd,Type,Reason]),
+ Data,"\n"],
+ test_server_io:print(From, unexpected_io, Data1)
end;
output_to_file(Detail, Data, From, _) ->
test_server_io:print(From, Detail, Data).
diff --git a/lib/test_server/src/test_server_h.erl b/lib/test_server/src/test_server_h.erl
index c624947306..24063ddb10 100644
--- a/lib/test_server/src/test_server_h.erl
+++ b/lib/test_server/src/test_server_h.erl
@@ -142,7 +142,7 @@ report_receiver(_, _) -> none.
tag({M,F,A}) when is_atom(M), is_atom(F), is_integer(A) ->
io:format(user, "~n=TESTCASE: ~w:~w/~w", [M,F,A]);
tag(Testcase) ->
- io:format(user, "~n=TESTCASE: ~tp", [Testcase]).
+ io:format(user, "~n=TESTCASE: ~p", [Testcase]).
tag_event(Event) ->
{calendar:local_time(), Event}.
diff --git a/lib/test_server/src/test_server_io.erl b/lib/test_server/src/test_server_io.erl
index 662ee11515..242c08f765 100644
--- a/lib/test_server/src/test_server_io.erl
+++ b/lib/test_server/src/test_server_io.erl
@@ -235,7 +235,7 @@ handle_info(kill_group_leaders, #st{gls=Gls,stopping=From}=St) ->
gen_server:reply(From, ok),
{stop,normal,St};
handle_info(Other, St) ->
- io:format("Ignoring: ~tp\n", [Other]),
+ io:format("Ignoring: ~p\n", [Other]),
{noreply,St}.
terminate(_, _) ->
@@ -261,7 +261,7 @@ do_output(stdout, Str0, #st{job_name=Name}) ->
do_output(Tag, Str, #st{fds=Fds}=St) ->
case gb_trees:lookup(Tag, Fds) of
none ->
- S = io_lib:format("\n*** ERROR: ~w, line ~w: No known '~tp' log file\n",
+ S = io_lib:format("\n*** ERROR: ~w, line ~w: No known '~p' log file\n",
[?MODULE,?LINE,Tag]),
do_output(stdout, [S,Str], St);
{value,Fd} ->
@@ -273,7 +273,7 @@ do_output(Tag, Str, #st{fds=Fds}=St) ->
end
catch _:Error ->
S = io_lib:format("\n*** ERROR: ~w, line ~w: Error writing to "
- "log file '~tp': ~tp\n",
+ "log file '~p': ~p\n",
[?MODULE,?LINE,Tag,Error]),
do_output(stdout, [S,Str], St)
end
diff --git a/lib/test_server/src/test_server_node.erl b/lib/test_server/src/test_server_node.erl
index 62248af4db..54a49b31ca 100644
--- a/lib/test_server/src/test_server_node.erl
+++ b/lib/test_server/src/test_server_node.erl
@@ -249,7 +249,7 @@ print_trc(Out,{trace_ts,P,call,{M,F,A},C,Ts},N) ->
"~w: ~s~n"
"Process : ~w~n"
"Call : ~w:~w/~w~n"
- "Arguments : ~tp~n"
+ "Arguments : ~p~n"
"Caller : ~w~n~n",
[N,ts(Ts),P,M,F,length(A),A,C]);
print_trc(Out,{trace_ts,P,call,{M,F,A},Ts},N) ->
@@ -257,14 +257,14 @@ print_trc(Out,{trace_ts,P,call,{M,F,A},Ts},N) ->
"~w: ~s~n"
"Process : ~w~n"
"Call : ~w:~w/~w~n"
- "Arguments : ~tp~n~n",
+ "Arguments : ~p~n~n",
[N,ts(Ts),P,M,F,length(A),A]);
print_trc(Out,{trace_ts,P,return_from,{M,F,A},R,Ts},N) ->
io:format(Out,
"~w: ~s~n"
"Process : ~w~n"
"Return from : ~w:~w/~w~n"
- "Return value : ~tp~n~n",
+ "Return value : ~p~n~n",
[N,ts(Ts),P,M,F,A,R]);
print_trc(Out,{drop,X},N) ->
io:format(Out,
@@ -274,7 +274,7 @@ print_trc(Out,Trace,N) ->
Ts = element(size(Trace),Trace),
io:format(Out,
"~w: ~s~n"
- "Trace : ~tp~n~n",
+ "Trace : ~p~n~n",
[N,ts(Ts),Trace]).
ts({_, _, Micro} = Now) ->
{{Y,M,D},{H,Min,S}} = calendar:now_to_local_time(Now),
@@ -465,8 +465,8 @@ handle_start_node_return(Version,VsnStr,{started, Node, OVersion, OVsnStr}) ->
Str = io_lib:format("WARNING: Started node "
"reports different system "
"version than current node! "
- "Current node version: ~tp, ~tp "
- "Started node version: ~tp, ~tp",
+ "Current node version: ~p, ~p "
+ "Started node version: ~p, ~p",
[Version, VsnStr,
OVersion, OVsnStr]),
Str1 = lists:flatten(Str),
diff --git a/lib/test_server/src/test_server_sup.erl b/lib/test_server/src/test_server_sup.erl
index cd96568970..377aa21018 100644
--- a/lib/test_server/src/test_server_sup.erl
+++ b/lib/test_server/src/test_server_sup.erl
@@ -75,7 +75,7 @@ timetrap(Timeout0, ReportTVal, Scale, Pid) ->
"Testcase process ~w not "
"responding to timetrap "
"timeout:~n"
- " ~tp.~n"
+ " ~p.~n"
"Killing testcase...~n",
[Pid, Trap]),
exit(Pid, kill)
@@ -142,11 +142,11 @@ call_crash(Time,Crash,M,F,A) ->
{'EXIT',Pid,_Reason} when Crash==any ->
ok;
{'EXIT',Reason} ->
- test_server:format(12, "Wrong crash reason. Wanted ~tp, got ~tp.",
+ test_server:format(12, "Wrong crash reason. Wanted ~p, got ~p.",
[Crash, Reason]),
exit({wrong_crash_reason,Reason});
{'EXIT',Pid,Reason} ->
- test_server:format(12, "Wrong crash reason. Wanted ~tp, got ~tp.",
+ test_server:format(12, "Wrong crash reason. Wanted ~p, got ~p.",
[Crash, Reason]),
exit({wrong_crash_reason,Reason});
{'EXIT',OtherPid,Reason} when OldTrapExit == false ->
@@ -312,7 +312,7 @@ check_dict(Dict, Reason) ->
[] ->
1; % All ok.
List ->
- io:format("** ~ts (~ts) ->~n~tp~n",[Reason, Dict, List]),
+ io:format("** ~ts (~ts) ->~n~p~n",[Reason, Dict, List]),
0
end.
@@ -321,7 +321,7 @@ check_dict_tolerant(Dict, Reason, Mode) ->
[] ->
1; % All ok.
List ->
- io:format("** ~ts (~ts) ->~n~tp~n",[Reason, Dict, List]),
+ io:format("** ~ts (~ts) ->~n~p~n",[Reason, Dict, List]),
case Mode of
pedantic ->
0;
@@ -397,7 +397,7 @@ append_files_to_logfile([File|Files]) ->
%% fail, but in that case it will throw an exception so that
%% we will be aware of the problem.
io:format(Fd, "Unable to write the crash dump "
- "to this file: ~tp~n", [file:format_error(Error)])
+ "to this file: ~p~n", [file:format_error(Error)])
end;
_Error ->
io:format(Fd, "Failed to read: ~ts\n", [File])
@@ -555,7 +555,7 @@ format_loc([{Mod,LineOrFunc}]) ->
format_loc({Mod,Func}) when is_atom(Func) ->
io_lib:format("{~w,~w}",[Mod,Func]);
format_loc(Loc) ->
- io_lib:format("~tp",[Loc]).
+ io_lib:format("~p",[Loc]).
format_loc1([{Mod,Func,Line}]) ->
[" ",format_loc1({Mod,Func,Line}),"]"];
diff --git a/lib/tools/src/cover.erl b/lib/tools/src/cover.erl
index 468225dc13..2579711dc7 100644
--- a/lib/tools/src/cover.erl
+++ b/lib/tools/src/cover.erl
@@ -1372,10 +1372,15 @@ do_compile_beam(Module,Beam,UserOptions) ->
Forms0 = epp:interpret_file_attribute(Code),
{Forms,Vars} = transform(Vsn, Forms0, Module, Beam),
+ %% We need to recover the source from the compilation
+ %% info otherwise the newly compiled module will have
+ %% source pointing to the current directory
+ SourceInfo = get_source_info(Module, Beam),
+
%% Compile and load the result
%% It's necessary to check the result of loading since it may
%% fail, for example if Module resides in a sticky directory
- {ok, Module, Binary} = compile:forms(Forms, UserOptions),
+ {ok, Module, Binary} = compile:forms(Forms, SourceInfo ++ UserOptions),
case code:load_binary(Module, ?TAG, Binary) of
{module, Module} ->
@@ -1403,6 +1408,17 @@ get_abstract_code(Module, Beam) ->
Error -> Error
end.
+get_source_info(Module, Beam) ->
+ case beam_lib:chunks(Beam, [compile_info]) of
+ {ok, {Module, [{compile_info, Compile}]}} ->
+ case lists:keyfind(source, 1, Compile) of
+ { source, _ } = Tuple -> [Tuple];
+ false -> []
+ end;
+ _ ->
+ []
+ end.
+
transform(Vsn, Code, Module, Beam) when Vsn=:=abstract_v1; Vsn=:=abstract_v2 ->
Vars0 = #vars{module=Module, vsn=Vsn},
MainFile=find_main_filename(Code),
@@ -1783,17 +1799,11 @@ munge_expr({'catch',Line,Expr}, Vars) ->
{MungedExpr, Vars2} = munge_expr(Expr, Vars),
{{'catch',Line,MungedExpr}, Vars2};
munge_expr({call,Line1,{remote,Line2,ExprM,ExprF},Exprs},
- Vars) when Vars#vars.is_guard=:=false->
+ Vars) ->
{MungedExprM, Vars2} = munge_expr(ExprM, Vars),
{MungedExprF, Vars3} = munge_expr(ExprF, Vars2),
{MungedExprs, Vars4} = munge_exprs(Exprs, Vars3, []),
{{call,Line1,{remote,Line2,MungedExprM,MungedExprF},MungedExprs}, Vars4};
-munge_expr({call,Line1,{remote,_Line2,_ExprM,ExprF},Exprs},
- Vars) when Vars#vars.is_guard=:=true ->
- %% Difference in abstract format after preprocessing: BIF calls in guards
- %% are translated to {remote,...} (which is not allowed as source form)
- %% NOT NECESSARY FOR Vsn=raw_abstract_v1
- munge_expr({call,Line1,ExprF,Exprs}, Vars);
munge_expr({call,Line,Expr,Exprs}, Vars) ->
{MungedExpr, Vars2} = munge_expr(Expr, Vars),
{MungedExprs, Vars3} = munge_exprs(Exprs, Vars2, []),
@@ -1945,7 +1955,7 @@ move_clauses([]) ->
%% Given a .beam file, find the .erl file. Look first in same directory as
%% the .beam file, then in <beamdir>/../src
-find_source(File0) ->
+find_source(Module, File0) ->
case filename:rootname(File0,".beam") of
File0 ->
File0;
@@ -1962,11 +1972,27 @@ find_source(File0) ->
true ->
InDotDotSrc;
false ->
- {beam,File0}
+ find_source_from_module(Module, File0)
end
end
end.
+%% In case we can't find the file from the given .beam,
+%% we try to get the information directly from the module source
+find_source_from_module(Module, File) ->
+ Compile = Module:module_info(compile),
+ case lists:keyfind(source, 1, Compile) of
+ {source, Path} ->
+ case filelib:is_file(Path) of
+ true ->
+ Path;
+ false ->
+ {beam, File}
+ end;
+ false ->
+ {beam, File}
+ end.
+
do_parallel_analysis(Module, Analysis, Level, Loaded, From, State) ->
analyse_info(Module,State#main_state.imported),
C = case Loaded of
@@ -2070,7 +2096,7 @@ do_parallel_analysis_to_file(Module, OutFile, Opts, Loaded, From, State) ->
{imported, File0, _} ->
File0
end,
- case find_source(File) of
+ case find_source(Module, File) of
{beam,_BeamFile} ->
reply(From, {error,no_source_code_found});
ErlFile ->
diff --git a/lib/tools/test/cover_SUITE.erl b/lib/tools/test/cover_SUITE.erl
index 57260a3869..5abc5c41b1 100644
--- a/lib/tools/test/cover_SUITE.erl
+++ b/lib/tools/test/cover_SUITE.erl
@@ -149,7 +149,9 @@ compile(Config) when is_list(Config) ->
ok = beam_lib:crypto_key_fun(simple_crypto_fun(Key)),
{ok,crypt} = cover:compile_beam("crypt.beam")
end,
+ Path = filename:join([?config(data_dir, Config), "compile_beam", "v.erl"]),
?line {ok,v} = cover:compile_beam(v),
+ {source,Path} = lists:keyfind(source, 1, v:module_info(compile)),
?line {ok,w} = cover:compile_beam("w.beam"),
?line {error,{no_abstract_code,"./x.beam"}} = cover:compile_beam(x),
?line {error,{already_cover_compiled,no_beam_found,a}}=cover:compile_beam(a),
@@ -277,12 +279,23 @@ analyse(Config) when is_list(Config) ->
?line f:f2(),
?line {ok, "f.COVER.out"} = cover:analyse_to_file(f),
- %% Source code cannot be found by analyse_to_file
+ %% Source code can be found via source
?line {ok,v} = compile:file("compile_beam/v",[debug_info]),
?line code:purge(v),
?line {module,v} = code:load_file(v),
?line {ok,v} = cover:compile_beam(v),
- ?line {error,no_source_code_found} = cover:analyse_to_file(v),
+ {ok,"v.COVER.out"} = cover:analyse_to_file(v),
+
+ %% Source code cannot be found
+ {ok,_} = file:copy("compile_beam/z.erl", "z.erl"),
+ {ok,z} = compile:file(z,[debug_info]),
+ code:purge(z),
+ {module,z} = code:load_file(z),
+ {ok,z} = cover:compile_beam(z),
+ ok = file:delete("z.erl"),
+ {error,no_source_code_found} = cover:analyse_to_file(z),
+ code:purge(z),
+ code:delete(z),
?line {error,{not_cover_compiled,b}} = cover:analyse(b),
?line {error,{not_cover_compiled,g}} = cover:analyse(g),
diff --git a/lib/tools/test/cover_SUITE_data/compile_beam/v.erl b/lib/tools/test/cover_SUITE_data/compile_beam/v.erl
index 007957297a..7fb0b08d40 100644
--- a/lib/tools/test/cover_SUITE_data/compile_beam/v.erl
+++ b/lib/tools/test/cover_SUITE_data/compile_beam/v.erl
@@ -1,6 +1,9 @@
-module(v).
-
--export([f/0]).
+-compile({ no_auto_import, [is_integer/1] }).
+-export([f/0,f/1]).
f() ->
ok.
+
+f(Number) when erlang:is_integer(Number) ->
+ Number.
diff --git a/lib/tools/test/cover_SUITE_data/compile_beam/z.erl b/lib/tools/test/cover_SUITE_data/compile_beam/z.erl
new file mode 100644
index 0000000000..7a2b143dde
--- /dev/null
+++ b/lib/tools/test/cover_SUITE_data/compile_beam/z.erl
@@ -0,0 +1 @@
+-module(z).
diff --git a/lib/tools/vsn.mk b/lib/tools/vsn.mk
index 892a425124..4fb2f30e4f 100644
--- a/lib/tools/vsn.mk
+++ b/lib/tools/vsn.mk
@@ -1 +1 @@
-TOOLS_VSN = 2.6.9
+TOOLS_VSN = 2.6.10