couchdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kxe...@apache.org
Subject [21/54] jiffy commit: updated refs/heads/master to ef77de4
Date Tue, 28 Jul 2015 22:42:46 GMT
Improved encoder errors

This updates encoder errors to report the actual Erlang value that
caused the error. This should make it easier to debug errors when
generating JSON.


Project: http://git-wip-us.apache.org/repos/asf/couchdb-jiffy/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-jiffy/commit/f9095c52
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-jiffy/tree/f9095c52
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-jiffy/diff/f9095c52

Branch: refs/heads/master
Commit: f9095c52581867938e1ea1eb695235994f585e89
Parents: 5eb499d
Author: Paul J. Davis <paul.joseph.davis@gmail.com>
Authored: Sat Aug 23 05:47:59 2014 -0500
Committer: Paul J. Davis <paul.joseph.davis@gmail.com>
Committed: Sat Aug 23 06:41:25 2014 -0500

----------------------------------------------------------------------
 c_src/encoder.c                | 30 ++++++++-----
 c_src/jiffy.h                  |  2 +
 c_src/util.c                   |  8 ++++
 src/jiffy.erl                  |  6 ++-
 test/jiffy_04_string_tests.erl |  2 +-
 test/jiffy_12_error_tests.erl  | 87 +++++++++++++++++++++++++++++++++++++
 6 files changed, 120 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-jiffy/blob/f9095c52/c_src/encoder.c
----------------------------------------------------------------------
diff --git a/c_src/encoder.c b/c_src/encoder.c
index 992b5d5..ac4935d 100644
--- a/c_src/encoder.c
+++ b/c_src/encoder.c
@@ -122,6 +122,12 @@ enc_error(Encoder* e, const char* msg)
     return make_error(e->atoms, e->env, msg);
 }
 
