You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by ma...@apache.org on 2011/08/10 21:16:05 UTC

[lucy-commits] svn commit: r1156321 - in /incubator/lucy/trunk: core/Lucy/Test/Util/TestJson.c core/Lucy/Util/Json.cfh perl/lib/Lucy.pm

Author: marvin
Date: Wed Aug 10 19:16:05 2011
New Revision: 1156321

URL: http://svn.apache.org/viewvc?rev=1156321&view=rev
Log:
Change to_json() and from_json() to set Err_error and return NULL on failure.
Add tests for invalid JSON.

Modified:
    incubator/lucy/trunk/core/Lucy/Test/Util/TestJson.c
    incubator/lucy/trunk/core/Lucy/Util/Json.cfh
    incubator/lucy/trunk/perl/lib/Lucy.pm

Modified: incubator/lucy/trunk/core/Lucy/Test/Util/TestJson.c
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/core/Lucy/Test/Util/TestJson.c?rev=1156321&r1=1156320&r2=1156321&view=diff
==============================================================================
--- incubator/lucy/trunk/core/Lucy/Test/Util/TestJson.c (original)
+++ incubator/lucy/trunk/core/Lucy/Test/Util/TestJson.c Wed Aug 10 19:16:05 2011
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <string.h>
 #include "Lucy/Util/ToolSet.h"
 
 #include "Lucy/Test.h"
@@ -32,6 +33,17 @@ S_make_dump() {
     return (Obj*)dump;
 }
 
+static void
+test_tolerance(TestBatch *batch) {
+    CharBuf *foo = CB_newf("foo");
+    CharBuf *not_json = Json_to_json((Obj*)foo);
+    TEST_TRUE(batch, not_json == NULL,
+              "to_json returns NULL when fed invalid data type");
+    TEST_TRUE(batch, Err_get_error() != NULL,
+              "to_json sets Err_error when fed invalid data type");
+    DECREF(foo);
+}
+
 // Test escapes for control characters ASCII 0-31.
 static char* control_escapes[] = {
     "\\u0000",
@@ -226,20 +238,59 @@ test_spew_and_slurp(TestBatch *batch) {
     DECREF(folder);
 }
 
+static void
+S_verify_bad_syntax(TestBatch *batch, const char *bad, const char *mess) {
+    ZombieCharBuf *has_errors = ZCB_WRAP_STR(bad, strlen(bad));
+    Err_set_error(NULL);
+    Obj *not_json = Json_from_json((CharBuf*)has_errors);
+    TEST_TRUE(batch, not_json == NULL, "from_json returns NULL: %s", mess);
+    TEST_TRUE(batch, Err_get_error() != NULL, "from_json sets Err_error: %s",
+              mess);
+}
+
+static void
+test_syntax_errors(TestBatch *batch) {
+    S_verify_bad_syntax(batch, "[", "unclosed left bracket");
+    S_verify_bad_syntax(batch, "]", "unopened right bracket");
+    S_verify_bad_syntax(batch, "{", "unclosed left curly");
+    S_verify_bad_syntax(batch, "}", "unopened right curly");
+    S_verify_bad_syntax(batch, "{}[]", "two top-level objects");
+    S_verify_bad_syntax(batch, "[1 \"foo\"]", "missing comma in array");
+    S_verify_bad_syntax(batch, "[1, \"foo\",]", "extra comma in array");
+    S_verify_bad_syntax(batch, "{\"1\":1 \"2\":2}", "missing comma in hash");
+    S_verify_bad_syntax(batch, "{\"1\":1,\"2\":2,}", "extra comma in hash");
+    S_verify_bad_syntax(batch, "\"1", "unterminated string");
+    // Tolerated by strtod().
+    // S_verify_bad_syntax(batch, "1. ", "float missing fraction");
+    // S_verify_bad_syntax(batch, "-.3 ", "Number missing integral part");
+    S_verify_bad_syntax(batch, "-. ", "Number missing any digits");
+    S_verify_bad_syntax(batch, "+1.0 ", "float with prepended plus");
+    S_verify_bad_syntax(batch, "\"\\g\"", "invalid char escape");
+    S_verify_bad_syntax(batch, "\"\\uAAAZ\"", "invalid \\u escape");
+}
+
 void
 TestJson_run_tests() {
-    TestBatch *batch = TestBatch_new(92);
+    int num_tests = 94;
+#ifndef LUCY_VALGRIND
+    num_tests += 28; // FIXME: syntax errors leak memory.
+#endif
+    TestBatch *batch = TestBatch_new(num_tests);
+    TestBatch_Plan(batch);
 
-    // Liberalize for testing.
+    // Test tolerance, then liberalize for testing.
+    test_tolerance(batch);
     Json_set_tolerant(true);
 
-    TestBatch_Plan(batch);
     test_to_and_from(batch);
     test_escapes(batch);
     test_numbers(batch);
     test_spew_and_slurp(batch);
 
+#ifndef LUCY_VALGRIND
+    test_syntax_errors(batch);
+#endif
+
     DECREF(batch);
 }
 
-

Modified: incubator/lucy/trunk/core/Lucy/Util/Json.cfh
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/core/Lucy/Util/Json.cfh?rev=1156321&r1=1156320&r2=1156321&view=diff
==============================================================================
--- incubator/lucy/trunk/core/Lucy/Util/Json.cfh (original)
+++ incubator/lucy/trunk/core/Lucy/Util/Json.cfh Wed Aug 10 19:16:05 2011
@@ -22,15 +22,17 @@ parcel Lucy;
  */
 class Lucy::Util::Json inherits Lucy::Object::Obj {
 
-    /** Encode <code>dump</code> as JSON.
+    /** Encode <code>dump</code> as JSON.  Returns NULL and sets Err_error on
+     * failure.
      */
-    inert incremented CharBuf*
+    inert incremented nullable CharBuf*
     to_json(Obj *dump);
 
     /** Decode the supplied JSON and return a data structure made
-     * of Hashes, VArrays, and CharBufs.
+     * of Hashes, VArrays, and CharBufs.  Returns NULL and sets Err_error on
+     * failure.
      */
-    inert incremented Obj*
+    inert incremented nullable Obj*
     from_json(CharBuf *json);
 
     /** Encode <code>dump</code> as JSON and attempt to write to the indicated

Modified: incubator/lucy/trunk/perl/lib/Lucy.pm
URL: http://svn.apache.org/viewvc/incubator/lucy/trunk/perl/lib/Lucy.pm?rev=1156321&r1=1156320&r2=1156321&view=diff
==============================================================================
--- incubator/lucy/trunk/perl/lib/Lucy.pm (original)
+++ incubator/lucy/trunk/perl/lib/Lucy.pm Wed Aug 10 19:16:05 2011
@@ -577,11 +577,23 @@ sub error {$Lucy::Object::Err::error}
 
     sub to_json {
         my ( undef, $dump ) = @_;
-        return $json_encoder->encode($dump);
+        my $json = eval { $json_encoder->encode($dump) };
+        if ($@) {
+            my $error = Lucy::Object::Err->new($@);
+            Lucy::Object::Err->set_error($error);
+            return;
+        }
+        return $json;
     }
 
     sub from_json {
-        return to_clownfish( $json_encoder->decode( $_[1] ) );
+        my $dump = eval { to_clownfish( $json_encoder->decode( $_[1] ) ) };
+        if ($@) {
+            my $error = Lucy::Object::Err->new($@);
+            Lucy::Object::Err->set_error($error);
+            return;
+        }
+        return $dump;
     }
 
     sub set_tolerant { $json_encoder->allow_nonref( $_[1] ) }