Add a flag to JSONReader to allow trailing commas.

Lots of unittests for this behavior.

BUG=1295713

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@51 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/base/json_reader_unittest.cc b/base/json_reader_unittest.cc
index f218531..130c8e8 100644
--- a/base/json_reader_unittest.cc
+++ b/base/json_reader_unittest.cc
@@ -34,26 +34,26 @@
 TEST(JSONReaderTest, Reading) {
   // some whitespace checking
   Value* root = NULL;
-  ASSERT_TRUE(JSONReader::JsonToValue("   null   ", &root, false));
+  ASSERT_TRUE(JSONReader::JsonToValue("   null   ", &root, false, false));
   ASSERT_TRUE(root);
   ASSERT_TRUE(root->IsType(Value::TYPE_NULL));
   delete root;
 
   // Invalid JSON string
   root = NULL;
-  ASSERT_FALSE(JSONReader::JsonToValue("nu", &root, false));
+  ASSERT_FALSE(JSONReader::JsonToValue("nu", &root, false, false));
   ASSERT_FALSE(root);
 
   // Simple bool
   root = NULL;
-  ASSERT_TRUE(JSONReader::JsonToValue("true  ", &root, false));
+  ASSERT_TRUE(JSONReader::JsonToValue("true  ", &root, false, false));
   ASSERT_TRUE(root);
   ASSERT_TRUE(root->IsType(Value::TYPE_BOOLEAN));
   delete root;
 
   // Test number formats
   root = NULL;
-  ASSERT_TRUE(JSONReader::JsonToValue("43", &root, false));
+  ASSERT_TRUE(JSONReader::JsonToValue("43", &root, false, false));
   ASSERT_TRUE(root);
   ASSERT_TRUE(root->IsType(Value::TYPE_INTEGER));
   int int_val = 0;
@@ -63,19 +63,19 @@
 
   // According to RFC4627, oct, hex, and leading zeros are invalid JSON.
   root = NULL;
-  ASSERT_FALSE(JSONReader::JsonToValue("043", &root, false));
+  ASSERT_FALSE(JSONReader::JsonToValue("043", &root, false, false));
   ASSERT_FALSE(root);
   root = NULL;
-  ASSERT_FALSE(JSONReader::JsonToValue("0x43", &root, false));
+  ASSERT_FALSE(JSONReader::JsonToValue("0x43", &root, false, false));
   ASSERT_FALSE(root);
   root = NULL;
-  ASSERT_FALSE(JSONReader::JsonToValue("00", &root, false));
+  ASSERT_FALSE(JSONReader::JsonToValue("00", &root, false, false));
   ASSERT_FALSE(root);
 
   // Test 0 (which needs to be special cased because of the leading zero
   // clause).
   root = NULL;
-  ASSERT_TRUE(JSONReader::JsonToValue("0", &root, false));
+  ASSERT_TRUE(JSONReader::JsonToValue("0", &root, false, false));
   ASSERT_TRUE(root);
   ASSERT_TRUE(root->IsType(Value::TYPE_INTEGER));
   int_val = 1;
@@ -85,15 +85,15 @@
 
   // Numbers that overflow ints should fail
   root = NULL;
-  ASSERT_FALSE(JSONReader::JsonToValue("2147483648", &root, false));
+  ASSERT_FALSE(JSONReader::JsonToValue("2147483648", &root, false, false));
   ASSERT_FALSE(root);
   root = NULL;
-  ASSERT_FALSE(JSONReader::JsonToValue("-2147483649", &root, false));
+  ASSERT_FALSE(JSONReader::JsonToValue("-2147483649", &root, false, false));
   ASSERT_FALSE(root);
 
   // Parse a double
   root = NULL;
-  ASSERT_TRUE(JSONReader::JsonToValue("43.1", &root, false));
+  ASSERT_TRUE(JSONReader::JsonToValue("43.1", &root, false, false));
   ASSERT_TRUE(root);
   ASSERT_TRUE(root->IsType(Value::TYPE_REAL));
   double real_val = 0.0;
@@ -102,7 +102,7 @@
   delete root;
 
   root = NULL;
-  ASSERT_TRUE(JSONReader::JsonToValue("4.3e-1", &root, false));
+  ASSERT_TRUE(JSONReader::JsonToValue("4.3e-1", &root, false, false));
   ASSERT_TRUE(root);
   ASSERT_TRUE(root->IsType(Value::TYPE_REAL));
   real_val = 0.0;
@@ -111,7 +111,7 @@
   delete root;
 
   root = NULL;
-  ASSERT_TRUE(JSONReader::JsonToValue("2.1e0", &root, false));
+  ASSERT_TRUE(JSONReader::JsonToValue("2.1e0", &root, false, false));
   ASSERT_TRUE(root);
   ASSERT_TRUE(root->IsType(Value::TYPE_REAL));
   real_val = 0.0;
@@ -120,7 +120,7 @@
   delete root;
 
   root = NULL;
-  ASSERT_TRUE(JSONReader::JsonToValue("2.1e+0001", &root, false));
+  ASSERT_TRUE(JSONReader::JsonToValue("2.1e+0001", &root, false, false));
   ASSERT_TRUE(root);
   ASSERT_TRUE(root->IsType(Value::TYPE_REAL));
   real_val = 0.0;
@@ -129,7 +129,7 @@
   delete root;
 
   root = NULL;
-  ASSERT_TRUE(JSONReader::JsonToValue("0.01", &root, false));
+  ASSERT_TRUE(JSONReader::JsonToValue("0.01", &root, false, false));
   ASSERT_TRUE(root);
   ASSERT_TRUE(root->IsType(Value::TYPE_REAL));
   real_val = 0.0;
@@ -138,7 +138,7 @@
   delete root;
 
   root = NULL;
-  ASSERT_TRUE(JSONReader::JsonToValue("1.00", &root, false));
+  ASSERT_TRUE(JSONReader::JsonToValue("1.00", &root, false, false));
   ASSERT_TRUE(root);
   ASSERT_TRUE(root->IsType(Value::TYPE_REAL));
   real_val = 0.0;
@@ -148,51 +148,51 @@
 
   // Fractional parts must have a digit before and after the decimal point.
   root = NULL;
-  ASSERT_FALSE(JSONReader::JsonToValue("1.", &root, false));
+  ASSERT_FALSE(JSONReader::JsonToValue("1.", &root, false, false));
   ASSERT_FALSE(root);
   root = NULL;
-  ASSERT_FALSE(JSONReader::JsonToValue(".1", &root, false));
+  ASSERT_FALSE(JSONReader::JsonToValue(".1", &root, false, false));
   ASSERT_FALSE(root);
   root = NULL;
-  ASSERT_FALSE(JSONReader::JsonToValue("1.e10", &root, false));
+  ASSERT_FALSE(JSONReader::JsonToValue("1.e10", &root, false, false));
   ASSERT_FALSE(root);
 
   // Exponent must have a digit following the 'e'.
   root = NULL;
-  ASSERT_FALSE(JSONReader::JsonToValue("1e", &root, false));
+  ASSERT_FALSE(JSONReader::JsonToValue("1e", &root, false, false));
   ASSERT_FALSE(root);
   root = NULL;
-  ASSERT_FALSE(JSONReader::JsonToValue("1E", &root, false));
+  ASSERT_FALSE(JSONReader::JsonToValue("1E", &root, false, false));
   ASSERT_FALSE(root);
   root = NULL;
-  ASSERT_FALSE(JSONReader::JsonToValue("1e1.", &root, false));
+  ASSERT_FALSE(JSONReader::JsonToValue("1e1.", &root, false, false));
   ASSERT_FALSE(root);
   root = NULL;
-  ASSERT_FALSE(JSONReader::JsonToValue("1e1.0", &root, false));
+  ASSERT_FALSE(JSONReader::JsonToValue("1e1.0", &root, false, false));
   ASSERT_FALSE(root);
 
   // INF/-INF/NaN are not valid
   root = NULL;
-  ASSERT_FALSE(JSONReader::JsonToValue("1e1000", &root, false));
+  ASSERT_FALSE(JSONReader::JsonToValue("1e1000", &root, false, false));
   ASSERT_FALSE(root);
   root = NULL;
-  ASSERT_FALSE(JSONReader::JsonToValue("-1e1000", &root, false));
+  ASSERT_FALSE(JSONReader::JsonToValue("-1e1000", &root, false, false));
   ASSERT_FALSE(root);
   root = NULL;
-  ASSERT_FALSE(JSONReader::JsonToValue("NaN", &root, false));
+  ASSERT_FALSE(JSONReader::JsonToValue("NaN", &root, false, false));
   ASSERT_FALSE(root);
 
   // Invalid number formats
   root = NULL;
-  ASSERT_FALSE(JSONReader::JsonToValue("4.3.1", &root, false));
+  ASSERT_FALSE(JSONReader::JsonToValue("4.3.1", &root, false, false));
   ASSERT_FALSE(root);
   root = NULL;
-  ASSERT_FALSE(JSONReader::JsonToValue("4e3.1", &root, false));
+  ASSERT_FALSE(JSONReader::JsonToValue("4e3.1", &root, false, false));
   ASSERT_FALSE(root);
 
   // Test string parser
   root = NULL;
-  ASSERT_TRUE(JSONReader::JsonToValue("\"hello world\"", &root, false));
+  ASSERT_TRUE(JSONReader::JsonToValue("\"hello world\"", &root, false, false));
   ASSERT_TRUE(root);
   ASSERT_TRUE(root->IsType(Value::TYPE_STRING));
   std::wstring str_val;
@@ -202,7 +202,7 @@
 
   // Empty string
   root = NULL;
-  ASSERT_TRUE(JSONReader::JsonToValue("\"\"", &root, false));
+  ASSERT_TRUE(JSONReader::JsonToValue("\"\"", &root, false, false));
   ASSERT_TRUE(root);
   ASSERT_TRUE(root->IsType(Value::TYPE_STRING));
   str_val.clear();
@@ -213,7 +213,7 @@
   // Test basic string escapes
   root = NULL;
   ASSERT_TRUE(JSONReader::JsonToValue("\" \\\"\\\\\\/\\b\\f\\n\\r\\t\"", &root,
-                                      false));
+                                      false, false));
   ASSERT_TRUE(root);
   ASSERT_TRUE(root->IsType(Value::TYPE_STRING));
   str_val.clear();
