Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/debug/trace_event.h" | 5 #include "base/debug/trace_event.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
| 9 #include "base/json/json_reader.h" | 9 #include "base/json/json_reader.h" |
| 10 #include "base/json/json_writer.h" | 10 #include "base/json/json_writer.h" |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 33 const char* value; | 33 const char* value; |
| 34 CompareOp op; | 34 CompareOp op; |
| 35 }; | 35 }; |
| 36 | 36 |
| 37 class TraceEventTestFixture : public testing::Test { | 37 class TraceEventTestFixture : public testing::Test { |
| 38 public: | 38 public: |
| 39 // This fixture does not use SetUp() because the fixture must be manually set | 39 // This fixture does not use SetUp() because the fixture must be manually set |
| 40 // up multiple times when testing AtExit. Use ManualTestSetUp for this. | 40 // up multiple times when testing AtExit. Use ManualTestSetUp for this. |
| 41 void ManualTestSetUp(); | 41 void ManualTestSetUp(); |
| 42 void OnTraceDataCollected( | 42 void OnTraceDataCollected( |
| 43 scoped_refptr<TraceLog::RefCountedString> json_events_str); | 43 scoped_refptr<TraceLog::RefCountedString> events_str); |
| 44 bool FindMatchingTraceEntry(const JsonKeyValue* key_values); | 44 bool FindMatchingTraceEntry(const JsonKeyValue* key_values); |
| 45 bool FindNamePhase(const char* name, const char* phase); | 45 bool FindNamePhase(const char* name, const char* phase); |
| 46 bool FindMatchingValue(const char* key, | 46 bool FindMatchingValue(const char* key, |
| 47 const char* value); | 47 const char* value); |
| 48 bool FindNonMatchingValue(const char* key, | 48 bool FindNonMatchingValue(const char* key, |
| 49 const char* value); | 49 const char* value); |
| 50 void Clear() { | 50 void Clear() { |
| 51 trace_string_.clear(); | |
| 52 trace_parsed_.Clear(); | 51 trace_parsed_.Clear(); |
| 52 json_output_.json_output.clear(); | |
| 53 } | 53 } |
| 54 | 54 |
| 55 std::string trace_string_; | |
| 56 ListValue trace_parsed_; | 55 ListValue trace_parsed_; |
| 56 base::debug::TraceResultBuffer trace_buffer_; | |
| 57 base::debug::TraceResultBuffer::SimpleOutput json_output_; | |
| 57 | 58 |
| 58 private: | 59 private: |
| 59 // We want our singleton torn down after each test. | 60 // We want our singleton torn down after each test. |
| 60 ShadowingAtExitManager at_exit_manager_; | 61 ShadowingAtExitManager at_exit_manager_; |
| 61 Lock lock_; | 62 Lock lock_; |
| 62 }; | 63 }; |
| 63 | 64 |
| 64 void TraceEventTestFixture::ManualTestSetUp() { | 65 void TraceEventTestFixture::ManualTestSetUp() { |
| 65 TraceLog::DeleteForTesting(); | 66 TraceLog::DeleteForTesting(); |
| 66 TraceLog::Resurrect(); | 67 TraceLog::Resurrect(); |
| 67 TraceLog* tracelog = TraceLog::GetInstance(); | 68 TraceLog* tracelog = TraceLog::GetInstance(); |
| 68 ASSERT_TRUE(tracelog); | 69 ASSERT_TRUE(tracelog); |
| 69 ASSERT_FALSE(tracelog->IsEnabled()); | 70 ASSERT_FALSE(tracelog->IsEnabled()); |
| 70 tracelog->SetOutputCallback( | 71 tracelog->SetOutputCallback( |
| 71 base::Bind(&TraceEventTestFixture::OnTraceDataCollected, | 72 base::Bind(&TraceEventTestFixture::OnTraceDataCollected, |
| 72 base::Unretained(this))); | 73 base::Unretained(this))); |
| 74 trace_buffer_.SetOutputCallback(json_output_.GetCallback()); | |
| 73 } | 75 } |
| 74 | 76 |
| 75 void TraceEventTestFixture::OnTraceDataCollected( | 77 void TraceEventTestFixture::OnTraceDataCollected( |
| 76 scoped_refptr<TraceLog::RefCountedString> json_events_str) { | 78 scoped_refptr<TraceLog::RefCountedString> events_str) { |
| 77 AutoLock lock(lock_); | 79 AutoLock lock(lock_); |
| 78 trace_string_ += json_events_str->data; | 80 json_output_.json_output.clear(); |
| 81 trace_buffer_.Start(); | |
| 82 trace_buffer_.AddFragment(events_str->data); | |
| 83 trace_buffer_.Finish(); | |
| 79 | 84 |
| 80 scoped_ptr<Value> root; | 85 scoped_ptr<Value> root; |
| 81 root.reset(base::JSONReader::Read(json_events_str->data, false)); | 86 root.reset(base::JSONReader::Read(json_output_.json_output, false)); |
| 82 | 87 |
| 83 ListValue* root_list = NULL; | 88 ListValue* root_list = NULL; |
| 84 ASSERT_TRUE(root.get()); | 89 ASSERT_TRUE(root.get()); |
| 85 ASSERT_TRUE(root->GetAsList(&root_list)); | 90 ASSERT_TRUE(root->GetAsList(&root_list)); |
| 86 | 91 |
| 87 // Move items into our aggregate collection | 92 // Move items into our aggregate collection |
| 88 while (root_list->GetSize()) { | 93 while (root_list->GetSize()) { |
| 89 Value* item = NULL; | 94 Value* item = NULL; |
| 90 root_list->Remove(0, &item); | 95 root_list->Remove(0, &item); |
| 91 trace_parsed_.Append(item); | 96 trace_parsed_.Append(item); |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 274 TRACE_EVENT_END1("all", "TRACE_EVENT_END1 call", "name1", "value1"); | 279 TRACE_EVENT_END1("all", "TRACE_EVENT_END1 call", "name1", "value1"); |
| 275 TRACE_EVENT_END2("all", "TRACE_EVENT_END2 call", | 280 TRACE_EVENT_END2("all", "TRACE_EVENT_END2 call", |
| 276 "name1", "value1", | 281 "name1", "value1", |
| 277 "name2", "value2"); | 282 "name2", "value2"); |
| 278 } // Scope close causes TRACE_EVENT0 etc to send their END events. | 283 } // Scope close causes TRACE_EVENT0 etc to send their END events. |
| 279 | 284 |
| 280 if (task_complete_event) | 285 if (task_complete_event) |
| 281 task_complete_event->Signal(); | 286 task_complete_event->Signal(); |
| 282 } | 287 } |
| 283 | 288 |
| 284 void ValidateAllTraceMacrosCreatedData(const ListValue& trace_parsed, | 289 void ValidateAllTraceMacrosCreatedData(const ListValue& trace_parsed) { |
| 285 const std::string& trace_string) { | |
| 286 DictionaryValue* item = NULL; | 290 DictionaryValue* item = NULL; |
| 287 | 291 |
| 288 #define EXPECT_FIND_(string) \ | 292 #define EXPECT_FIND_(string) \ |
| 289 EXPECT_TRUE((item = FindTraceEntry(trace_parsed, string))); | 293 EXPECT_TRUE((item = FindTraceEntry(trace_parsed, string))); |
| 290 #define EXPECT_NOT_FIND_(string) \ | 294 #define EXPECT_NOT_FIND_(string) \ |
| 291 EXPECT_FALSE((item = FindTraceEntry(trace_parsed, string))); | 295 EXPECT_FALSE((item = FindTraceEntry(trace_parsed, string))); |
| 292 #define EXPECT_SUB_FIND_(string) \ | 296 #define EXPECT_SUB_FIND_(string) \ |
| 293 if (item) EXPECT_TRUE((IsStringInDict(string, item))); | 297 if (item) EXPECT_TRUE((IsStringInDict(string, item))); |
| 294 | 298 |
| 295 EXPECT_FIND_("ETW Trace Event"); | 299 EXPECT_FIND_("ETW Trace Event"); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 338 EXPECT_FIND_("TRACE_EVENT_END0 call"); | 342 EXPECT_FIND_("TRACE_EVENT_END0 call"); |
| 339 EXPECT_FIND_("TRACE_EVENT_END1 call"); | 343 EXPECT_FIND_("TRACE_EVENT_END1 call"); |
| 340 EXPECT_FIND_("TRACE_EVENT_END2 call"); | 344 EXPECT_FIND_("TRACE_EVENT_END2 call"); |
| 341 EXPECT_SUB_FIND_("name1"); | 345 EXPECT_SUB_FIND_("name1"); |
| 342 EXPECT_SUB_FIND_("value1"); | 346 EXPECT_SUB_FIND_("value1"); |
| 343 EXPECT_SUB_FIND_("name2"); | 347 EXPECT_SUB_FIND_("name2"); |
| 344 EXPECT_SUB_FIND_("value2"); | 348 EXPECT_SUB_FIND_("value2"); |
| 345 } | 349 } |
| 346 | 350 |
| 347 void TraceManyInstantEvents(int thread_id, int num_events, | 351 void TraceManyInstantEvents(int thread_id, int num_events, |
| 348 WaitableEvent* task_complete_event) { | 352 WaitableEvent* task_complete_event) { |
| 349 for (int i = 0; i < num_events; i++) { | 353 for (int i = 0; i < num_events; i++) { |
| 350 TRACE_EVENT_INSTANT2("all", "multi thread event", | 354 TRACE_EVENT_INSTANT2("all", "multi thread event", |
| 351 "thread", thread_id, | 355 "thread", thread_id, |
| 352 "event", i); | 356 "event", i); |
| 353 } | 357 } |
| 354 | 358 |
| 355 if (task_complete_event) | 359 if (task_complete_event) |
| 356 task_complete_event->Signal(); | 360 task_complete_event->Signal(); |
| 357 } | 361 } |
| 358 | 362 |
| 359 void ValidateInstantEventPresentOnEveryThread(const ListValue& trace_parsed, | 363 void ValidateInstantEventPresentOnEveryThread(const ListValue& trace_parsed, |
| 360 const std::string& trace_string, | 364 int num_threads, |
| 361 int num_threads, int num_events) { | 365 int num_events) { |
| 362 std::map<int, std::map<int, bool> > results; | 366 std::map<int, std::map<int, bool> > results; |
| 363 | 367 |
| 364 size_t trace_parsed_count = trace_parsed.GetSize(); | 368 size_t trace_parsed_count = trace_parsed.GetSize(); |
| 365 for (size_t i = 0; i < trace_parsed_count; i++) { | 369 for (size_t i = 0; i < trace_parsed_count; i++) { |
| 366 Value* value = NULL; | 370 Value* value = NULL; |
| 367 trace_parsed.Get(i, &value); | 371 trace_parsed.Get(i, &value); |
| 368 if (!value || value->GetType() != Value::TYPE_DICTIONARY) | 372 if (!value || value->GetType() != Value::TYPE_DICTIONARY) |
| 369 continue; | 373 continue; |
| 370 DictionaryValue* dict = static_cast<DictionaryValue*>(value); | 374 DictionaryValue* dict = static_cast<DictionaryValue*>(value); |
| 371 std::string name; | 375 std::string name; |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 399 | 403 |
| 400 // Simple Test for emitting data and validating it was received. | 404 // Simple Test for emitting data and validating it was received. |
| 401 TEST_F(TraceEventTestFixture, DataCaptured) { | 405 TEST_F(TraceEventTestFixture, DataCaptured) { |
| 402 ManualTestSetUp(); | 406 ManualTestSetUp(); |
| 403 TraceLog::GetInstance()->SetEnabled(true); | 407 TraceLog::GetInstance()->SetEnabled(true); |
| 404 | 408 |
| 405 TraceWithAllMacroVariants(NULL); | 409 TraceWithAllMacroVariants(NULL); |
| 406 | 410 |
| 407 TraceLog::GetInstance()->SetEnabled(false); | 411 TraceLog::GetInstance()->SetEnabled(false); |
| 408 | 412 |
| 409 ValidateAllTraceMacrosCreatedData(trace_parsed_, trace_string_); | 413 ValidateAllTraceMacrosCreatedData(trace_parsed_); |
| 410 } | 414 } |
| 411 | 415 |
| 412 // Test that categories work. | 416 // Test that categories work. |
| 413 TEST_F(TraceEventTestFixture, Categories) { | 417 TEST_F(TraceEventTestFixture, Categories) { |
| 414 ManualTestSetUp(); | 418 ManualTestSetUp(); |
| 415 | 419 |
| 416 // Test that categories that are used can be retrieved whether trace was | 420 // Test that categories that are used can be retrieved whether trace was |
| 417 // enabled or disabled when the trace event was encountered. | 421 // enabled or disabled when the trace event was encountered. |
| 418 TRACE_EVENT_INSTANT0("c1", "name"); | 422 TRACE_EVENT_INSTANT0("c1", "name"); |
| 419 TRACE_EVENT_INSTANT0("c2", "name"); | 423 TRACE_EVENT_INSTANT0("c2", "name"); |
| (...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 680 Thread thread("1"); | 684 Thread thread("1"); |
| 681 WaitableEvent task_complete_event(false, false); | 685 WaitableEvent task_complete_event(false, false); |
| 682 thread.Start(); | 686 thread.Start(); |
| 683 | 687 |
| 684 thread.message_loop()->PostTask( | 688 thread.message_loop()->PostTask( |
| 685 FROM_HERE, base::Bind(&TraceWithAllMacroVariants, &task_complete_event)); | 689 FROM_HERE, base::Bind(&TraceWithAllMacroVariants, &task_complete_event)); |
| 686 task_complete_event.Wait(); | 690 task_complete_event.Wait(); |
| 687 thread.Stop(); | 691 thread.Stop(); |
| 688 | 692 |
| 689 TraceLog::GetInstance()->SetEnabled(false); | 693 TraceLog::GetInstance()->SetEnabled(false); |
| 690 ValidateAllTraceMacrosCreatedData(trace_parsed_, trace_string_); | 694 ValidateAllTraceMacrosCreatedData(trace_parsed_); |
| 691 } | 695 } |
| 692 | 696 |
| 693 // Test that data sent from multiple threads is gathered | 697 // Test that data sent from multiple threads is gathered |
| 694 TEST_F(TraceEventTestFixture, DataCapturedManyThreads) { | 698 TEST_F(TraceEventTestFixture, DataCapturedManyThreads) { |
| 695 ManualTestSetUp(); | 699 ManualTestSetUp(); |
| 696 TraceLog::GetInstance()->SetEnabled(true); | 700 TraceLog::GetInstance()->SetEnabled(true); |
| 697 | 701 |
| 698 const int num_threads = 4; | 702 const int num_threads = 4; |
| 699 const int num_events = 4000; | 703 const int num_events = 4000; |
| 700 Thread* threads[num_threads]; | 704 Thread* threads[num_threads]; |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 713 } | 717 } |
| 714 | 718 |
| 715 for (int i = 0; i < num_threads; i++) { | 719 for (int i = 0; i < num_threads; i++) { |
| 716 threads[i]->Stop(); | 720 threads[i]->Stop(); |
| 717 delete threads[i]; | 721 delete threads[i]; |
| 718 delete task_complete_events[i]; | 722 delete task_complete_events[i]; |
| 719 } | 723 } |
| 720 | 724 |
| 721 TraceLog::GetInstance()->SetEnabled(false); | 725 TraceLog::GetInstance()->SetEnabled(false); |
| 722 | 726 |
| 723 ValidateInstantEventPresentOnEveryThread(trace_parsed_, trace_string_, | 727 ValidateInstantEventPresentOnEveryThread(trace_parsed_, |
| 724 num_threads, num_events); | 728 num_threads, num_events); |
| 725 } | 729 } |
| 726 | 730 |
| 727 // Test that thread and process names show up in the trace | 731 // Test that thread and process names show up in the trace |
| 728 TEST_F(TraceEventTestFixture, ThreadNames) { | 732 TEST_F(TraceEventTestFixture, ThreadNames) { |
| 729 ManualTestSetUp(); | 733 ManualTestSetUp(); |
| 730 | 734 |
| 731 // Create threads before we enable tracing to make sure | 735 // Create threads before we enable tracing to make sure |
| 732 // that tracelog still captures them. | 736 // that tracelog still captures them. |
| 733 const int num_threads = 4; | 737 const int num_threads = 4; |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 918 EXPECT_TRUE(entry2->GetInteger("args.arg1", &i)); | 922 EXPECT_TRUE(entry2->GetInteger("args.arg1", &i)); |
| 919 EXPECT_EQ(5, i); | 923 EXPECT_EQ(5, i); |
| 920 | 924 |
| 921 std::string s; | 925 std::string s; |
| 922 EXPECT_TRUE(entry3->GetString("args.arg1", &s)); | 926 EXPECT_TRUE(entry3->GetString("args.arg1", &s)); |
| 923 EXPECT_EQ("val1", s); | 927 EXPECT_EQ("val1", s); |
| 924 EXPECT_TRUE(entry3->GetString("args.arg2", &s)); | 928 EXPECT_TRUE(entry3->GetString("args.arg2", &s)); |
| 925 EXPECT_EQ("val2", s); | 929 EXPECT_EQ("val2", s); |
| 926 } | 930 } |
| 927 | 931 |
| 932 // Test that TraceResultBuffer outputs the correct result whether it is added | |
| 933 // in chunks or added all at once. | |
| 934 TEST_F(TraceEventTestFixture, TraceResultBuffer) { | |
| 935 ManualTestSetUp(); | |
| 936 | |
| 937 Clear(); | |
| 938 | |
| 939 trace_buffer_.Start(); | |
| 940 trace_buffer_.AddFragment("bla1"); | |
| 941 trace_buffer_.AddFragment("bla2"); | |
| 942 trace_buffer_.AddFragment("bla3,bla4"); | |
| 943 trace_buffer_.Finish(); | |
| 944 EXPECT_STREQ(json_output_.json_output.c_str(), "[bla1,bla2,bla3,bla4]"); | |
| 945 | |
| 946 Clear(); | |
|
nduca
2011/10/20 23:20:05
This is two tests, no?
jbates
2011/10/20 23:55:13
Easier to follow in one test IMO. Is there a rule
| |
| 947 | |
| 948 trace_buffer_.Start(); | |
| 949 trace_buffer_.AddFragment("bla1,bla2,bla3,bla4"); | |
| 950 trace_buffer_.Finish(); | |
| 951 EXPECT_STREQ(json_output_.json_output.c_str(), "[bla1,bla2,bla3,bla4]"); | |
| 952 } | |
| 953 | |
|
nduca
2011/10/20 23:20:05
Output callback test?
Any corner cases?
Not a big
jbates
2011/10/20 23:55:13
Output callback is tested by every other test now,
| |
| 928 } // namespace debug | 954 } // namespace debug |
| 929 } // namespace base | 955 } // namespace base |
| OLD | NEW |