Allow trace event to work with temporary name strings.

This is needed where the name or arg_names may not be available as compile time constants.


BUG=None
TEST=base_unittests --gtest_filter=TraceEvent*

Review URL: http://codereview.chromium.org/7354025

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@93375 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/base/debug/trace_event_unittest.cc b/base/debug/trace_event_unittest.cc
index b48260ce..6b8f5f9 100644
--- a/base/debug/trace_event_unittest.cc
+++ b/base/debug/trace_event_unittest.cc
@@ -28,6 +28,8 @@
 
 class TraceEventTestFixture : public testing::Test {
  public:
+  // This fixture does not use SetUp() because the fixture must be manually set
+  // up multiple times when testing AtExit. Use ManualTestSetUp for this.
   void ManualTestSetUp();
   void OnTraceDataCollected(
       scoped_refptr<TraceLog::RefCountedString> json_events_str);
@@ -559,5 +561,76 @@
   }
 }
 
+TEST_F(TraceEventTestFixture, NormallyNoDeepCopy) {
+  // Test that the TRACE_EVENT macros do not deep-copy their string. If they
+  // do so it may indicate a performance regression, but more-over it would
+  // make the DEEP_COPY overloads redundant.
+  ManualTestSetUp();
+
+  std::string name_string("event name");
+
+  TraceLog::GetInstance()->SetEnabled(true);
+  TRACE_EVENT_INSTANT0("category", name_string.c_str());
+
+  // Modify the string in place (a wholesale reassignment may leave the old
+  // string intact on the heap).
+  name_string[0] = '@';
+
+  TraceLog::GetInstance()->SetEnabled(false);
+
+  EXPECT_FALSE(FindTraceEntry(trace_parsed_, "event name"));
+  EXPECT_TRUE(FindTraceEntry(trace_parsed_, name_string.c_str()));
+}
+
+TEST_F(TraceEventTestFixture, DeepCopy) {
+  ManualTestSetUp();
+
+  static const char kOriginalName1[] = "name1";
+  static const char kOriginalName2[] = "name2";
+  static const char kOriginalName3[] = "name3";
+  std::string name1(kOriginalName1);
+  std::string name2(kOriginalName2);
+  std::string name3(kOriginalName3);
+  std::string arg1("arg1");
+  std::string arg2("arg2");
+  std::string val1("val1");
+  std::string val2("val2");
+
+  TraceLog::GetInstance()->SetEnabled(true);
+  TRACE_EVENT_COPY_INSTANT0("category", name1.c_str());
+  TRACE_EVENT_COPY_BEGIN1("category", name2.c_str(),
+                          arg1.c_str(), 5);
+  TRACE_EVENT_COPY_END2("category", name3.c_str(),
+                        arg1.c_str(), val1.c_str(),
+                        arg2.c_str(), val2.c_str());
+
+  // As per NormallyNoDeepCopy, modify the strings in place.
+  name1[0] = name2[0] = name3[0] = arg1[0] = arg2[0] = val1[0] = val2[0] = '@';
+
+  TraceLog::GetInstance()->SetEnabled(false);
+
+  EXPECT_FALSE(FindTraceEntry(trace_parsed_, name1.c_str()));
+  EXPECT_FALSE(FindTraceEntry(trace_parsed_, name2.c_str()));
+  EXPECT_FALSE(FindTraceEntry(trace_parsed_, name3.c_str()));
+
+  DictionaryValue* entry1 = FindTraceEntry(trace_parsed_, kOriginalName1);
+  DictionaryValue* entry2 = FindTraceEntry(trace_parsed_, kOriginalName2);
+  DictionaryValue* entry3 = FindTraceEntry(trace_parsed_, kOriginalName3);
+  ASSERT_TRUE(entry1);
+  ASSERT_TRUE(entry2);
+  ASSERT_TRUE(entry3);
+
+  int i;
+  EXPECT_FALSE(entry2->GetInteger("args.@rg1", &i));
+  EXPECT_TRUE(entry2->GetInteger("args.arg1", &i));
+  EXPECT_EQ(5, i);
+
+  std::string s;
+  EXPECT_TRUE(entry3->GetString("args.arg1", &s));
+  EXPECT_EQ("val1", s);
+  EXPECT_TRUE(entry3->GetString("args.arg2", &s));
+  EXPECT_EQ("val2", s);
+}
+
 }  // namespace debug
 }  // namespace base