aboutsummaryrefslogtreecommitdiffstats
path: root/lib/asn1/test/testInfObjectClass.erl
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2017-02-15 14:23:59 +0100
committerBjörn Gustavsson <[email protected]>2017-02-21 15:33:43 +0100
commit3f7d4324c7b99f93a6ad36015071276692534fa1 (patch)
tree86ba678ba6eb9ee5512691ee55a68f894c1db1b6 /lib/asn1/test/testInfObjectClass.erl
parent57c1ecadd6e3ab6763b494e7a9509e67d0e6a661 (diff)
downloadotp-3f7d4324c7b99f93a6ad36015071276692534fa1.tar.gz
otp-3f7d4324c7b99f93a6ad36015071276692534fa1.tar.bz2
otp-3f7d4324c7b99f93a6ad36015071276692534fa1.zip
encode/decode: Include the stack trace in error returns
The generated encode/2 and decode/2 functions can return cryptic error messages. Consider this ASN.1 spec: T DEFINITIONS AUTOMATIC TAGS ::= BEGIN S ::= SEQUENCE { b BOOLEAN, i INTEGER (1..100), j INTEGER (0..7), s OCTET STRING } END In OTP 19, the error terms will look like this: Eshell V8.2 (abort with ^G) 1> asn1ct:compile('T', [ber]). ok 2> rr('T'). ['S'] 3> 'T':encode('S', #'S'{}). {error,{asn1,{encode_boolean,undefined}}} 4> 'T':encode('S', #'S'{b=false}). {error,{asn1,{encode_integer,undefined}}} 5> 'T':encode('S', #'S'{b=false,i=7,j=0}). {error,{asn1,function_clause}} Some error terms are clearer than other. In the first error term, it is clear that the error refers to the 'b' field, since there is only one BOOLEAN in 'S'. The second error term could refer to either 'i' or 'j'. The last error term... well... in this case we can infer that it must refer to 's'. The easiest way to provide more information is to include the stack trace with line numbers in the error term: 3> 'T':encode('S', #'S'{b=false}). {error,{asn1,{{encode_integer,undefined}, [{'T',encode_integer,2,[{file,"T.erl"},{line,240}]}, {'T',enc_S,2,[{file,"T.erl"},{line,102}]}, {'T',encode,2,[{file,"T.erl"},{line,36}]}, {erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,674}]}, {shell,exprs,7,[{file,"shell.erl"},{line,686}]}, {shell,eval_exprs,7,[{file,"shell.erl"},{line,641}]}, {shell,eval_loop,3,[{file,"shell.erl"},{line,626}]}]}}} By looking at the generated Erlang code, we can see that encoding failed for 'i'. This is an compatible change. All that the documentation says is that the format of the error tuple is: {error,{asn1,Description}} With this change, Description is always a tuple: {ErrorDescription,StackTrace} Alternatives considered: Providing more information in the error term itself and make sure there can be no 'function_clause', 'badarg', or 'badmatch' exceptions. That would be possible, but it would require a lot of work and it would increase the size of the generated code and make it slower. Therefore, this solution was rejected.
Diffstat (limited to 'lib/asn1/test/testInfObjectClass.erl')
-rw-r--r--lib/asn1/test/testInfObjectClass.erl22
1 files changed, 16 insertions, 6 deletions
diff --git a/lib/asn1/test/testInfObjectClass.erl b/lib/asn1/test/testInfObjectClass.erl
index 560986fac9..540407fa51 100644
--- a/lib/asn1/test/testInfObjectClass.erl
+++ b/lib/asn1/test/testInfObjectClass.erl
@@ -33,19 +33,29 @@ main(Rule) ->
roundtrip('Seq', Val),
%% OTP-5783
- {error,{asn1,{'Type not compatible with table constraint',
- {component,'ArgumentType'},
- {value,_},_}}} = 'InfClass':encode('Seq', {'Seq',12,13,1}),
+ {'Type not compatible with table constraint',
+ {component,'ArgumentType'},
+ {value,_},_} = enc_error('Seq', {'Seq',12,13,1}),
Bytes2 = case Rule of
ber ->
<<48,9,2,1,12,2,1,11,2,1,1>>;
_ ->
<<1,12,1,11,1,1>>
end,
- {error,{asn1,{'Type not compatible with table constraint',
- {{component,_},
- {value,_B},_}}}} = 'InfClass':decode('Seq', Bytes2),
+ {'Type not compatible with table constraint',
+ {{component,_},
+ {value,_B},_}} = dec_error('Seq', Bytes2),
ok.
roundtrip(T, V) ->
asn1_test_lib:roundtrip('InfClass', T, V).
+
+enc_error(T, V) ->
+ {error,{asn1,{Reason,Stk}}} = 'InfClass':encode(T, V),
+ [{_,_,_,_}|_] = Stk,
+ Reason.
+
+dec_error(T, Bin) ->
+ {error,{asn1,{Reason,Stk}}} = 'InfClass':decode(T, Bin),
+ [{_,_,_,_}|_] = Stk,
+ Reason.