xref: /aosp_15_r20/external/cronet/base/json/json_value_converter_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2012 The Chromium Authors
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 <optional>
9 #include <string>
10 #include <string_view>
11 #include <vector>
12 
13 #include "base/json/json_reader.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,
24     BAR,
25   };
26   int foo;
27   std::string bar;
28   bool baz;
29   bool bstruct;
30   SimpleEnum simple_enum;
31   std::vector<std::unique_ptr<int>> ints;
32   std::vector<std::unique_ptr<std::string>> string_values;
SimpleMessagebase::__anonec408df40111::SimpleMessage33   SimpleMessage() : foo(0), baz(false), bstruct(false), simple_enum(FOO) {}
34 
ParseSimpleEnumbase::__anonec408df40111::SimpleMessage35   static bool ParseSimpleEnum(std::string_view value, SimpleEnum* field) {
36     if (value == "foo") {
37       *field = FOO;
38       return true;
39     }
40     if (value == "bar") {
41       *field = BAR;
42       return true;
43     }
44     return false;
45   }
46 
HasFieldPresentbase::__anonec408df40111::SimpleMessage47   static bool HasFieldPresent(const base::Value* value, bool* result) {
48     *result = value != nullptr;
49     return true;
50   }
51 
GetValueStringbase::__anonec408df40111::SimpleMessage52   static bool GetValueString(const base::Value* value, std::string* result) {
53     const Value::Dict* dict = value->GetIfDict();
54     if (!dict)
55       return false;
56     const std::string* str = dict->FindString("val");
57     if (!str)
58       return false;
59     if (result)
60       *result = *str;
61     return true;
62   }
63 
RegisterJSONConverterbase::__anonec408df40111::SimpleMessage64   static void RegisterJSONConverter(
65       base::JSONValueConverter<SimpleMessage>* converter) {
66     converter->RegisterIntField("foo", &SimpleMessage::foo);
67     converter->RegisterStringField("bar", &SimpleMessage::bar);
68     converter->RegisterBoolField("baz", &SimpleMessage::baz);
69     converter->RegisterCustomField<SimpleEnum>(
70         "simple_enum", &SimpleMessage::simple_enum, &ParseSimpleEnum);
71     converter->RegisterRepeatedInt("ints", &SimpleMessage::ints);
72     converter->RegisterCustomValueField<bool>(
73         "bstruct", &SimpleMessage::bstruct, &HasFieldPresent);
74     converter->RegisterRepeatedCustomValue<std::string>(
75         "string_values", &SimpleMessage::string_values, &GetValueString);
76   }
77 };
78 
79 // For nested messages.
80 struct NestedMessage {
81   double foo;
82   SimpleMessage child;
83   std::vector<std::unique_ptr<SimpleMessage>> children;
84 
NestedMessagebase::__anonec408df40111::NestedMessage85   NestedMessage() : foo(0) {}
86 
RegisterJSONConverterbase::__anonec408df40111::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   std::optional<Value> value = base::JSONReader::Read(normal_data);
110   ASSERT_TRUE(value);
111   SimpleMessage message;
112   base::JSONValueConverter<SimpleMessage> converter;
113   EXPECT_TRUE(converter.Convert(*value, &message));
114 
115   EXPECT_EQ(1, message.foo);
116   EXPECT_EQ("bar", message.bar);
117   EXPECT_TRUE(message.baz);
118   EXPECT_EQ(SimpleMessage::FOO, message.simple_enum);
119   EXPECT_EQ(2, static_cast<int>(message.ints.size()));
120   ASSERT_EQ(2U, message.string_values.size());
121   EXPECT_EQ("value_1", *message.string_values[0]);
122   EXPECT_EQ("value_2", *message.string_values[1]);
123   EXPECT_EQ(1, *(message.ints[0]));
124   EXPECT_EQ(2, *(message.ints[1]));
125 }
126 
TEST(JSONValueConverterTest,ParseNestedMessage)127 TEST(JSONValueConverterTest, ParseNestedMessage) {
128   const char normal_data[] =
129       "{\n"
130       "  \"foo\": 1.0,\n"
131       "  \"child\": {\n"
132       "    \"foo\": 1,\n"
133       "    \"bar\": \"bar\",\n"
134       "    \"bstruct\": {},\n"
135       "    \"string_values\": [{\"val\": \"value_1\"}, {\"val\": \"value_2\"}],"
136       "    \"baz\": true\n"
137       "  },\n"
138       "  \"children\": [{\n"
139       "    \"foo\": 2,\n"
140       "    \"bar\": \"foobar\",\n"
141       "    \"bstruct\": \"\",\n"
142       "    \"string_values\": [{\"val\": \"value_1\"}],"
143       "    \"baz\": true\n"
144       "  },\n"
145       "  {\n"
146       "    \"foo\": 3,\n"
147       "    \"bar\": \"barbaz\",\n"
148       "    \"baz\": false\n"
149       "  }]\n"
150       "}\n";
151 
152   std::optional<Value> value = base::JSONReader::Read(normal_data);
153   ASSERT_TRUE(value);
154   NestedMessage message;
155   base::JSONValueConverter<NestedMessage> converter;
156   EXPECT_TRUE(converter.Convert(*value, &message));
157 
158   EXPECT_EQ(1.0, message.foo);
159   EXPECT_EQ(1, message.child.foo);
160   EXPECT_EQ("bar", message.child.bar);
161   EXPECT_TRUE(message.child.baz);
162   EXPECT_TRUE(message.child.bstruct);
163   ASSERT_EQ(2U, message.child.string_values.size());
164   EXPECT_EQ("value_1", *message.child.string_values[0]);
165   EXPECT_EQ("value_2", *message.child.string_values[1]);
166 
167   EXPECT_EQ(2, static_cast<int>(message.children.size()));
168   const SimpleMessage* first_child = message.children[0].get();
169   ASSERT_TRUE(first_child);
170   EXPECT_EQ(2, first_child->foo);
171   EXPECT_EQ("foobar", first_child->bar);
172   EXPECT_TRUE(first_child->baz);
173   EXPECT_TRUE(first_child->bstruct);
174   ASSERT_EQ(1U, first_child->string_values.size());
175   EXPECT_EQ("value_1", *first_child->string_values[0]);
176 
177   const SimpleMessage* second_child = message.children[1].get();
178   ASSERT_TRUE(second_child);
179   EXPECT_EQ(3, second_child->foo);
180   EXPECT_EQ("barbaz", second_child->bar);
181   EXPECT_FALSE(second_child->baz);
182   EXPECT_FALSE(second_child->bstruct);
183   EXPECT_EQ(0U, second_child->string_values.size());
184 }
185 
TEST(JSONValueConverterTest,ParseFailures)186 TEST(JSONValueConverterTest, ParseFailures) {
187   const char normal_data[] =
188       "{\n"
189       "  \"foo\": 1,\n"
190       "  \"bar\": 2,\n"  // "bar" is an integer here.
191       "  \"baz\": true,\n"
192       "  \"ints\": [1, 2]"
193       "}\n";
194 
195   std::optional<Value> value = base::JSONReader::Read(normal_data);
196   ASSERT_TRUE(value);
197   SimpleMessage message;
198   base::JSONValueConverter<SimpleMessage> converter;
199   EXPECT_FALSE(converter.Convert(*value, &message));
200   // Do not check the values below.  |message| may be modified during
201   // Convert() even it fails.
202 }
203 
TEST(JSONValueConverterTest,ParseWithMissingFields)204 TEST(JSONValueConverterTest, ParseWithMissingFields) {
205   const char normal_data[] =
206       "{\n"
207       "  \"foo\": 1,\n"
208       "  \"baz\": true,\n"
209       "  \"ints\": [1, 2]"
210       "}\n";
211 
212   std::optional<Value> value = base::JSONReader::Read(normal_data);
213   ASSERT_TRUE(value);
214   SimpleMessage message;
215   base::JSONValueConverter<SimpleMessage> converter;
216   // Convert() still succeeds even if the input doesn't have "bar" field.
217   EXPECT_TRUE(converter.Convert(*value, &message));
218 
219   EXPECT_EQ(1, message.foo);
220   EXPECT_TRUE(message.baz);
221   EXPECT_EQ(2, static_cast<int>(message.ints.size()));
222   EXPECT_EQ(1, *(message.ints[0]));
223   EXPECT_EQ(2, *(message.ints[1]));
224 }
225 
TEST(JSONValueConverterTest,EnumParserFails)226 TEST(JSONValueConverterTest, EnumParserFails) {
227   const char normal_data[] =
228       "{\n"
229       "  \"foo\": 1,\n"
230       "  \"bar\": \"bar\",\n"
231       "  \"baz\": true,\n"
232       "  \"simple_enum\": \"baz\","
233       "  \"ints\": [1, 2]"
234       "}\n";
235 
236   std::optional<Value> value = base::JSONReader::Read(normal_data);
237   ASSERT_TRUE(value);
238   SimpleMessage message;
239   base::JSONValueConverter<SimpleMessage> converter;
240   EXPECT_FALSE(converter.Convert(*value, &message));
241   // No check the values as mentioned above.
242 }
243 
TEST(JSONValueConverterTest,RepeatedValueErrorInTheMiddle)244 TEST(JSONValueConverterTest, RepeatedValueErrorInTheMiddle) {
245   const char normal_data[] =
246       "{\n"
247       "  \"foo\": 1,\n"
248       "  \"bar\": \"bar\",\n"
249       "  \"baz\": true,\n"
250       "  \"simple_enum\": \"baz\","
251       "  \"ints\": [1, false]"
252       "}\n";
253 
254   std::optional<Value> value = base::JSONReader::Read(normal_data);
255   ASSERT_TRUE(value);
256   SimpleMessage message;
257   base::JSONValueConverter<SimpleMessage> converter;
258   EXPECT_FALSE(converter.Convert(*value, &message));
259   // No check the values as mentioned above.
260 }
261 
262 }  // namespace base
263