• 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 <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