@@ -223,7 +223,8 @@
 
   // Test hex and unicode escapes including the null character.
   root = NULL;
-  ASSERT_TRUE(JSONReader::JsonToValue("\"\\x41\\x00\\u1234\"", &root, false));
+  ASSERT_TRUE(JSONReader::JsonToValue("\"\\x41\\x00\\u1234\"", &root, false,
+                                      false));
   ASSERT_TRUE(root);
   ASSERT_TRUE(root->IsType(Value::TYPE_STRING));
   str_val.clear();
@@ -233,41 +234,48 @@
 
   // Test invalid strings
   root = NULL;
-  ASSERT_FALSE(JSONReader::JsonToValue("\"no closing quote", &root, false));
+  ASSERT_FALSE(JSONReader::JsonToValue("\"no closing quote", &root, false,
+                                       false));
   ASSERT_FALSE(root);
   root = NULL;
   ASSERT_FALSE(JSONReader::JsonToValue("\"\\z invalid escape char\"", &root,
-                                       false));
+                                       false, false));
   ASSERT_FALSE(root);
   root = NULL;
   ASSERT_FALSE(JSONReader::JsonToValue("\"\\xAQ invalid hex code\"", &root,
-                                       false));
+                                       false, false));
   ASSERT_FALSE(root);
   root = NULL;
   ASSERT_FALSE(JSONReader::JsonToValue("not enough hex chars\\x1\"", &root,
-                                       false));
+                                       false, false));
   ASSERT_FALSE(root);
   root = NULL;
   ASSERT_FALSE(JSONReader::JsonToValue("\"not enough escape chars\\u123\"",
-                                       &root, false));
+                                       &root, false, false));
   ASSERT_FALSE(root);
   root = NULL;
   ASSERT_FALSE(JSONReader::JsonToValue("\"extra backslash at end of input\\\"",
-                                       &root, false));
+                                       &root, false, false));
   ASSERT_FALSE(root);
 
   // Basic array
   root = NULL;
