xref: /aosp_15_r20/external/cronet/base/trace_event/trace_arguments_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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