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