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; 31 SimpleMessage() : foo(0), baz(false), bstruct(false), simple_enum(FOO) {} 32 33 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 44 static bool HasFieldPresent(const base::Value* value, bool* result) { 45 *result = value != nullptr; 46 return true; 47 } 48 49 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 60 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 84 NestedMessage() : foo(0) {} 85 86 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 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 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 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 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 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 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