-  ASSERT_TRUE(JSONReader::Read("[true, false, null]", &root));
+  ASSERT_TRUE(JSONReader::Read("[true, false, null]", &root, false));
   ASSERT_TRUE(root);
   ASSERT_TRUE(root->IsType(Value::TYPE_LIST));
   ListValue* list = static_cast<ListValue*>(root);
   ASSERT_EQ(3, list->GetSize());
+
+  // Test with trailing comma.  Should be parsed the same as above.
+  Value* root2 = NULL;
+  ASSERT_TRUE(JSONReader::Read("[true, false, null, ]", &root2, true));
+  EXPECT_TRUE(root->Equals(root2));
   delete root;
+  delete root2;
 
   // Empty array
   root = NULL;
-  ASSERT_TRUE(JSONReader::Read("[]", &root));
+  ASSERT_TRUE(JSONReader::Read("[]", &root, false));
   ASSERT_TRUE(root);
   ASSERT_TRUE(root->IsType(Value::TYPE_LIST));
   list = static_cast<ListValue*>(root);
@@ -276,43 +284,81 @@
 
   // Nested arrays
   root = NULL;
-  ASSERT_TRUE(JSONReader::Read("[[true], [], [false, [], [null]], null]", &root));
+  ASSERT_TRUE(JSONReader::Read("[[true], [], [false, [], [null]], null]", &root,
+                               false));
   ASSERT_TRUE(root);
   ASSERT_TRUE(root->IsType(Value::TYPE_LIST));
   list = static_cast<ListValue*>(root);
   ASSERT_EQ(4, list->GetSize());
