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