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