+
+  // Lots of trailing commas.
+  root2 = NULL;
+  ASSERT_TRUE(JSONReader::Read("[[true], [], [false, [], [null, ]  , ], null,]",
+                               &root2, true));
+  EXPECT_TRUE(root->Equals(root2));
   delete root;
+  delete root2;
 
   // Invalid, missing close brace.
   root = NULL;
-  ASSERT_FALSE(JSONReader::Read("[[true], [], [false, [], [null]], null", &root));
+  ASSERT_FALSE(JSONReader::Read("[[true], [], [false, [], [null]], null", &root,
+                                false));
   ASSERT_FALSE(root);
 
   // Invalid, too many commas
   root = NULL;
-  ASSERT_FALSE(JSONReader::Read("[true,, null]", &root));
+  ASSERT_FALSE(JSONReader::Read("[true,, null]", &root, false));
+  ASSERT_FALSE(root);
+  ASSERT_FALSE(JSONReader::Read("[true,, null]", &root, true));
   ASSERT_FALSE(root);
 
   // Invalid, no commas
   root = NULL;
-  ASSERT_FALSE(JSONReader::Read("[true null]", &root));
+  ASSERT_FALSE(JSONReader::Read("[true null]", &root, false));
   ASSERT_FALSE(root);
 
   // Invalid, trailing comma
   root = NULL;
-  ASSERT_FALSE(JSONReader::Read("[true,]", &root));
+  ASSERT_FALSE(JSONReader::Read("[true,]", &root, false));
   ASSERT_FALSE(root);
 
