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