json_writer_unittest.cc 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  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. #include "base/json/json_writer.h"
  5. #include "base/json/json_reader.h"
  6. #include "base/containers/span.h"
  7. #include "base/memory/ptr_util.h"
  8. #include "base/strings/stringprintf.h"
  9. #include "base/values.h"
  10. #include "build/build_config.h"
  11. #include "testing/gtest/include/gtest/gtest.h"
  12. namespace base {
  13. TEST(JSONWriterTest, BasicTypes) {
  14. std::string output_js;
  15. // Test null.
  16. EXPECT_TRUE(JSONWriter::Write(Value(), &output_js));
  17. EXPECT_EQ("null", output_js);
  18. // Test empty dict.
  19. EXPECT_TRUE(JSONWriter::Write(Value(Value::Type::DICTIONARY), &output_js));
  20. EXPECT_EQ("{}", output_js);
  21. // Test empty list.
  22. EXPECT_TRUE(JSONWriter::Write(Value(Value::Type::LIST), &output_js));
  23. EXPECT_EQ("[]", output_js);
  24. // Test integer values.
  25. EXPECT_TRUE(JSONWriter::Write(Value(42), &output_js));
  26. EXPECT_EQ("42", output_js);
  27. // Test boolean values.
  28. EXPECT_TRUE(JSONWriter::Write(Value(true), &output_js));
  29. EXPECT_EQ("true", output_js);
  30. // Test Real values should always have a decimal or an 'e'.
  31. EXPECT_TRUE(JSONWriter::Write(Value(1.0), &output_js));
  32. EXPECT_EQ("1.0", output_js);
  33. // Test Real values in the range (-1, 1) must have leading zeros
  34. EXPECT_TRUE(JSONWriter::Write(Value(0.2), &output_js));
  35. EXPECT_EQ("0.2", output_js);
  36. // Test Real values in the range (-1, 1) must have leading zeros
  37. EXPECT_TRUE(JSONWriter::Write(Value(-0.8), &output_js));
  38. EXPECT_EQ("-0.8", output_js);
  39. // Test String values.
  40. EXPECT_TRUE(JSONWriter::Write(Value("foo"), &output_js));
  41. EXPECT_EQ("\"foo\"", output_js);
  42. }
  43. TEST(JSONWriterTest, NestedTypes) {
  44. std::string output_js;
  45. // Writer unittests like empty list/dict nesting,
  46. // list list nesting, etc.
  47. Value::Dict root_dict;
  48. Value::List list;
  49. Value::Dict inner_dict;
  50. inner_dict.Set("inner int", 10);
  51. list.Append(std::move(inner_dict));
  52. Value::Dict empty_dict;
  53. list.Append(std::move(empty_dict));
  54. list.Append(Value::List());
  55. list.Append(true);
  56. root_dict.Set("list", Value(std::move(list)));
  57. // The pretty-printer uses a different newline style on Windows than on
  58. // other platforms.
  59. #if BUILDFLAG(IS_WIN)
  60. #define JSON_NEWLINE "\r\n"
  61. #else
  62. #define JSON_NEWLINE "\n"
  63. #endif
  64. // Test the pretty-printer.
  65. EXPECT_TRUE(JSONWriter::Write(root_dict, &output_js));
  66. EXPECT_EQ("{\"list\":[{\"inner int\":10},{},[],true]}", output_js);
  67. EXPECT_TRUE(JSONWriter::WriteWithOptions(
  68. root_dict, JSONWriter::OPTIONS_PRETTY_PRINT, &output_js));
  69. EXPECT_EQ("{" JSON_NEWLINE " \"list\": [ {" JSON_NEWLINE
  70. " \"inner int\": 10" JSON_NEWLINE " }, {" JSON_NEWLINE
  71. " }, [ ], true ]" JSON_NEWLINE "}" JSON_NEWLINE,
  72. output_js);
  73. #undef JSON_NEWLINE
  74. }
  75. TEST(JSONWriterTest, KeysWithPeriods) {
  76. std::string output_js;
  77. Value::Dict period_dict;
  78. period_dict.Set("a.b", 3);
  79. period_dict.Set("c", 2);
  80. Value::Dict period_dict2;
  81. period_dict2.Set("g.h.i.j", 1);
  82. period_dict.Set("d.e.f", std::move(period_dict2));
  83. EXPECT_TRUE(JSONWriter::Write(period_dict, &output_js));
  84. EXPECT_EQ("{\"a.b\":3,\"c\":2,\"d.e.f\":{\"g.h.i.j\":1}}", output_js);
  85. Value::Dict period_dict3;
  86. period_dict3.SetByDottedPath("a.b", 2);
  87. period_dict3.Set("a.b", 1);
  88. EXPECT_TRUE(JSONWriter::Write(period_dict3, &output_js));
  89. EXPECT_EQ("{\"a\":{\"b\":2},\"a.b\":1}", output_js);
  90. }
  91. TEST(JSONWriterTest, BinaryValues) {
  92. std::string output_js;
  93. // Binary values should return errors unless suppressed via the
  94. // OPTIONS_OMIT_BINARY_VALUES flag.
  95. const auto kBufferSpan =
  96. base::make_span(reinterpret_cast<const uint8_t*>("asdf"), 4);
  97. Value root(kBufferSpan);
  98. EXPECT_FALSE(JSONWriter::Write(root, &output_js));
  99. EXPECT_TRUE(JSONWriter::WriteWithOptions(
  100. root, JSONWriter::OPTIONS_OMIT_BINARY_VALUES, &output_js));
  101. EXPECT_TRUE(output_js.empty());
  102. Value::List binary_list;
  103. binary_list.Append(Value(kBufferSpan));
  104. binary_list.Append(5);
  105. binary_list.Append(Value(kBufferSpan));
  106. binary_list.Append(2);
  107. binary_list.Append(Value(kBufferSpan));
  108. EXPECT_FALSE(JSONWriter::Write(binary_list, &output_js));
  109. EXPECT_TRUE(JSONWriter::WriteWithOptions(
  110. binary_list, JSONWriter::OPTIONS_OMIT_BINARY_VALUES, &output_js));
  111. EXPECT_EQ("[5,2]", output_js);
  112. Value::Dict binary_dict;
  113. binary_dict.Set("a", Value(kBufferSpan));
  114. binary_dict.Set("b", 5);
  115. binary_dict.Set("c", Value(kBufferSpan));
  116. binary_dict.Set("d", 2);
  117. binary_dict.Set("e", Value(kBufferSpan));
  118. EXPECT_FALSE(JSONWriter::Write(binary_dict, &output_js));
  119. EXPECT_TRUE(JSONWriter::WriteWithOptions(
  120. binary_dict, JSONWriter::OPTIONS_OMIT_BINARY_VALUES, &output_js));
  121. EXPECT_EQ("{\"b\":5,\"d\":2}", output_js);
  122. }
  123. TEST(JSONWriterTest, DoublesAsInts) {
  124. std::string output_js;
  125. // Test allowing a double with no fractional part to be written as an integer.
  126. Value double_value(1e10);
  127. EXPECT_TRUE(JSONWriter::WriteWithOptions(
  128. double_value, JSONWriter::OPTIONS_OMIT_DOUBLE_TYPE_PRESERVATION,
  129. &output_js));
  130. EXPECT_EQ("10000000000", output_js);
  131. }
  132. TEST(JSONWriterTest, StackOverflow) {
  133. std::string output_js;
  134. Value::List deep_list;
  135. const size_t max_depth = 100000;
  136. for (size_t i = 0; i < max_depth; ++i) {
  137. Value::List new_top_list;
  138. new_top_list.Append(std::move(deep_list));
  139. deep_list = std::move(new_top_list);
  140. }
  141. Value deep_list_value(std::move(deep_list));
  142. EXPECT_FALSE(JSONWriter::Write(deep_list_value, &output_js));
  143. EXPECT_FALSE(JSONWriter::WriteWithOptions(
  144. deep_list_value, JSONWriter::OPTIONS_PRETTY_PRINT, &output_js));
  145. // We cannot just let deep_list tear down since it
  146. // would cause a stack overflow. Therefore, we tear
  147. // down the deep list manually.
  148. deep_list = std::move(deep_list_value.GetList());
  149. while (!deep_list.empty()) {
  150. DCHECK_EQ(deep_list.size(), 1u);
  151. Value::List inner_list = std::move(deep_list[0].GetList());
  152. deep_list = std::move(inner_list);
  153. }
  154. }
  155. TEST(JSONWriterTest, TestMaxDepthWithValidNodes) {
  156. // Create JSON to the max depth - 1. Nodes at that depth are still valid
  157. // for writing which matches the JSONParser logic.
  158. std::string nested_json;
  159. for (int i = 0; i < 199; ++i) {
  160. std::string node = "[";
  161. for (int j = 0; j < 5; j++) {
  162. node.append(StringPrintf("%d,", j));
  163. }
  164. nested_json.insert(0, node);
  165. nested_json.append("]");
  166. }
  167. // Ensure we can read and write the JSON
  168. auto json_val = JSONReader::ReadAndReturnValueWithError(
  169. nested_json, JSON_ALLOW_TRAILING_COMMAS);
  170. EXPECT_TRUE(json_val.has_value());
  171. const Value& value = *json_val;
  172. std::string serialized;
  173. EXPECT_TRUE(JSONWriter::Write(value, &serialized));
  174. }
  175. } // namespace base