+  // Valid if we set |allow_trailing_comma| to true.
+  EXPECT_TRUE(JSONReader::Read("[true,]", &root, true));
+  ASSERT_TRUE(root);
+  ASSERT_TRUE(root->IsType(Value::TYPE_LIST));
+  list = static_cast<ListValue*>(root);
+  EXPECT_EQ(1, list->GetSize());
+  Value* tmp_value = NULL;
+  ASSERT_TRUE(list->Get(0, &tmp_value));
+  EXPECT_TRUE(tmp_value->IsType(Value::TYPE_BOOLEAN));
+  bool bool_value = false;
+  ASSERT_TRUE(tmp_value->GetAsBoolean(&bool_value));
+  EXPECT_TRUE(bool_value);
+  delete root;
+
+  // Don't allow empty elements, even if |allow_trailing_comma| is
+  // true.
+  root = NULL;
+  EXPECT_FALSE(JSONReader::Read("[,]", &root, true));
+  EXPECT_FALSE(root);
+  EXPECT_FALSE(JSONReader::Read("[true,,]", &root, true));
+  EXPECT_FALSE(root);
+  EXPECT_FALSE(JSONReader::Read("[,true,]", &root, true));
+  EXPECT_FALSE(root);
+  EXPECT_FALSE(JSONReader::Read("[true,,false]", &root, true));
+  EXPECT_FALSE(root);
+
   // Test objects
   root = NULL;
-  ASSERT_TRUE(JSONReader::Read("{}", &root));
+  ASSERT_TRUE(JSONReader::Read("{}", &root, false));
   ASSERT_TRUE(root);
   ASSERT_TRUE(root->IsType(Value::TYPE_DICTIONARY));
   delete root;
 
   root = NULL;
   ASSERT_TRUE(JSONReader::Read(
-    "{\"number\":9.87654321, \"null\":null , \"\\x53\" : \"str\" }", &root));
+    "{\"number\":9.87654321, \"null\":null , \"\\x53\" : \"str\" }", &root,
+    false));
   ASSERT_TRUE(root);
   ASSERT_TRUE(root->IsType(Value::TYPE_DICTIONARY));
   DictionaryValue* dict_val = static_cast<DictionaryValue*>(root);
@@ -325,12 +371,19 @@
   str_val.clear();
   ASSERT_TRUE(dict_val->GetString(L"S", &str_val));
   ASSERT_EQ(L"str", str_val);
+
+  root2 = NULL;
+  ASSERT_TRUE(JSONReader::Read(
+    "{\"number\":9.87654321, \"null\":null , \"\\x53\" : \"str\", }", &root2,
+    true));
+  EXPECT_TRUE(root->Equals(root2));
   delete root;
+  delete root2;
 
   // Test nesting
   root = NULL;
   ASSERT_TRUE(JSONReader::Read(
-    "{\"inner\":{\"array\":[true]},\"false\":false,\"d\":{}}", &root));
+    "{\"inner\":{\"array\":[true]},\"false\":false,\"d\":{}}", &root, false));
   ASSERT_TRUE(root);
   ASSERT_TRUE(root->IsType(Value::TYPE_DICTIONARY));
   dict_val = static_cast<DictionaryValue*>(root);
@@ -339,43 +392,66 @@
   ListValue* inner_array = NULL;
   ASSERT_TRUE(inner_dict->GetList(L"array", &inner_array));
   ASSERT_EQ(1, inner_array->GetSize());
-  bool bool_value = true;
+  bool_value = true;
   ASSERT_TRUE(dict_val->GetBoolean(L"false", &bool_value));
   ASSERT_FALSE(bool_value);
   inner_dict = NULL;
   ASSERT_TRUE(dict_val->GetDictionary(L"d", &inner_dict));
+
+  root2 = NULL;
+  ASSERT_TRUE(JSONReader::Read(
+    "{\"inner\": {\"array\":[true] , },\"false\":false,\"d\":{},}", &root2,
+    true));
+  EXPECT_TRUE(root->Equals(root2));
   delete root;
+  delete root2;
 
   // Invalid, no closing brace
   root = NULL;
-  ASSERT_FALSE(JSONReader::Read("{\"a\": true", &root));
+  ASSERT_FALSE(JSONReader::Read("{\"a\": true", &root, false));
   ASSERT_FALSE(root);
 
   // Invalid, keys must be quoted
   root = NULL;
