1 // Copyright 2018 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/trace_arguments.h"
6
7 #include <gtest/gtest.h>
8 #include <limits>
9 #include <string>
10
11 #include "base/memory/raw_ptr.h"
12
13 namespace base {
14 namespace trace_event {
15
16 namespace {
17
18 // Simple convertable that holds a string to append to the trace,
19 // and can also write to a boolean flag on destruction.
20 class MyConvertable : public ConvertableToTraceFormat {
21 public:
MyConvertable(const char * text,bool * destroy_flag=nullptr)22 MyConvertable(const char* text, bool* destroy_flag = nullptr)
23 : text_(text), destroy_flag_(destroy_flag) {}
~MyConvertable()24 ~MyConvertable() override {
25 if (destroy_flag_)
26 *destroy_flag_ = true;
27 }
AppendAsTraceFormat(std::string * out) const28 void AppendAsTraceFormat(std::string* out) const override { *out += text_; }
text() const29 const char* text() const { return text_; }
30
31 private:
32 const char* text_;
33 raw_ptr<bool> destroy_flag_;
34 };
35
36 } // namespace
37
TEST(TraceArguments,StringStorageDefaultConstruction)38 TEST(TraceArguments, StringStorageDefaultConstruction) {
39 StringStorage storage;
40 EXPECT_TRUE(storage.empty());
41 EXPECT_FALSE(storage.data());
42 EXPECT_EQ(0U, storage.size());
43 }
44
TEST(TraceArguments,StringStorageConstructionWithSize)45 TEST(TraceArguments, StringStorageConstructionWithSize) {
46 const size_t kSize = 128;
47 StringStorage storage(kSize);
48 EXPECT_FALSE(storage.empty());
49 EXPECT_TRUE(storage.data());
50 EXPECT_EQ(kSize, storage.size());
51 EXPECT_EQ(storage.data(), storage.begin());
52 EXPECT_EQ(storage.data() + kSize, storage.end());
53 }
54
TEST(TraceArguments,StringStorageReset)55 TEST(TraceArguments, StringStorageReset) {
56 StringStorage storage(128);
57 EXPECT_FALSE(storage.empty());
58
59 storage.Reset();
60 EXPECT_TRUE(storage.empty());
61 EXPECT_FALSE(storage.data());
62 EXPECT_EQ(0u, storage.size());
63 }
64
TEST(TraceArguments,StringStorageResetWithSize)65 TEST(TraceArguments, StringStorageResetWithSize) {
66 StringStorage storage;
67 EXPECT_TRUE(storage.empty());
68
69 const size_t kSize = 128;
70 storage.Reset(kSize);
71 EXPECT_FALSE(storage.empty());
72 EXPECT_TRUE(storage.data());
73 EXPECT_EQ(kSize, storage.size());
74 EXPECT_EQ(storage.data(), storage.begin());
75 EXPECT_EQ(storage.data() + kSize, storage.end());
76 }
77
TEST(TraceArguments,StringStorageEstimateTraceMemoryOverhead)78 TEST(TraceArguments, StringStorageEstimateTraceMemoryOverhead) {
79 StringStorage storage;
80 EXPECT_EQ(0u, storage.EstimateTraceMemoryOverhead());
81
82 const size_t kSize = 128;
83 storage.Reset(kSize);
84 EXPECT_EQ(sizeof(size_t) + kSize, storage.EstimateTraceMemoryOverhead());
85 }
86
CheckJSONFor(TraceValue v,char type,const char * expected)87 static void CheckJSONFor(TraceValue v, char type, const char* expected) {
88 std::string out;
89 v.AppendAsJSON(type, &out);
90 EXPECT_STREQ(expected, out.c_str());
91 }
92
CheckStringFor(TraceValue v,char type,const char * expected)93 static void CheckStringFor(TraceValue v, char type, const char* expected) {
94 std::string out;
95 v.AppendAsString(type, &out);
96 EXPECT_STREQ(expected, out.c_str());
97 }
98
TEST(TraceArguments,TraceValueAppend)99 TEST(TraceArguments, TraceValueAppend) {
100 TraceValue v;
101
102 v.Init(-1024);
103 CheckJSONFor(v, TRACE_VALUE_TYPE_INT, "-1024");
104 CheckStringFor(v, TRACE_VALUE_TYPE_INT, "-1024");
105 v.Init(1024ULL);
106 CheckJSONFor(v, TRACE_VALUE_TYPE_UINT, "1024");
107 CheckStringFor(v, TRACE_VALUE_TYPE_UINT, "1024");
108 v.Init(3.1415926535);
109 CheckJSONFor(v, TRACE_VALUE_TYPE_DOUBLE, "3.1415926535");
110 CheckStringFor(v, TRACE_VALUE_TYPE_DOUBLE, "3.1415926535");
111 v.Init(2.0);
112 CheckJSONFor(v, TRACE_VALUE_TYPE_DOUBLE, "2.0");
113 CheckStringFor(v, TRACE_VALUE_TYPE_DOUBLE, "2.0");
114 v.Init(0.5);
115 CheckJSONFor(v, TRACE_VALUE_TYPE_DOUBLE, "0.5");
116 CheckStringFor(v, TRACE_VALUE_TYPE_DOUBLE, "0.5");
117 v.Init(-0.5);
118 CheckJSONFor(v, TRACE_VALUE_TYPE_DOUBLE, "-0.5");
119 CheckStringFor(v, TRACE_VALUE_TYPE_DOUBLE, "-0.5");
120 v.Init(std::numeric_limits<double>::quiet_NaN());
121 CheckJSONFor(v, TRACE_VALUE_TYPE_DOUBLE, "\"NaN\"");
122 CheckStringFor(v, TRACE_VALUE_TYPE_DOUBLE, "NaN");
123 v.Init(std::numeric_limits<double>::quiet_NaN());
124 CheckJSONFor(v, TRACE_VALUE_TYPE_DOUBLE, "\"NaN\"");
125 CheckStringFor(v, TRACE_VALUE_TYPE_DOUBLE, "NaN");
126 v.Init(std::numeric_limits<double>::infinity());
127 CheckJSONFor(v, TRACE_VALUE_TYPE_DOUBLE, "\"Infinity\"");
128 CheckStringFor(v, TRACE_VALUE_TYPE_DOUBLE, "Infinity");
129 v.Init(-std::numeric_limits<double>::infinity());
130 CheckJSONFor(v, TRACE_VALUE_TYPE_DOUBLE, "\"-Infinity\"");
131 CheckStringFor(v, TRACE_VALUE_TYPE_DOUBLE, "-Infinity");
132 v.Init(true);
133 CheckJSONFor(v, TRACE_VALUE_TYPE_BOOL, "true");
134 CheckStringFor(v, TRACE_VALUE_TYPE_BOOL, "true");
135 v.Init(false);
136 CheckJSONFor(v, TRACE_VALUE_TYPE_BOOL, "false");
137 CheckStringFor(v, TRACE_VALUE_TYPE_BOOL, "false");
138 v.Init("Some \"nice\" String");
139 CheckJSONFor(v, TRACE_VALUE_TYPE_STRING, "\"Some \\\"nice\\\" String\"");
140 CheckStringFor(v, TRACE_VALUE_TYPE_STRING, "Some \"nice\" String");
141 CheckJSONFor(v, TRACE_VALUE_TYPE_COPY_STRING, "\"Some \\\"nice\\\" String\"");
142 CheckStringFor(v, TRACE_VALUE_TYPE_COPY_STRING, "Some \"nice\" String");
143
144 int* p = nullptr;
145 v.Init(static_cast<void*>(p));
146 CheckJSONFor(v, TRACE_VALUE_TYPE_POINTER, "\"0x0\"");
147 CheckStringFor(v, TRACE_VALUE_TYPE_POINTER, "0x0");
148
149 const char kText[] = "Hello World";
150 bool destroy_flag = false;
151 TraceArguments args("arg1",
152 std::make_unique<MyConvertable>(kText, &destroy_flag));
153
154 CheckJSONFor(std::move(args.values()[0]), args.types()[0], kText);
155 CheckStringFor(std::move(args.values()[0]), args.types()[0], kText);
156 }
157
TEST(TraceArguments,DefaultConstruction)158 TEST(TraceArguments, DefaultConstruction) {
159 TraceArguments args;
160 EXPECT_EQ(0U, args.size());
161 }
162
TEST(TraceArguments,ConstructorSingleInteger)163 TEST(TraceArguments, ConstructorSingleInteger) {
164 TraceArguments args("foo_int", int(10));
165 EXPECT_EQ(1U, args.size());
166 EXPECT_EQ(TRACE_VALUE_TYPE_INT, args.types()[0]);
167 EXPECT_STREQ("foo_int", args.names()[0]);
168 EXPECT_EQ(10, args.values()[0].as_int);
169 }
170
TEST(TraceArguments,ConstructorSingleFloat)171 TEST(TraceArguments, ConstructorSingleFloat) {
172 TraceArguments args("foo_pi", float(3.1415));
173 double expected = float(3.1415);
174 EXPECT_EQ(1U, args.size());
175 EXPECT_EQ(TRACE_VALUE_TYPE_DOUBLE, args.types()[0]);
176 EXPECT_STREQ("foo_pi", args.names()[0]);
177 EXPECT_EQ(expected, args.values()[0].as_double);
178 }
179
TEST(TraceArguments,ConstructorSingleNoCopyString)180 TEST(TraceArguments, ConstructorSingleNoCopyString) {
181 const char kText[] = "Persistent string";
182 TraceArguments args("foo_cstring", kText);
183 EXPECT_EQ(1U, args.size());
184 EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args.types()[0]);
185 EXPECT_STREQ("foo_cstring", args.names()[0]);
186 EXPECT_EQ(kText, args.values()[0].as_string);
187 }
188
TEST(TraceArguments,ConstructorSingleStdString)189 TEST(TraceArguments, ConstructorSingleStdString) {
190 std::string text = "Non-persistent string";
191 TraceArguments args("foo_stdstring", text);
192 EXPECT_EQ(1U, args.size());
193 EXPECT_EQ(TRACE_VALUE_TYPE_COPY_STRING, args.types()[0]);
194 EXPECT_STREQ("foo_stdstring", args.names()[0]);
195 EXPECT_EQ(text.c_str(), args.values()[0].as_string);
196 }
197
TEST(TraceArguments,ConstructorSingleTraceStringWithCopy)198 TEST(TraceArguments, ConstructorSingleTraceStringWithCopy) {
199 const char kText[] = "Persistent string #2";
200 TraceArguments args("foo_tracestring", TraceStringWithCopy(kText));
201 EXPECT_EQ(1U, args.size());
202 EXPECT_EQ(TRACE_VALUE_TYPE_COPY_STRING, args.types()[0]);
203 EXPECT_STREQ("foo_tracestring", args.names()[0]);
204 EXPECT_EQ(kText, args.values()[0].as_string);
205 }
206
TEST(TraceArguments,ConstructorSinglePointer)207 TEST(TraceArguments, ConstructorSinglePointer) {
208 bool destroy_flag = false;
209 {
210 // Simple class that can set a boolean flag on destruction.
211 class Foo {
212 public:
213 Foo(bool* destroy_flag) : destroy_flag_(destroy_flag) {}
214 ~Foo() {
215 if (destroy_flag_)
216 *destroy_flag_ = true;
217 }
218
219 private:
220 raw_ptr<bool> destroy_flag_;
221 };
222 auto foo = std::make_unique<Foo>(&destroy_flag);
223 EXPECT_FALSE(destroy_flag);
224 // This test also verifies that the object is not destroyed by the
225 // TraceArguments destructor. This should only be possible for
226 // TRACE_VALUE_TYPE_CONVERTABLE instances.
227 {
228 TraceArguments args("foo_pointer", static_cast<void*>(foo.get()));
229 EXPECT_EQ(1U, args.size());
230 EXPECT_EQ(TRACE_VALUE_TYPE_POINTER, args.types()[0]);
231 EXPECT_STREQ("foo_pointer", args.names()[0]);
232 EXPECT_EQ(foo.get(), args.values()[0].as_pointer);
233 EXPECT_FALSE(destroy_flag);
234 } // Calls TraceArguments destructor.
235 EXPECT_FALSE(destroy_flag);
236 } // Calls Foo destructor.
237 EXPECT_TRUE(destroy_flag);
238 }
239
TEST(TraceArguments,ConstructorSingleConvertable)240 TEST(TraceArguments, ConstructorSingleConvertable) {
241 bool destroy_flag = false;
242 const char kText[] = "Text for MyConvertable instance";
243 MyConvertable* ptr = new MyConvertable(kText, &destroy_flag);
244
245 // This test also verifies that the MyConvertable instance is properly
246 // destroyed when the TraceArguments destructor is called.
247 EXPECT_FALSE(destroy_flag);
248 {
249 TraceArguments args("foo_convertable", std::unique_ptr<MyConvertable>(ptr));
250 EXPECT_EQ(1U, args.size());
251 EXPECT_EQ(TRACE_VALUE_TYPE_CONVERTABLE, args.types()[0]);
252 EXPECT_STREQ("foo_convertable", args.names()[0]);
253 EXPECT_EQ(ptr, args.values()[0].as_convertable);
254 EXPECT_FALSE(destroy_flag);
255 } // Calls TraceArguments destructor.
256 EXPECT_TRUE(destroy_flag);
257 }
258
TEST(TraceArguments,ConstructorWithTwoArguments)259 TEST(TraceArguments, ConstructorWithTwoArguments) {
260 const char kText1[] = "First argument";
261 const char kText2[] = "Second argument";
262 bool destroy_flag = false;
263
264 {
265 MyConvertable* ptr = new MyConvertable(kText2, &destroy_flag);
266 TraceArguments args1("foo_arg1_cstring", kText1, "foo_arg2_convertable",
267 std::unique_ptr<MyConvertable>(ptr));
268 EXPECT_EQ(2U, args1.size());
269 EXPECT_STREQ("foo_arg1_cstring", args1.names()[0]);
270 EXPECT_STREQ("foo_arg2_convertable", args1.names()[1]);
271 EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args1.types()[0]);
272 EXPECT_EQ(TRACE_VALUE_TYPE_CONVERTABLE, args1.types()[1]);
273 EXPECT_EQ(kText1, args1.values()[0].as_string);
274 EXPECT_EQ(ptr, args1.values()[1].as_convertable);
275 EXPECT_FALSE(destroy_flag);
276 } // calls |args1| destructor. Should delete |ptr|.
277 EXPECT_TRUE(destroy_flag);
278 }
279
TEST(TraceArguments,ConstructorLegacyNoConvertables)280 TEST(TraceArguments, ConstructorLegacyNoConvertables) {
281 const char* const kNames[3] = {"legacy_arg1", "legacy_arg2", "legacy_arg3"};
282 const unsigned char kTypes[3] = {
283 TRACE_VALUE_TYPE_INT,
284 TRACE_VALUE_TYPE_STRING,
285 TRACE_VALUE_TYPE_POINTER,
286 };
287 static const char kText[] = "Some text";
288 const unsigned long long kValues[3] = {
289 1000042ULL,
290 reinterpret_cast<unsigned long long>(kText),
291 reinterpret_cast<unsigned long long>(kText + 2),
292 };
293 TraceArguments args(3, kNames, kTypes, kValues);
294 // Check that only the first kMaxSize arguments are taken!
295 EXPECT_EQ(2U, args.size());
296 EXPECT_STREQ(kNames[0], args.names()[0]);
297 EXPECT_STREQ(kNames[1], args.names()[1]);
298 EXPECT_EQ(TRACE_VALUE_TYPE_INT, args.types()[0]);
299 EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args.types()[1]);
300 EXPECT_EQ(kValues[0], args.values()[0].as_uint);
301 EXPECT_EQ(kText, args.values()[1].as_string);
302 }
303
TEST(TraceArguments,ConstructorLegacyWithConvertables)304 TEST(TraceArguments, ConstructorLegacyWithConvertables) {
305 const char* const kNames[3] = {"legacy_arg1", "legacy_arg2", "legacy_arg3"};
306 const unsigned char kTypes[3] = {
307 TRACE_VALUE_TYPE_CONVERTABLE,
308 TRACE_VALUE_TYPE_CONVERTABLE,
309 TRACE_VALUE_TYPE_CONVERTABLE,
310 };
311 std::unique_ptr<MyConvertable> convertables[3] = {
312 std::make_unique<MyConvertable>("First one"),
313 std::make_unique<MyConvertable>("Second one"),
314 std::make_unique<MyConvertable>("Third one"),
315 };
316 TraceArguments args(3, kNames, kTypes, nullptr, convertables);
317 // Check that only the first kMaxSize arguments are taken!
318 EXPECT_EQ(2U, args.size());
319 EXPECT_STREQ(kNames[0], args.names()[0]);
320 EXPECT_STREQ(kNames[1], args.names()[1]);
321 EXPECT_EQ(TRACE_VALUE_TYPE_CONVERTABLE, args.types()[0]);
322 EXPECT_EQ(TRACE_VALUE_TYPE_CONVERTABLE, args.types()[1]);
323 // Check that only the first two items were moved to |args|.
324 EXPECT_FALSE(convertables[0].get());
325 EXPECT_FALSE(convertables[1].get());
326 EXPECT_TRUE(convertables[2].get());
327 }
328
TEST(TraceArguments,MoveConstruction)329 TEST(TraceArguments, MoveConstruction) {
330 const char kText1[] = "First argument";
331 const char kText2[] = "Second argument";
332 bool destroy_flag = false;
333
334 {
335 MyConvertable* ptr = new MyConvertable(kText2, &destroy_flag);
336 TraceArguments args1("foo_arg1_cstring", kText1, "foo_arg2_convertable",
337 std::unique_ptr<MyConvertable>(ptr));
338 EXPECT_EQ(2U, args1.size());
339 EXPECT_STREQ("foo_arg1_cstring", args1.names()[0]);
340 EXPECT_STREQ("foo_arg2_convertable", args1.names()[1]);
341 EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args1.types()[0]);
342 EXPECT_EQ(TRACE_VALUE_TYPE_CONVERTABLE, args1.types()[1]);
343 EXPECT_EQ(kText1, args1.values()[0].as_string);
344 EXPECT_EQ(ptr, args1.values()[1].as_convertable);
345
346 {
347 TraceArguments args2(std::move(args1));
348 EXPECT_FALSE(destroy_flag);
349
350 // |args1| is now empty.
351 EXPECT_EQ(0U, args1.size());
352
353 // Check that everything was transferred to |args2|.
354 EXPECT_EQ(2U, args2.size());
355 EXPECT_STREQ("foo_arg1_cstring", args2.names()[0]);
356 EXPECT_STREQ("foo_arg2_convertable", args2.names()[1]);
357 EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args2.types()[0]);
358 EXPECT_EQ(TRACE_VALUE_TYPE_CONVERTABLE, args2.types()[1]);
359 EXPECT_EQ(kText1, args2.values()[0].as_string);
360 EXPECT_EQ(ptr, args2.values()[1].as_convertable);
361 } // Calls |args2| destructor. Should delete |ptr|.
362 EXPECT_TRUE(destroy_flag);
363 destroy_flag = false;
364 } // Calls |args1| destructor. Should not delete |ptr|.
365 EXPECT_FALSE(destroy_flag);
366 }
367
TEST(TraceArguments,MoveAssignment)368 TEST(TraceArguments, MoveAssignment) {
369 const char kText1[] = "First argument";
370 const char kText2[] = "Second argument";
371 bool destroy_flag = false;
372
373 {
374 MyConvertable* ptr = new MyConvertable(kText2, &destroy_flag);
375 TraceArguments args1("foo_arg1_cstring", kText1, "foo_arg2_convertable",
376 std::unique_ptr<MyConvertable>(ptr));
377 EXPECT_EQ(2U, args1.size());
378 EXPECT_STREQ("foo_arg1_cstring", args1.names()[0]);
379 EXPECT_STREQ("foo_arg2_convertable", args1.names()[1]);
380 EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args1.types()[0]);
381 EXPECT_EQ(TRACE_VALUE_TYPE_CONVERTABLE, args1.types()[1]);
382 EXPECT_EQ(kText1, args1.values()[0].as_string);
383 EXPECT_EQ(ptr, args1.values()[1].as_convertable);
384
385 {
386 TraceArguments args2;
387
388 args2 = std::move(args1);
389 EXPECT_FALSE(destroy_flag);
390
391 // |args1| is now empty.
392 EXPECT_EQ(0U, args1.size());
393
394 // Check that everything was transferred to |args2|.
395 EXPECT_EQ(2U, args2.size());
396 EXPECT_STREQ("foo_arg1_cstring", args2.names()[0]);
397 EXPECT_STREQ("foo_arg2_convertable", args2.names()[1]);
398 EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args2.types()[0]);
399 EXPECT_EQ(TRACE_VALUE_TYPE_CONVERTABLE, args2.types()[1]);
400 EXPECT_EQ(kText1, args2.values()[0].as_string);
401 EXPECT_EQ(ptr, args2.values()[1].as_convertable);
402 } // Calls |args2| destructor. Should delete |ptr|.
403 EXPECT_TRUE(destroy_flag);
404 destroy_flag = false;
405 } // Calls |args1| destructor. Should not delete |ptr|.
406 EXPECT_FALSE(destroy_flag);
407 }
408
TEST(TraceArguments,Reset)409 TEST(TraceArguments, Reset) {
410 bool destroy_flag = false;
411 {
412 TraceArguments args(
413 "foo_arg1", "Hello", "foo_arg2",
414 std::make_unique<MyConvertable>("World", &destroy_flag));
415
416 EXPECT_EQ(2U, args.size());
417 EXPECT_FALSE(destroy_flag);
418 args.Reset();
419 EXPECT_EQ(0U, args.size());
420 EXPECT_TRUE(destroy_flag);
421 destroy_flag = false;
422 } // Calls |args| destructor. Should not delete twice.
423 EXPECT_FALSE(destroy_flag);
424 }
425
TEST(TraceArguments,CopyStringsTo_NoStrings)426 TEST(TraceArguments, CopyStringsTo_NoStrings) {
427 StringStorage storage;
428
429 TraceArguments args("arg1", 10, "arg2", 42);
430 args.CopyStringsTo(&storage, false, nullptr, nullptr);
431 EXPECT_TRUE(storage.empty());
432 EXPECT_EQ(0U, storage.size());
433 }
434
TEST(TraceArguments,CopyStringsTo_OnlyArgs)435 TEST(TraceArguments, CopyStringsTo_OnlyArgs) {
436 StringStorage storage;
437
438 TraceArguments args("arg1", TraceStringWithCopy("Hello"), "arg2",
439 TraceStringWithCopy("World"));
440
441 const char kExtra1[] = "extra1";
442 const char kExtra2[] = "extra2";
443 const char* extra1 = kExtra1;
444 const char* extra2 = kExtra2;
445
446 // Types should be copyable strings.
447 EXPECT_EQ(TRACE_VALUE_TYPE_COPY_STRING, args.types()[0]);
448 EXPECT_EQ(TRACE_VALUE_TYPE_COPY_STRING, args.types()[1]);
449
450 args.CopyStringsTo(&storage, false, &extra1, &extra2);
451
452 // Storage should be allocated.
453 EXPECT_TRUE(storage.data());
454 EXPECT_NE(0U, storage.size());
455
456 // Types should not be changed.
457 EXPECT_EQ(TRACE_VALUE_TYPE_COPY_STRING, args.types()[0]);
458 EXPECT_EQ(TRACE_VALUE_TYPE_COPY_STRING, args.types()[1]);
459
460 // names should not be copied.
461 EXPECT_FALSE(storage.Contains(args.names()[0]));
462 EXPECT_FALSE(storage.Contains(args.names()[1]));
463 EXPECT_STREQ("arg1", args.names()[0]);
464 EXPECT_STREQ("arg2", args.names()[1]);
465
466 // strings should be copied.
467 EXPECT_TRUE(storage.Contains(args.values()[0].as_string));
468 EXPECT_TRUE(storage.Contains(args.values()[1].as_string));
469 EXPECT_STREQ("Hello", args.values()[0].as_string);
470 EXPECT_STREQ("World", args.values()[1].as_string);
471
472 // |extra1| and |extra2| should not be copied.
473 EXPECT_EQ(kExtra1, extra1);
474 EXPECT_EQ(kExtra2, extra2);
475 }
476
TEST(TraceArguments,CopyStringsTo_Everything)477 TEST(TraceArguments, CopyStringsTo_Everything) {
478 StringStorage storage;
479
480 TraceArguments args("arg1", "Hello", "arg2", "World");
481 const char kExtra1[] = "extra1";
482 const char kExtra2[] = "extra2";
483 const char* extra1 = kExtra1;
484 const char* extra2 = kExtra2;
485
486 // Types should be normal strings.
487 EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args.types()[0]);
488 EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args.types()[1]);
489
490 args.CopyStringsTo(&storage, true, &extra1, &extra2);
491
492 // Storage should be allocated.
493 EXPECT_TRUE(storage.data());
494 EXPECT_NE(0U, storage.size());
495
496 // Types should be changed to copyable strings.
497 EXPECT_EQ(TRACE_VALUE_TYPE_COPY_STRING, args.types()[0]);
498 EXPECT_EQ(TRACE_VALUE_TYPE_COPY_STRING, args.types()[1]);
499
500 // names should be copied.
501 EXPECT_TRUE(storage.Contains(args.names()[0]));
502 EXPECT_TRUE(storage.Contains(args.names()[1]));
503 EXPECT_STREQ("arg1", args.names()[0]);
504 EXPECT_STREQ("arg2", args.names()[1]);
505
506 // strings should be copied.
507 EXPECT_TRUE(storage.Contains(args.values()[0].as_string));
508 EXPECT_TRUE(storage.Contains(args.values()[1].as_string));
509 EXPECT_STREQ("Hello", args.values()[0].as_string);
510 EXPECT_STREQ("World", args.values()[1].as_string);
511
512 // |extra1| and |extra2| should be copied.
513 EXPECT_NE(kExtra1, extra1);
514 EXPECT_NE(kExtra2, extra2);
515 EXPECT_TRUE(storage.Contains(extra1));
516 EXPECT_TRUE(storage.Contains(extra2));
517 EXPECT_STREQ(kExtra1, extra1);
518 EXPECT_STREQ(kExtra2, extra2);
519 }
520
521 } // namespace trace_event
522 } // namespace base
523