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::__anonc7c6db940111::SimpleMessage32 SimpleMessage() : foo(0), baz(false), bstruct(false), simple_enum(FOO) {}
33
ParseSimpleEnumbase::__anonc7c6db940111::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::__anonc7c6db940111::SimpleMessage45 static bool HasFieldPresent(const base::Value* value, bool* result) {
46 *result = value != NULL;
47 return true;
48 }
49
GetValueStringbase::__anonc7c6db940111::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::__anonc7c6db940111::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::__anonc7c6db940111::NestedMessage85 NestedMessage() : foo(0) {}
86
RegisterJSONConverterbase::__anonc7c6db940111::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