OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/trace_event/memory_dump_manager.h" | 5 #include "base/trace_event/memory_dump_manager.h" |
6 | 6 |
| 7 #include <vector> |
| 8 |
7 #include "base/bind_helpers.h" | 9 #include "base/bind_helpers.h" |
8 #include "base/memory/scoped_vector.h" | 10 #include "base/memory/scoped_ptr.h" |
9 #include "base/message_loop/message_loop.h" | 11 #include "base/message_loop/message_loop.h" |
10 #include "base/run_loop.h" | 12 #include "base/run_loop.h" |
11 #include "base/strings/stringprintf.h" | 13 #include "base/strings/stringprintf.h" |
12 #include "base/synchronization/waitable_event.h" | 14 #include "base/synchronization/waitable_event.h" |
13 #include "base/test/test_io_thread.h" | 15 #include "base/test/test_io_thread.h" |
14 #include "base/test/trace_event_analyzer.h" | 16 #include "base/test/trace_event_analyzer.h" |
15 #include "base/thread_task_runner_handle.h" | 17 #include "base/thread_task_runner_handle.h" |
16 #include "base/threading/thread.h" | 18 #include "base/threading/thread.h" |
17 #include "base/trace_event/memory_dump_provider.h" | 19 #include "base/trace_event/memory_dump_provider.h" |
18 #include "base/trace_event/process_memory_dump.h" | 20 #include "base/trace_event/process_memory_dump.h" |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
195 for (int i = 0; i < 3; ++i) | 197 for (int i = 0; i < 3; ++i) |
196 RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED, | 198 RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED, |
197 MemoryDumpLevelOfDetail::DETAILED); | 199 MemoryDumpLevelOfDetail::DETAILED); |
198 DisableTracing(); | 200 DisableTracing(); |
199 | 201 |
200 mdm_->UnregisterDumpProvider(&mdp); | 202 mdm_->UnregisterDumpProvider(&mdp); |
201 | 203 |
202 // Finally check the unregister logic: the delegate will be invoked but not | 204 // Finally check the unregister logic: the delegate will be invoked but not |
203 // the dump provider, as it has been unregistered. | 205 // the dump provider, as it has been unregistered. |
204 EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory); | 206 EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory); |
205 EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1); | 207 EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(3); |
206 EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(0); | 208 EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(0); |
207 RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED, | 209 |
208 MemoryDumpLevelOfDetail::DETAILED); | 210 for (int i = 0; i < 3; ++i) { |
| 211 RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED, |
| 212 MemoryDumpLevelOfDetail::DETAILED); |
| 213 } |
209 DisableTracing(); | 214 DisableTracing(); |
210 } | 215 } |
211 | 216 |
212 // Checks that requesting dumps with high level of detail actually propagates | 217 // Checks that requesting dumps with high level of detail actually propagates |
213 // the level of the detail properly to OnMemoryDump() call on dump providers. | 218 // the level of the detail properly to OnMemoryDump() call on dump providers. |
214 TEST_F(MemoryDumpManagerTest, CheckMemoryDumpArgs) { | 219 TEST_F(MemoryDumpManagerTest, CheckMemoryDumpArgs) { |
215 InitializeMemoryDumpManager(false /* is_coordinator */); | 220 InitializeMemoryDumpManager(false /* is_coordinator */); |
216 MockMemoryDumpProvider mdp; | 221 MockMemoryDumpProvider mdp; |
217 | 222 |
218 RegisterDumpProvider(&mdp); | 223 RegisterDumpProvider(&mdp); |
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
524 MemoryDumpLevelOfDetail::DETAILED); | 529 MemoryDumpLevelOfDetail::DETAILED); |
525 } | 530 } |
526 | 531 |
527 DisableTracing(); | 532 DisableTracing(); |
528 } | 533 } |
529 | 534 |
530 // Checks that the dump does not abort when unregistering a provider while | 535 // Checks that the dump does not abort when unregistering a provider while |
531 // dumping from a different thread than the dumping thread. | 536 // dumping from a different thread than the dumping thread. |
532 TEST_F(MemoryDumpManagerTest, UnregisterDumperFromThreadWhileDumping) { | 537 TEST_F(MemoryDumpManagerTest, UnregisterDumperFromThreadWhileDumping) { |
533 InitializeMemoryDumpManager(false /* is_coordinator */); | 538 InitializeMemoryDumpManager(false /* is_coordinator */); |
534 ScopedVector<TestIOThread> threads; | 539 std::vector<scoped_ptr<TestIOThread>> threads; |
535 ScopedVector<MockMemoryDumpProvider> mdps; | 540 std::vector<scoped_ptr<MockMemoryDumpProvider>> mdps; |
536 | 541 |
537 for (int i = 0; i < 2; i++) { | 542 for (int i = 0; i < 2; i++) { |
538 threads.push_back(new TestIOThread(TestIOThread::kAutoStart)); | 543 threads.push_back( |
539 mdps.push_back(new MockMemoryDumpProvider()); | 544 make_scoped_ptr(new TestIOThread(TestIOThread::kAutoStart))); |
540 RegisterDumpProvider(mdps.back(), threads.back()->task_runner(), | 545 mdps.push_back(make_scoped_ptr(new MockMemoryDumpProvider())); |
| 546 RegisterDumpProvider(mdps.back().get(), threads.back()->task_runner(), |
541 kDefaultOptions); | 547 kDefaultOptions); |
542 } | 548 } |
543 | 549 |
544 int on_memory_dump_call_count = 0; | 550 int on_memory_dump_call_count = 0; |
545 | 551 |
546 // When OnMemoryDump is called on either of the dump providers, it will | 552 // When OnMemoryDump is called on either of the dump providers, it will |
547 // unregister the other one. | 553 // unregister the other one. |
548 for (MockMemoryDumpProvider* mdp : mdps) { | 554 for (const scoped_ptr<MockMemoryDumpProvider>& mdp : mdps) { |
549 int other_idx = (mdps.front() == mdp); | 555 int other_idx = (mdps.front() == mdp); |
550 TestIOThread* other_thread = threads[other_idx]; | 556 TestIOThread* other_thread = threads[other_idx].get(); |
551 MockMemoryDumpProvider* other_mdp = mdps[other_idx]; | 557 MockMemoryDumpProvider* other_mdp = mdps[other_idx].get(); |
552 auto on_dump = [this, other_thread, other_mdp, &on_memory_dump_call_count]( | 558 auto on_dump = [this, other_thread, other_mdp, &on_memory_dump_call_count]( |
553 const MemoryDumpArgs& args, ProcessMemoryDump* pmd) { | 559 const MemoryDumpArgs& args, ProcessMemoryDump* pmd) { |
554 other_thread->PostTaskAndWait( | 560 other_thread->PostTaskAndWait( |
555 FROM_HERE, base::Bind(&MemoryDumpManager::UnregisterDumpProvider, | 561 FROM_HERE, base::Bind(&MemoryDumpManager::UnregisterDumpProvider, |
556 base::Unretained(&*mdm_), other_mdp)); | 562 base::Unretained(&*mdm_), other_mdp)); |
557 on_memory_dump_call_count++; | 563 on_memory_dump_call_count++; |
558 return true; | 564 return true; |
559 }; | 565 }; |
560 | 566 |
561 // OnMemoryDump is called once for the provider that dumps first, and zero | 567 // OnMemoryDump is called once for the provider that dumps first, and zero |
562 // times for the other provider. | 568 // times for the other provider. |
563 EXPECT_CALL(*mdp, OnMemoryDump(_, _)) | 569 EXPECT_CALL(*mdp, OnMemoryDump(_, _)) |
564 .Times(AtMost(1)) | 570 .Times(AtMost(1)) |
565 .WillOnce(Invoke(on_dump)); | 571 .WillOnce(Invoke(on_dump)); |
566 } | 572 } |
567 | 573 |
568 last_callback_success_ = false; | 574 last_callback_success_ = false; |
569 EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory); | 575 EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory); |
570 EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1); | 576 EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1); |
571 RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED, | 577 RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED, |
572 MemoryDumpLevelOfDetail::DETAILED); | 578 MemoryDumpLevelOfDetail::DETAILED); |
573 ASSERT_EQ(1, on_memory_dump_call_count); | 579 ASSERT_EQ(1, on_memory_dump_call_count); |
574 ASSERT_EQ(true, last_callback_success_); | 580 ASSERT_TRUE(last_callback_success_); |
575 | 581 |
576 DisableTracing(); | 582 DisableTracing(); |
577 } | 583 } |
| 584 |
| 585 // If a thread (with a dump provider living on it) is torn down during a dump |
| 586 // its dump provider should be skipped but the dump itself should succeed. |
| 587 TEST_F(MemoryDumpManagerTest, TearDownThreadWhileDumping) { |
| 588 InitializeMemoryDumpManager(false /* is_coordinator */); |
| 589 std::vector<scoped_ptr<TestIOThread>> threads; |
| 590 std::vector<scoped_ptr<MockMemoryDumpProvider>> mdps; |
| 591 |
| 592 for (int i = 0; i < 2; i++) { |
| 593 threads.push_back( |
| 594 make_scoped_ptr(new TestIOThread(TestIOThread::kAutoStart))); |
| 595 mdps.push_back(make_scoped_ptr(new MockMemoryDumpProvider())); |
| 596 RegisterDumpProvider(mdps.back().get(), threads.back()->task_runner(), |
| 597 kDefaultOptions); |
| 598 } |
| 599 |
| 600 int on_memory_dump_call_count = 0; |
| 601 |
| 602 // When OnMemoryDump is called on either of the dump providers, it will |
| 603 // tear down the thread of the other one. |
| 604 for (const scoped_ptr<MockMemoryDumpProvider>& mdp : mdps) { |
| 605 int other_idx = (mdps.front() == mdp); |
| 606 TestIOThread* other_thread = threads[other_idx].get(); |
| 607 auto on_dump = [other_thread, &on_memory_dump_call_count]( |
| 608 const MemoryDumpArgs& args, ProcessMemoryDump* pmd) { |
| 609 other_thread->Stop(); |
| 610 on_memory_dump_call_count++; |
| 611 return true; |
| 612 }; |
| 613 |
| 614 // OnMemoryDump is called once for the provider that dumps first, and zero |
| 615 // times for the other provider. |
| 616 EXPECT_CALL(*mdp, OnMemoryDump(_, _)) |
| 617 .Times(AtMost(1)) |
| 618 .WillOnce(Invoke(on_dump)); |
| 619 } |
| 620 |
| 621 last_callback_success_ = false; |
| 622 EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory); |
| 623 EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1); |
| 624 RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED, |
| 625 MemoryDumpLevelOfDetail::DETAILED); |
| 626 ASSERT_EQ(1, on_memory_dump_call_count); |
| 627 ASSERT_TRUE(last_callback_success_); |
| 628 |
| 629 DisableTracing(); |
| 630 } |
578 | 631 |
579 // Checks that a NACK callback is invoked if RequestGlobalDump() is called when | 632 // Checks that a NACK callback is invoked if RequestGlobalDump() is called when |
580 // tracing is not enabled. | 633 // tracing is not enabled. |
581 TEST_F(MemoryDumpManagerTest, CallbackCalledOnFailure) { | 634 TEST_F(MemoryDumpManagerTest, CallbackCalledOnFailure) { |
582 InitializeMemoryDumpManager(false /* is_coordinator */); | 635 InitializeMemoryDumpManager(false /* is_coordinator */); |
583 MockMemoryDumpProvider mdp1; | 636 MockMemoryDumpProvider mdp1; |
584 RegisterDumpProvider(&mdp1); | 637 RegisterDumpProvider(&mdp1); |
585 | 638 |
586 EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(0); | 639 EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(0); |
587 EXPECT_CALL(mdp1, OnMemoryDump(_, _)).Times(0); | 640 EXPECT_CALL(mdp1, OnMemoryDump(_, _)).Times(0); |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
754 RunLoop run_loop; | 807 RunLoop run_loop; |
755 MemoryDumpCallback callback = | 808 MemoryDumpCallback callback = |
756 Bind(&MemoryDumpManagerTest::DumpCallbackAdapter, Unretained(this), | 809 Bind(&MemoryDumpManagerTest::DumpCallbackAdapter, Unretained(this), |
757 MessageLoop::current()->task_runner(), run_loop.QuitClosure()); | 810 MessageLoop::current()->task_runner(), run_loop.QuitClosure()); |
758 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, | 811 mdm_->RequestGlobalDump(MemoryDumpType::EXPLICITLY_TRIGGERED, |
759 MemoryDumpLevelOfDetail::DETAILED, callback); | 812 MemoryDumpLevelOfDetail::DETAILED, callback); |
760 DisableTracing(); | 813 DisableTracing(); |
761 tracing_disabled_event.Signal(); | 814 tracing_disabled_event.Signal(); |
762 run_loop.Run(); | 815 run_loop.Run(); |
763 | 816 |
764 // RequestGlobalMemoryDump() should be NACK-ed because one of the threads | 817 // RequestGlobalMemoryDump() should still suceed even if some threads were |
765 // threads died before we had a chance to PostTask onto them. | 818 // torn down during the dump. |
766 EXPECT_FALSE(last_callback_success_); | 819 EXPECT_TRUE(last_callback_success_); |
767 } | 820 } |
768 | 821 |
769 TEST_F(MemoryDumpManagerTest, DumpOnBehalfOfOtherProcess) { | 822 TEST_F(MemoryDumpManagerTest, DumpOnBehalfOfOtherProcess) { |
770 using trace_analyzer::Query; | 823 using trace_analyzer::Query; |
771 | 824 |
772 InitializeMemoryDumpManager(false /* is_coordinator */); | 825 InitializeMemoryDumpManager(false /* is_coordinator */); |
773 | 826 |
774 // Standard provider with default options (create dump for current process). | 827 // Standard provider with default options (create dump for current process). |
775 MemoryDumpProvider::Options options; | 828 MemoryDumpProvider::Options options; |
776 MockMemoryDumpProvider mdp1; | 829 MockMemoryDumpProvider mdp1; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
817 ASSERT_EQ(1u, trace_analyzer::CountMatches(events, Query::EventPidIs(123))); | 870 ASSERT_EQ(1u, trace_analyzer::CountMatches(events, Query::EventPidIs(123))); |
818 ASSERT_EQ(1u, trace_analyzer::CountMatches(events, Query::EventPidIs(456))); | 871 ASSERT_EQ(1u, trace_analyzer::CountMatches(events, Query::EventPidIs(456))); |
819 ASSERT_EQ(1u, trace_analyzer::CountMatches( | 872 ASSERT_EQ(1u, trace_analyzer::CountMatches( |
820 events, Query::EventPidIs(GetCurrentProcId()))); | 873 events, Query::EventPidIs(GetCurrentProcId()))); |
821 ASSERT_EQ(events[0]->id, events[1]->id); | 874 ASSERT_EQ(events[0]->id, events[1]->id); |
822 ASSERT_EQ(events[0]->id, events[2]->id); | 875 ASSERT_EQ(events[0]->id, events[2]->id); |
823 } | 876 } |
824 | 877 |
825 } // namespace trace_event | 878 } // namespace trace_event |
826 } // namespace base | 879 } // namespace base |
OLD | NEW |