-  ASSERT_FALSE(JSONReader::Read("{foo:true}", &root));
+  ASSERT_FALSE(JSONReader::Read("{foo:true}", &root, false));
   ASSERT_FALSE(root);
 
   // Invalid, trailing comma
   root = NULL;
-  ASSERT_FALSE(JSONReader::Read("{\"a\":true,}", &root));
+  ASSERT_FALSE(JSONReader::Read("{\"a\":true,}", &root, false));
   ASSERT_FALSE(root);
 
   // Invalid, too many commas
   root = NULL;
-  ASSERT_FALSE(JSONReader::Read("{\"a\":true,,\"b\":false}", &root));
+  ASSERT_FALSE(JSONReader::Read("{\"a\":true,,\"b\":false}", &root, false));
+  ASSERT_FALSE(root);
+  root = NULL;
+  ASSERT_FALSE(JSONReader::Read("{\"a\":true,,\"b\":false}", &root, true));
   ASSERT_FALSE(root);
 
   // Invalid, no separator
   root = NULL;
-  ASSERT_FALSE(JSONReader::Read("{\"a\" \"b\"}", &root));
+  ASSERT_FALSE(JSONReader::Read("{\"a\" \"b\"}", &root, false));
+  ASSERT_FALSE(root);
+
+  // Invalid, lone comma.
+  root = NULL;
+  ASSERT_FALSE(JSONReader::Read("{,}", &root, false));
+  ASSERT_FALSE(root);
+  ASSERT_FALSE(JSONReader::Read("{,}", &root, true));
+  ASSERT_FALSE(root);
+  ASSERT_FALSE(JSONReader::Read("{\"a\":true,,}", &root, true));
+  ASSERT_FALSE(root);
+  ASSERT_FALSE(JSONReader::Read("{,\"a\":true}", &root, true));
+  ASSERT_FALSE(root);
+  ASSERT_FALSE(JSONReader::Read("{\"a\":true,,\"b\":false}", &root, true));
   ASSERT_FALSE(root);
 
   // Test stack overflow
   root = NULL;
   std::string evil(1000000, '[');
   evil.append(std::string(1000000, ']'));
-  ASSERT_FALSE(JSONReader::Read(evil, &root));
+  ASSERT_FALSE(JSONReader::Read(evil, &root, false));
   ASSERT_FALSE(root);
 
   // A few thousand adjacent lists is fine.
@@ -385,7 +461,7 @@
     not_evil.append("[],");
   }
   not_evil.append("[]]");
-  ASSERT_TRUE(JSONReader::Read(not_evil, &root));
+  ASSERT_TRUE(JSONReader::Read(not_evil, &root, false));
   ASSERT_TRUE(root);
   ASSERT_TRUE(root->IsType(Value::TYPE_LIST));
   list = static_cast<ListValue*>(root);
@@ -395,7 +471,7 @@
   // Test utf8 encoded input
   root = NULL;
   ASSERT_TRUE(JSONReader::JsonToValue("\"\xe7\xbd\x91\xe9\xa1\xb5\"", &root,
-                                      false));
+                                      false, false));
   ASSERT_TRUE(root);
   ASSERT_TRUE(root->IsType(Value::TYPE_STRING));
   str_val.clear();
@@ -405,8 +481,8 @@
 
   // Test invalid root objects.
   root = NULL;
-  ASSERT_FALSE(JSONReader::Read("null", &root));
-  ASSERT_FALSE(JSONReader::Read("true", &root));
-  ASSERT_FALSE(JSONReader::Read("10", &root));
-  ASSERT_FALSE(JSONReader::Read("\"root\"", &root));
+  ASSERT_FALSE(JSONReader::Read("null", &root, false));
+  ASSERT_FALSE(JSONReader::Read("true", &root, false));
+  ASSERT_FALSE(JSONReader::Read("10", &root, false));
+  ASSERT_FALSE(JSONReader::Read("\"root\"", &root, false));
 }