Home | History | Annotate | Download | only in json
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/json/json_value_converter.h"
      6 
      7 #include <string>
      8 #include <vector>
      9 
     10 #include "base/json/json_reader.h"
     11 #include "base/memory/scoped_ptr.h"
     12 #include "base/memory/scoped_vector.h"
     13 #include "base/strings/string_piece.h"
     14 #include "base/values.h"
     15 #include "testing/gtest/include/gtest/gtest.h"
     16 
     17 namespace base {
     18 namespace {
     19 
     20 // Very simple messages.
     21 struct SimpleMessage {
     22   enum SimpleEnum {
     23     FOO, BAR,
     24   };
     25   int foo;
     26   std::string bar;
     27   bool baz;
     28   bool bstruct;
     29   SimpleEnum simple_enum;
     30   ScopedVector<int> ints;
     31   ScopedVector<std::string> string_values;
     32   SimpleMessage() : foo(0), baz(false), bstruct(false), simple_enum(FOO) {}
     33 
     34   static bool ParseSimpleEnum(const StringPiece& value, SimpleEnum* field) {
     35     if (value == "foo") {
     36       *field = FOO;
     37       return true;
     38     } else if (value == "bar") {
     39       *field = BAR;
     40       return true;
     41     }
     42     return false;
     43   }
     44 
     45   static bool HasFieldPresent(const base::Value* value, bool* result) {
     46     *result = value != NULL;
     47     return true;
     48   }
     49 
     50   static bool GetValueString(const base::Value* value, std::string* result) {
     51     const base::DictionaryValue* dict = NULL;
     52     if (!value->GetAsDictionary(&dict))
     53       return false;
     54 
     55     if (!dict->GetString("val", result))
     56       return false;
     57 
     58     return true;
     59   }
     60 
     61   static void RegisterJSONConverter(
     62       base::JSONValueConverter<SimpleMessage>* converter) {
     63     converter->RegisterIntField("foo", &SimpleMessage::foo);
     64     converter->RegisterStringField("bar", &SimpleMessage::bar);
     65     converter->RegisterBoolField("baz", &SimpleMessage::baz);
     66     converter->RegisterCustomField<SimpleEnum>(
     67         "simple_enum", &SimpleMessage::simple_enum, &ParseSimpleEnum);
     68     converter->RegisterRepeatedInt("ints", &SimpleMessage::ints);
     69     converter->RegisterCustomValueField<bool>("bstruct",
     70                                               &SimpleMessage::bstruct,
     71                                               &HasFieldPresent);
     72     converter->RegisterRepeatedCustomValue<std::string>(
     73         "string_values",
     74         &SimpleMessage::string_values,
     75         &GetValueString);
     76   }
     77 };
     78 
     79 // For nested messages.
     80 struct NestedMessage {
     81   double foo;
     82   SimpleMessage child;
     83   ScopedVector<SimpleMessage> children;
     84 
     85   NestedMessage() : foo(0) {}
     86 
     87   static void RegisterJSONConverter(
     88       base::JSONValueConverter<NestedMessage>* converter) {
     89     converter->RegisterDoubleField("foo", &NestedMessage::foo);
     90     converter->RegisterNestedField("child", &NestedMessage::child);
     91     converter->RegisterRepeatedMessage("children", &NestedMessage::children);
     92   }
     93 };
     94 
     95 }  // namespace
     96 
     97 TEST(JSONValueConverterTest, ParseSimpleMessage) {
     98   const char normal_data[] =
     99       "{\n"
    100       "  \"foo\": 1,\n"
    101       "  \"bar\": \"bar\",\n"
    102       "  \"baz\": true,\n"
    103       "  \"bstruct\": {},\n"
    104       "  \"string_values\": [{\"val\": \"value_1\"}, {\"val\": \"value_2\"}],"
    105       "  \"simple_enum\": \"foo\","
    106       "  \"ints\": [1, 2]"
    107       "}\n";
    108 
    109   scoped_ptr<Value> value = base::JSONReader::Read(normal_data);
    110   SimpleMessage message;
    111   base::JSONValueConverter<SimpleMessage> converter;
    112   EXPECT_TRUE(converter.Convert(*value.get(), &message));
    113 
    114   EXPECT_EQ(1, message.foo);
    115   EXPECT_EQ("bar", message.bar);
    116   EXPECT_TRUE(message.baz);
    117   EXPECT_EQ(SimpleMessage::FOO, message.simple_enum);
    118   EXPECT_EQ(2, static_cast<int>(message.ints.size()));
    119   ASSERT_EQ(2U, message.string_values.size());
    120   EXPECT_EQ("value_1", *message.string_values[0]);
    121   EXPECT_EQ("value_2", *message.string_values[1]);
    122   EXPECT_EQ(1, *(message.ints[0]));
    123   EXPECT_EQ(2, *(message.ints[1]));
    124 }
    125 
    126 TEST(JSONValueConverterTest, ParseNestedMessage) {
    127   const char normal_data[] =
    128       "{\n"
    129       "  \"foo\": 1.0,\n"
    130       "  \"child\": {\n"
    131       "    \"foo\": 1,\n"
    132       "    \"bar\": \"bar\",\n"
    133       "    \"bstruct\": {},\n"
    134       "    \"string_values\": [{\"val\": \"value_1\"}, {\"val\": \"value_2\"}],"
    135       "    \"baz\": true\n"
    136       "  },\n"
    137       "  \"children\": [{\n"
    138       "    \"foo\": 2,\n"
    139       "    \"bar\": \"foobar\",\n"
    140       "    \"bstruct\": \"\",\n"
    141       "    \"string_values\": [{\"val\": \"value_1\"}],"
    142       "    \"baz\": true\n"
    143       "  },\n"
    144       "  {\n"
    145       "    \"foo\": 3,\n"
    146       "    \"bar\": \"barbaz\",\n"
    147       "    \"baz\": false\n"
    148       "  }]\n"
    149       "}\n";
    150 
    151   scoped_ptr<Value> value = base::JSONReader::Read(normal_data);
    152   NestedMessage message;
    153   base::JSONValueConverter<NestedMessage> converter;
    154   EXPECT_TRUE(converter.Convert(*value.get(), &message));
    155 
    156   EXPECT_EQ(1.0, message.foo);
    157   EXPECT_EQ(1, message.child.foo);
    158   EXPECT_EQ("bar", message.child.bar);
    159   EXPECT_TRUE(message.child.baz);
    160   EXPECT_TRUE(message.child.bstruct);
    161   ASSERT_EQ(2U, message.child.string_values.size());
    162   EXPECT_EQ("value_1", *message.child.string_values[0]);
    163   EXPECT_EQ("value_2", *message.child.string_values[1]);
    164 
    165   EXPECT_EQ(2, static_cast<int>(message.children.size()));
    166   const SimpleMessage* first_child = message.children[0];
    167   ASSERT_TRUE(first_child);
    168   EXPECT_EQ(2, first_child->foo);
    169   EXPECT_EQ("foobar", first_child->bar);
    170   EXPECT_TRUE(first_child->baz);
    171   EXPECT_TRUE(first_child->bstruct);
    172   ASSERT_EQ(1U, first_child->string_values.size());
    173   EXPECT_EQ("value_1", *first_child->string_values[0]);
    174 
    175   const SimpleMessage* second_child = message.children[1];
    176   ASSERT_TRUE(second_child);
    177   EXPECT_EQ(3, second_child->foo);
    178   EXPECT_EQ("barbaz", second_child->bar);
    179   EXPECT_FALSE(second_child->baz);
    180   EXPECT_FALSE(second_child->bstruct);
    181   EXPECT_EQ(0U, second_child->string_values.size());
    182 }
    183 
    184 TEST(JSONValueConverterTest, ParseFailures) {
    185   const char normal_data[] =
    186       "{\n"
    187       "  \"foo\": 1,\n"
    188       "  \"bar\": 2,\n" // "bar" is an integer here.
    189       "  \"baz\": true,\n"
    190       "  \"ints\": [1, 2]"
    191       "}\n";
    192 
    193   scoped_ptr<Value> value = base::JSONReader::Read(normal_data);
    194   SimpleMessage message;
    195   base::JSONValueConverter<SimpleMessage> converter;
    196   EXPECT_FALSE(converter.Convert(*value.get(), &message));
    197   // Do not check the values below.  |message| may be modified during
    198   // Convert() even it fails.
    199 }
    200 
    201 TEST(JSONValueConverterTest, ParseWithMissingFields) {
    202   const char normal_data[] =
    203       "{\n"
    204       "  \"foo\": 1,\n"
    205       "  \"baz\": true,\n"
    206       "  \"ints\": [1, 2]"
    207       "}\n";
    208 
    209   scoped_ptr<Value> value = base::JSONReader::Read(normal_data);
    210   SimpleMessage message;
    211   base::JSONValueConverter<SimpleMessage> converter;
    212   // Convert() still succeeds even if the input doesn't have "bar" field.
    213   EXPECT_TRUE(converter.Convert(*value.get(), &message));
    214 
    215   EXPECT_EQ(1, message.foo);
    216   EXPECT_TRUE(message.baz);
    217   EXPECT_EQ(2, static_cast<int>(message.ints.size()));
    218   EXPECT_EQ(1, *(message.ints[0]));
    219   EXPECT_EQ(2, *(message.ints[1]));
    220 }
    221 
    222 TEST(JSONValueConverterTest, EnumParserFails) {
    223   const char normal_data[] =
    224       "{\n"
    225       "  \"foo\": 1,\n"
    226       "  \"bar\": \"bar\",\n"
    227       "  \"baz\": true,\n"
    228       "  \"simple_enum\": \"baz\","
    229       "  \"ints\": [1, 2]"
    230       "}\n";
    231 
    232   scoped_ptr<Value> value = base::JSONReader::Read(normal_data);
    233   SimpleMessage message;
    234   base::JSONValueConverter<SimpleMessage> converter;
    235   EXPECT_FALSE(converter.Convert(*value.get(), &message));
    236   // No check the values as mentioned above.
    237 }
    238 
    239 TEST(JSONValueConverterTest, RepeatedValueErrorInTheMiddle) {
    240   const char normal_data[] =
    241       "{\n"
    242       "  \"foo\": 1,\n"
    243       "  \"bar\": \"bar\",\n"
    244       "  \"baz\": true,\n"
    245       "  \"simple_enum\": \"baz\","
    246       "  \"ints\": [1, false]"
    247       "}\n";
    248 
    249   scoped_ptr<Value> value = base::JSONReader::Read(normal_data);
    250   SimpleMessage message;
    251   base::JSONValueConverter<SimpleMessage> converter;
    252   EXPECT_FALSE(converter.Convert(*value.get(), &message));
    253   // No check the values as mentioned above.
    254 }
    255 
    256 }  // namespace base
    257