Skip to content

Commit

Permalink
Encode error stack in Erlang stacktrace
Browse files Browse the repository at this point in the history
  • Loading branch information
zmstone committed May 7, 2017
1 parent 19daa06 commit 732cd97
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 6 deletions.
15 changes: 15 additions & 0 deletions include/avro_internal.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,21 @@

-define(ERROR_IF_NOT(Cond, Err), ?ERROR_IF(not (Cond), Err)).

-define(ENC_ERR(Reason, Context),
{'$avro_encode_error', Reason, Context}).

-define(RAISE_ENC_ERR(EXCEPTION_CLASS, EXCEPTION_REASON, THIS_CONTEXT),
begin
Stack = erlang:get_stacktrace(),
{_Reason_, _Context_} =
case EXCEPTION_REASON of
?ENC_ERR(__Reason__, __Context__) ->
{__Reason__, THIS_CONTEXT ++ __Context__};
_ ->
{EXCEPTION_REASON, THIS_CONTEXT}
end,
erlang:raise(EXCEPTION_CLASS, ?ENC_ERR(_Reason_, _Context_), Stack)
end).
-endif.

%%%_* Emacs ====================================================================
Expand Down
2 changes: 1 addition & 1 deletion scripts/cover-print-not-covered-lines.escript
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env escript
%% -*- erlang -*-
%%! -smp enable -sname notcoveredlinessummary -pa ebin -pa ../ebin
%%! -pa ebin -pa ../ebin

%%%
%%% Copyright (c) 2015-2017, Klarna AB
Expand Down
6 changes: 5 additions & 1 deletion src/avro_map.erl
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,11 @@ cast(Type, Value) when ?IS_MAP_TYPE(Type) ->
encode(Type, Value, EncodeFun) ->
ItemsType = avro_map:get_items_type(Type),
lists:map(fun({K, V}) ->
EncodeFun(ItemsType, K, V)
try
EncodeFun(ItemsType, K, V)
catch
C : E -> ?RAISE_ENC_ERR(C, E, [Type, K])
end
end, Value).

%%%_* Internal Functions =======================================================
Expand Down
9 changes: 7 additions & 2 deletions src/avro_record.erl
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,6 @@ to_term(Record) when ?IS_RECORD_VALUE(Record) ->
lists:map(fun({N, V}) -> {N, avro:to_term(V)} end, to_list(Record)).

%% @hidden Help function for JSON/binary encoder.
%% TODO: better spec for Value and EncodeFun
-spec encode(record_type(), [{field_name_raw(), avro:in()}],
fun(({field_name(), avro_type(), avro:in()}) -> avro:out())) ->
[avro:out()].
Expand All @@ -243,7 +242,13 @@ encode(Type, Fields, EncodeFun) ->
TypeFullName = avro:get_type_fullname(Type),
TypeAndValueList = zip_record_field_types_with_key_value(
TypeFullName, FieldTypes, Fields),
lists:map(EncodeFun, TypeAndValueList).
lists:map(fun({FieldName, _FieldType, _FieldValue} = X) ->
try
EncodeFun(X)
catch
C : E -> ?RAISE_ENC_ERR(C, E, [TypeFullName, FieldName])
end
end, TypeAndValueList).

%%%_* Internal functions =======================================================

Expand Down
2 changes: 1 addition & 1 deletion src/erlavro.app.src
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{application, erlavro,
[
{description, "Apache Avro support for Erlang/Elixir"},
{vsn, "2.0.2"},
{vsn, "2.0.3"},
{registered, []},
{applications, [
kernel,
Expand Down
23 changes: 22 additions & 1 deletion test/avro_binary_encoder_tests.erl
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
, zigzag/2
]).

-include("erlavro.hrl").
-include("avro_internal.hrl").
-include_lib("eunit/include/eunit.hrl").

-define(TO_STRING(S), iolist_to_binary(S)).
Expand Down Expand Up @@ -123,6 +123,21 @@ encode_record_test() ->
],
?assertBinEq(Expected, BinRecord).

encode_record_error_test() ->
SubType =
avro_record:type("sub_rec",
[ define_field("bool_field", boolean, [])
, define_field("int_field", int, [])
]),
RootType =
avro_record:type("root_rec",
[ define_field("sub", SubType, [])
]),
In = [{sub, [{<<"bool_field">>, true}, {<<"int_field">>, "not int"}]}],
?assertError(?ENC_ERR(_, [<<"root_rec">>, <<"sub">>,
<<"sub_rec">>, <<"int_field">>]),
encode(fun(_) -> error(unexpected) end, RootType, In)).

encode_enum_test() ->
EnumType = avro_enum:type("TestEnum",
["SYMBOL_0", "SYMBOL_1", "SYMBOL_2",
Expand Down Expand Up @@ -153,6 +168,12 @@ encode_map_test() ->
Body = iolist_to_binary([string(a), int(3), string(<<"b">>), int(27)]),
?assertBinEq([long(-2), long(size(Body)), Body, 0], encode_value(TypedValue)).

encode_map_error_test() ->
Type = avro_map:type(int),
Value = [{a, 3}, {"b", "not int"}],
?assertError(?ENC_ERR(_, [Type, "b"]),
encode(fun(_) -> error(unexpected) end, Type, Value)).

encode_union_test() ->
Type = avro_union:type([null, string]),
Value1 = avro_union:new(Type, null),
Expand Down

0 comments on commit 732cd97

Please sign in to comment.