+ERL_NIF_TERM
+enc_obj_error(Encoder* e, const char* msg, ERL_NIF_TERM obj)
+{
+    return make_obj_error(e->atoms, e->env, msg, obj);
+}
+
 static inline int
 enc_ensure(Encoder* e, size_t req)
 {
@@ -667,11 +673,11 @@ encode_iter(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
                 goto done;
             }
             if(!enif_get_tuple(env, item, &arity, &tuple)) {
-                ret = enc_error(e, "invalid_object_pair");
+                ret = enc_obj_error(e, "invalid_object_member", item);
                 goto done;
             }
             if(arity != 2) {
-                ret = enc_error(e, "invalid_object_pair");
+                ret = enc_obj_error(e, "invalid_object_member_arity", item);
                 goto done;
             }
             if(!enc_comma(e)) {
@@ -679,7 +685,7 @@ encode_iter(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
                 goto done;
             }
             if(!enc_string(e, tuple[0])) {
-                ret = enc_error(e, "invalid_object_key");
+                ret = enc_obj_error(e, "invalid_object_member_key", tuple[0]);
                 goto done;
             }
             if(!enc_colon(e)) {
@@ -712,12 +718,12 @@ encode_iter(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
             stack = enif_make_list_cell(env, curr, stack);
             stack = enif_make_list_cell(env, e->atoms->ref_array, stack);
             stack = enif_make_list_cell(env, item, stack);
-        } else if(enif_compare(curr, e->atoms->atom_null) == 0 
+        } else if(enif_compare(curr, e->atoms->atom_null) == 0) {
             if(!enc_literal(e, "null", 4)) {
                 ret = enc_error(e, "null");
                 goto done;
             }
-        } else if(e->use_nil && enif_compare(curr, e->atoms->atom_nil) ==
0)) {
+        } else if(e->use_nil && enif_compare(curr, e->atoms->atom_nil) ==
0) {
             if(!enc_literal(e, "null", 4)) {
                 ret = enc_error(e, "null");
                 goto done;
@@ -734,12 +740,12 @@ encode_iter(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
             }
         } else if(enif_is_binary(env, curr)) {
             if(!enc_string(e, curr)) {
-                ret = enc_error(e, "invalid_string");
+                ret = enc_obj_error(e, "invalid_string", curr);
                 goto done;
             }
         } else if(enif_is_atom(env, curr)) {
             if(!enc_string(e, curr)) {
-                ret = enc_error(e, "invalid_string");
+                ret = enc_obj_error(e, "invalid_string", curr);
                 goto done;
             }
         } else if(enif_get_int64(env, curr, &lval)) {
@@ -754,11 +760,11 @@ encode_iter(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
             }
         } else if(enif_get_tuple(env, curr, &arity, &tuple)) {
             if(arity != 1) {
-                ret = enc_error(e, "invalid_ejson");
+                ret = enc_obj_error(e, "invalid_ejson", curr);
                 goto done;
             }
             if(!enif_is_list(env, tuple[0])) {
-                ret = enc_error(e, "invalid_object");
+                ret = enc_obj_error(e, "invalid_object", curr);
                 goto done;
             }
             if(!enc_start_object(e)) {
@@ -777,15 +783,15 @@ encode_iter(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
                 goto done;
             }
             if(!enif_get_tuple(env, item, &arity, &tuple)) {
-                ret = enc_error(e, "invalid_object_member");
+                ret = enc_obj_error(e, "invalid_object_member", item);
                 goto done;
             }
             if(arity != 2) {
-                ret = enc_error(e, "invalid_object_member_arity");
+                ret = enc_obj_error(e, "invalid_object_member_arity", item);
                 goto done;
             }
             if(!enc_string(e, tuple[0])) {
-                ret = enc_error(e, "invalid_object_member_key");
+                ret = enc_obj_error(e, "invalid_object_member_key", tuple[0]);
                 goto done;
             }
             if(!enc_colon(e)) {

http://git-wip-us.apache.org/repos/asf/couchdb-jiffy/blob/f9095c52/c_src/jiffy.h
----------------------------------------------------------------------
diff --git a/c_src/jiffy.h b/c_src/jiffy.h
index 34dff75..6d869a5 100644
--- a/c_src/jiffy.h
+++ b/c_src/jiffy.h
@@ -41,6 +41,8 @@ typedef struct {
 ERL_NIF_TERM make_atom(ErlNifEnv* env, const char* name);
 ERL_NIF_TERM make_ok(jiffy_st* st, ErlNifEnv* env, ERL_NIF_TERM data);
 ERL_NIF_TERM make_error(jiffy_st* st, ErlNifEnv* env, const char* error);
+ERL_NIF_TERM make_obj_error(jiffy_st* st, ErlNifEnv* env, const char* error,
+        ERL_NIF_TERM obj);
 int get_bytes_per_iter(ErlNifEnv* env, ERL_NIF_TERM val, size_t* bpi);
 int should_yield(size_t used, size_t limit);
 int consume_timeslice(ErlNifEnv* env, size_t used, size_t limit);

http://git-wip-us.apache.org/repos/asf/couchdb-jiffy/blob/f9095c52/c_src/util.c
----------------------------------------------------------------------
diff --git a/c_src/util.c b/c_src/util.c
index 7436add..c30a6d7 100644
--- a/c_src/util.c
+++ b/c_src/util.c
@@ -25,6 +25,14 @@ make_error(jiffy_st* st, ErlNifEnv* env, const char* error)
     return enif_make_tuple2(env, st->atom_error, make_atom(env, error));
 }
 
+ERL_NIF_TERM
+make_obj_error(jiffy_st* st, ErlNifEnv* env,
+        const char* error, ERL_NIF_TERM obj)
+{
+    ERL_NIF_TERM reason = enif_make_tuple2(env, make_atom(env, error), obj);
+    return enif_make_tuple2(env, st->atom_error, reason);
+}
+
 int
 get_bytes_per_iter(ErlNifEnv* env, ERL_NIF_TERM val, size_t* bpi)
 {

http://git-wip-us.apache.org/repos/asf/couchdb-jiffy/blob/f9095c52/src/jiffy.erl
----------------------------------------------------------------------
diff --git a/src/jiffy.erl b/src/jiffy.erl
index 8903831..9642b25 100644
--- a/src/jiffy.erl
+++ b/src/jiffy.erl
@@ -34,7 +34,7 @@ encode(Data) ->
 encode(Data, Options) ->
     ForceUTF8 = lists:member(force_utf8, Options),
     case nif_encode_init(Data, Options) of
-        {error, invalid_string} when ForceUTF8 == true ->
+        {error, {invalid_string, _}} when ForceUTF8 == true ->
             FixedData = jiffy_utf8:fix(Data),
             encode(FixedData, Options -- [force_utf8]);
         {error, _} = Error ->
@@ -102,6 +102,8 @@ finish_encode([<<_/binary>>=B | Rest], Acc) ->
 finish_encode([Val | Rest], Acc) when is_integer(Val) ->
     Bin = list_to_binary(integer_to_list(Val)),
     finish_encode(Rest, [Bin | Acc]);
+finish_encode([InvalidEjson | _], _) ->
+    throw({error, {invalid_ejson, InvalidEjson}});
 finish_encode(_, _) ->
     throw({error, invalid_ejson}).
 
@@ -134,7 +136,7 @@ decode_loop(Data, Decoder, Objs, Curr) ->
 encode_loop(Data, Options, Encoder, Stack, IOBuf) ->
     ForceUTF8 = lists:member(force_utf8, Options),
     case nif_encode_iter(Encoder, Stack, IOBuf) of
-        {error, invalid_string} when ForceUTF8 == true ->
+        {error, {invalid_string, _}} when ForceUTF8 == true ->
             FixedData = jiffy_utf8:fix(Data),
             encode(FixedData, Options -- [force_utf8]);
         {error, _} = Error ->

http://git-wip-us.apache.org/repos/asf/couchdb-jiffy/blob/f9095c52/test/jiffy_04_string_tests.erl
----------------------------------------------------------------------
diff --git a/test/jiffy_04_string_tests.erl b/test/jiffy_04_string_tests.erl
index 46f15ff..7238f7c 100644
--- a/test/jiffy_04_string_tests.erl
+++ b/test/jiffy_04_string_tests.erl
@@ -48,7 +48,7 @@ gen(utf8, {Case, Fixed}) ->
     Case2 = <<34, Case/binary, 34>>,
     Fixed2 = <<34, Fixed/binary, 34>>,
     {msg("UTF-8: ~s", [hex(Case)]), [
-        ?_assertThrow({error, invalid_string}, jiffy:encode(Case)),
+        ?_assertThrow({error, {invalid_string, _}}, jiffy:encode(Case)),
         ?_assertEqual(Fixed2, jiffy:encode(Case, [force_utf8])),
         ?_assertThrow({error, {_, invalid_string}}, jiffy:decode(Case2))
     ]}.

http://git-wip-us.apache.org/repos/asf/couchdb-jiffy/blob/f9095c52/test/jiffy_12_error_tests.erl
----------------------------------------------------------------------
diff --git a/test/jiffy_12_error_tests.erl b/test/jiffy_12_error_tests.erl
new file mode 100644
index 0000000..a7d4ed6
--- /dev/null
+++ b/test/jiffy_12_error_tests.erl
@@ -0,0 +1,87 @@
+% This file is part of Jiffy released under the MIT license.
+% See the LICENSE file for more information.
+
+-module(jiffy_12_error_tests).
+
+-include_lib("eunit/include/eunit.hrl").
+
+
+enc_invalid_ejson_test_() ->
+    Type = invalid_ejson,
+    Ref = make_ref(),
+    {"invalid_ejson", [
+        {"Basic", enc_error(Type, Ref, Ref)},
+        {"Nested", enc_error(Type, {Ref, Ref}, {Ref, Ref})}
+    ]}.
+
+
+enc_invalid_string_test_() ->
+    Type = invalid_string,
+    {"invalid_string", [
+        {"Bare strign", enc_error(Type, <<143>>, <<143>>)},
+        {"List element", enc_error(Type, <<143>>, [<<143>>])},
+        {"Bad obj value", enc_error(Type, <<143>>, {[{foo, <<143>>}]})}
+    ]}.
+
+enc_invalid_object_test_() ->
+    Type = invalid_object,
+    Ref = make_ref(),
+    {"invalid_object", [
+        {"Number", enc_error(Type, {1}, {1})},
+        {"Ref", enc_error(Type, {Ref}, {Ref})},
+        {"Tuple", enc_error(Type, {{[]}}, {{[]}})},
+        {"Atom", enc_error(Type, {foo}, {foo})}
+    ]}.
+
+
+enc_invalid_object_member_test_() ->
+    Type = invalid_object_member,
+    {"invalid_object_member", [
+        {"Basic", enc_error(Type, foo, {[foo]})},
+        {"Basic", enc_error(Type, foo, {[{bar, baz}, foo]})},
+        {"Nested", enc_error(Type, foo, {[{bar,{[foo]}}]})},
+        {"Nested", enc_error(Type, foo, {[{bar,{[{baz, 1}, foo]}}]})},
+        {"In List", enc_error(Type, foo, [{[foo]}])},
+        {"In List", enc_error(Type, foo, [{[{bang, true}, foo]}])}
+    ]}.
+
+
+enc_invalid_object_member_arity_test_() ->
+    Type = invalid_object_member_arity,
+    E1 = {foo},
+    E2 = {x, y, z},
+    {"invalid_object_member", [
+        {"Basic", enc_error(Type, E1, {[E1]})},
+        {"Basic", enc_error(Type, E2, {[E2]})},
+        {"Basic", enc_error(Type, E1, {[{bar, baz}, E1]})},
+        {"Basic", enc_error(Type, E2, {[{bar, baz}, E2]})},
+        {"Nested", enc_error(Type, E1, {[{bar,{[E1]}}]})},
+        {"Nested", enc_error(Type, E2, {[{bar,{[E2]}}]})},
+        {"Nested", enc_error(Type, E1, {[{bar,{[{baz, 1}, E1]}}]})},
+        {"Nested", enc_error(Type, E2, {[{bar,{[{baz, 1}, E2]}}]})},
+        {"In List", enc_error(Type, E1, [{[E1]}])},
+        {"In List", enc_error(Type, E2, [{[E2]}])},
+        {"In List", enc_error(Type, E1, [{[{bang, true}, E1]}])},
+        {"In List", enc_error(Type, E2, [{[{bang, true}, E2]}])}
+    ]}.
+
+
+enc_invalid_object_member_key_test_() ->
+    Type = invalid_object_member_key,
+    E1 = {1, true},
+    {"invalid_object_member_key", [
+        {"Bad string", enc_error(Type, <<143>>, {[{<<143>>, true}]})},
+        {"Basic", enc_error(Type, 1, {[{1, true}]})},
+        {"Basic", enc_error(Type, [1], {[{[1], true}]})},
+        {"Basic", enc_error(Type, {[{foo,bar}]}, {[{{[{foo,bar}]}, true}]})},
+        {"Second", enc_error(Type, 1, {[{bar, baz}, E1]})},
+        {"Nested", enc_error(Type, 1, {[{bar,{[E1]}}]})},
+        {"Nested", enc_error(Type, 1, {[{bar,{[{baz, 1}, E1]}}]})},
+        {"In List", enc_error(Type, 1, [{[E1]}])},
+        {"In List", enc_error(Type, 1, [{[{bang, true}, E1]}])}
+    ]}.
+
+
+
+enc_error(Type, Obj, Case) ->
+    ?_assertEqual({error, {Type, Obj}}, (catch jiffy:encode(Case))).


Mime
View raw message