traced_value_unittest.cc 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. // Copyright (c) 2014 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/trace_event/traced_value.h"
  5. #include <cmath>
  6. #include <cstddef>
  7. #include <utility>
  8. #include "base/strings/string_util.h"
  9. #include "base/values.h"
  10. #include "testing/gtest/include/gtest/gtest.h"
  11. namespace base {
  12. namespace trace_event {
  13. TEST(TraceEventArgumentTest, InitializerListCreatedContainers) {
  14. std::string json;
  15. TracedValue::Build(
  16. {
  17. {"empty_array", TracedValue::Array({})},
  18. {"empty_dictionary", TracedValue::Dictionary({})},
  19. {"nested_array", TracedValue::Array({
  20. TracedValue::Array({}),
  21. TracedValue::Dictionary({}),
  22. true,
  23. })},
  24. {"nested_dictionary", TracedValue::Dictionary({
  25. {"d", TracedValue::Dictionary({})},
  26. {"a", TracedValue::Array({})},
  27. {"b", true},
  28. })},
  29. })
  30. ->AppendAsTraceFormat(&json);
  31. EXPECT_EQ(
  32. "{\"empty_array\":[],\"empty_dictionary\":{},"
  33. "\"nested_array\":[[],{},true],"
  34. "\"nested_dictionary\":{\"d\":{},\"a\":[],\"b\":true}}",
  35. json);
  36. }
  37. TEST(TraceEventArgumentTest, InitializerListCreatedFlatDictionary) {
  38. std::string json;
  39. TracedValue::Build({{"bool_var", true},
  40. {"double_var", 3.14},
  41. {"int_var", 2020},
  42. {"literal_var", "literal"}})
  43. ->AppendAsTraceFormat(&json);
  44. EXPECT_EQ(
  45. "{\"bool_var\":true,\"double_var\":3.14,\"int_var\":2020,\""
  46. "literal_var\":\"literal\"}",
  47. json);
  48. }
  49. TEST(TraceEventArgumentTest, ArrayAndDictionaryScope) {
  50. std::unique_ptr<TracedValue> value(new TracedValue());
  51. {
  52. auto dictionary = value->BeginDictionaryScoped("dictionary_name");
  53. value->SetInteger("my_int", 1);
  54. }
  55. {
  56. auto array = value->BeginArrayScoped("array_name");
  57. value->AppendInteger(2);
  58. }
  59. {
  60. auto surround_dictionary =
  61. value->BeginDictionaryScoped("outside_dictionary");
  62. value->SetBoolean("my_bool", true);
  63. {
  64. auto inside_array = value->BeginArrayScoped("inside_array");
  65. value->AppendBoolean(false);
  66. }
  67. {
  68. auto inside_array = value->BeginDictionaryScoped("inside_dictionary");
  69. value->SetBoolean("inner_bool", false);
  70. }
  71. }
  72. {
  73. auto surround_array = value->BeginArrayScoped("outside_array");
  74. value->AppendBoolean(false);
  75. {
  76. auto inside_dictionary = value->AppendDictionaryScoped();
  77. value->SetBoolean("my_bool", true);
  78. }
  79. {
  80. auto inside_array = value->AppendArrayScoped();
  81. value->AppendBoolean(false);
  82. }
  83. }
  84. {
  85. auto dictionary = value->BeginDictionaryScopedWithCopiedName(
  86. std::string("wonderful_") + std::string("world"));
  87. }
  88. {
  89. auto array = value->BeginArrayScopedWithCopiedName(
  90. std::string("wonderful_") + std::string("array"));
  91. }
  92. std::string json;
  93. value->AppendAsTraceFormat(&json);
  94. EXPECT_EQ(
  95. "{"
  96. "\"dictionary_name\":{\"my_int\":1},"
  97. "\"array_name\":[2],"
  98. "\"outside_dictionary\":{\"my_bool\":true,\"inside_array\":[false],"
  99. "\"inside_dictionary\":{\"inner_bool\":false}},"
  100. "\"outside_array\":[false,{\"my_bool\":true},[false]],"
  101. "\"wonderful_world\":{},"
  102. "\"wonderful_array\":[]"
  103. "}",
  104. json);
  105. }
  106. std::string SayHello() {
  107. // Create a string by concatenating two strings, so that there is no literal
  108. // corresponding to the result.
  109. return std::string("hello ") + std::string("world");
  110. }
  111. TEST(TraceEventArgumentTest, StringAndPointerConstructors) {
  112. std::string json;
  113. const char* const_char_ptr_var = "const char* value";
  114. TracedValue::Build(
  115. {
  116. {"literal_var", "literal"},
  117. {"std_string_var", std::string("std::string value")},
  118. {"string_from_function", SayHello()},
  119. {"string_from_lambda", []() { return std::string("hello"); }()},
  120. {"base_string_piece_var",
  121. base::StringPiece("base::StringPiece value")},
  122. {"const_char_ptr_var", const_char_ptr_var},
  123. {"void_nullptr", static_cast<void*>(nullptr)},
  124. {"int_nullptr", static_cast<int*>(nullptr)},
  125. {"void_1234ptr", reinterpret_cast<void*>(0x1234)},
  126. })
  127. ->AppendAsTraceFormat(&json);
  128. EXPECT_EQ(
  129. "{\"literal_var\":\"literal\","
  130. "\"std_string_var\":\"std::string value\","
  131. "\"string_from_function\":\"hello world\","
  132. "\"string_from_lambda\":\"hello\","
  133. "\"base_string_piece_var\":\"base::StringPiece value\","
  134. "\"const_char_ptr_var\":\"const char* value\","
  135. "\"void_nullptr\":\"0x0\","
  136. "\"int_nullptr\":\"0x0\","
  137. "\"void_1234ptr\":\"0x1234\"}",
  138. json);
  139. }
  140. TEST(TraceEventArgumentTest, FlatDictionary) {
  141. std::unique_ptr<TracedValue> value(new TracedValue());
  142. value->SetBoolean("bool", true);
  143. value->SetDouble("double", 0.0);
  144. value->SetInteger("int", 2014);
  145. value->SetString("string", "string");
  146. value->SetPointer("ptr", reinterpret_cast<void*>(0x1234));
  147. std::string json = "PREFIX";
  148. value->AppendAsTraceFormat(&json);
  149. EXPECT_EQ(
  150. "PREFIX{\"bool\":true,\"double\":0.0,\"int\":2014,\"string\":\"string\","
  151. "\"ptr\":\"0x1234\"}",
  152. json);
  153. }
  154. TEST(TraceEventArgumentTest, NoDotPathExpansion) {
  155. std::unique_ptr<TracedValue> value(new TracedValue());
  156. value->SetBoolean("bo.ol", true);
  157. value->SetDouble("doub.le", 0.0);
  158. value->SetInteger("in.t", 2014);
  159. value->SetString("str.ing", "str.ing");
  160. std::string json;
  161. value->AppendAsTraceFormat(&json);
  162. EXPECT_EQ(
  163. "{\"bo.ol\":true,\"doub.le\":0.0,\"in.t\":2014,\"str.ing\":\"str.ing\"}",
  164. json);
  165. }
  166. TEST(TraceEventArgumentTest, Hierarchy) {
  167. std::unique_ptr<TracedValue> value(new TracedValue());
  168. value->BeginArray("a1");
  169. value->AppendInteger(1);
  170. value->AppendBoolean(true);
  171. value->BeginDictionary();
  172. value->SetInteger("i2", 3);
  173. value->EndDictionary();
  174. value->EndArray();
  175. value->SetBoolean("b0", true);
  176. value->SetDouble("d0", 0.0);
  177. value->BeginDictionary("dict1");
  178. value->BeginDictionary("dict2");
  179. value->SetBoolean("b2", false);
  180. value->EndDictionary();
  181. value->SetInteger("i1", 2014);
  182. value->SetString("s1", "foo");
  183. value->EndDictionary();
  184. value->SetInteger("i0", 2014);
  185. value->SetString("s0", "foo");
  186. std::string json;
  187. value->AppendAsTraceFormat(&json);
  188. EXPECT_EQ(
  189. "{\"a1\":[1,true,{\"i2\":3}],\"b0\":true,\"d0\":0.0,\"dict1\":{\"dict2\":"
  190. "{\"b2\":false},\"i1\":2014,\"s1\":\"foo\"},\"i0\":2014,\"s0\":"
  191. "\"foo\"}",
  192. json);
  193. }
  194. TEST(TraceEventArgumentTest, LongStrings) {
  195. std::string kLongString = "supercalifragilisticexpialidocious";
  196. std::string kLongString2 = "0123456789012345678901234567890123456789";
  197. char kLongString3[4096];
  198. for (size_t i = 0; i < sizeof(kLongString3); ++i)
  199. kLongString3[i] = 'a' + (i % 25);
  200. kLongString3[sizeof(kLongString3) - 1] = '\0';
  201. std::unique_ptr<TracedValue> value(new TracedValue());
  202. value->SetString("a", "short");
  203. value->SetString("b", kLongString);
  204. value->BeginArray("c");
  205. value->AppendString(kLongString2);
  206. value->AppendString("");
  207. value->BeginDictionary();
  208. value->SetString("a", kLongString3);
  209. value->EndDictionary();
  210. value->EndArray();
  211. std::string json;
  212. value->AppendAsTraceFormat(&json);
  213. EXPECT_EQ("{\"a\":\"short\",\"b\":\"" + kLongString + "\",\"c\":[\"" +
  214. kLongString2 + "\",\"\",{\"a\":\"" + kLongString3 + "\"}]}",
  215. json);
  216. }
  217. TEST(TraceEventArgumentTest, PassTracedValue) {
  218. auto dict_value = std::make_unique<TracedValue>();
  219. dict_value->SetInteger("a", 1);
  220. auto nested_dict_value = std::make_unique<TracedValue>();
  221. nested_dict_value->SetInteger("b", 2);
  222. nested_dict_value->BeginArray("c");
  223. nested_dict_value->AppendString("foo");
  224. nested_dict_value->EndArray();
  225. dict_value->SetValue("e", nested_dict_value.get());
  226. // Check the merged result.
  227. std::string json;
  228. dict_value->AppendAsTraceFormat(&json);
  229. EXPECT_EQ("{\"a\":1,\"e\":{\"b\":2,\"c\":[\"foo\"]}}", json);
  230. // Check that the passed nestd dict was left unouthced.
  231. json = "";
  232. nested_dict_value->AppendAsTraceFormat(&json);
  233. EXPECT_EQ("{\"b\":2,\"c\":[\"foo\"]}", json);
  234. // And that it is still usable.
  235. nested_dict_value->SetInteger("f", 3);
  236. nested_dict_value->BeginDictionary("g");
  237. nested_dict_value->EndDictionary();
  238. json = "";
  239. nested_dict_value->AppendAsTraceFormat(&json);
  240. EXPECT_EQ("{\"b\":2,\"c\":[\"foo\"],\"f\":3,\"g\":{}}", json);
  241. }
  242. TEST(TraceEventArgumentTest, NanAndInfinityJSON) {
  243. TracedValueJSON value;
  244. value.SetDouble("nan", std::nan(""));
  245. value.SetDouble("infinity", INFINITY);
  246. value.SetDouble("negInfinity", -INFINITY);
  247. std::string json;
  248. value.AppendAsTraceFormat(&json);
  249. EXPECT_EQ(
  250. "{\"nan\":\"NaN\",\"infinity\":\"Infinity\","
  251. "\"negInfinity\":\"-Infinity\"}",
  252. json);
  253. std::string formatted_json = value.ToFormattedJSON();
  254. // Remove CR and LF to make the result platform-independent.
  255. ReplaceChars(formatted_json, "\n\r", "", &formatted_json);
  256. EXPECT_EQ(
  257. "{"
  258. " \"infinity\": \"Infinity\","
  259. " \"nan\": \"NaN\","
  260. " \"negInfinity\": \"-Infinity\""
  261. "}",
  262. formatted_json);
  263. }
  264. } // namespace trace_event
  265. } // namespace base