• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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;
SimpleMessagebase::__anon4d4e50ad0111::SimpleMessage32   SimpleMessage() : foo(0), baz(false), bstruct(false), simple_enum(FOO) {}
33 
ParseSimpleEnumbase::__anon4d4e50ad0111::SimpleMessage34   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 
HasFieldPresentbase::__anon4d4e50ad0111::SimpleMessage45   static bool HasFieldPresent(const base::Value* value, bool* result) {
46     *result = value != NULL;
47     return true;
48   }
49 
GetValueStringbase::__anon4d4e50ad0111::SimpleMessage50   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 
RegisterJSONConverterbase::__anon4d4e50ad0111::SimpleMessage61   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 
NestedMessagebase::__anon4d4e50ad0111::NestedMessage85   NestedMessage() : foo(0) {}
86 
RegisterJSONConverterbase::__anon4d4e50ad0111::NestedMessage87   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 
TEST(JSONValueConverterTest,ParseSimpleMessage)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 
TEST(JSONValueConverterTest,ParseNestedMessage)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 
TEST(JSONValueConverterTest,ParseFailures)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 
TEST(JSONValueConverterTest,ParseWithMissingFields)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 
TEST(JSONValueConverterTest,EnumParserFails)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 
TEST(JSONValueConverterTest,RepeatedValueErrorInTheMiddle)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