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