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> | 7 #include <vector> |
8 | 8 |
9 #include "base/bind_helpers.h" | 9 #include "base/bind_helpers.h" |
10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
11 #include "base/message_loop/message_loop.h" | 11 #include "base/message_loop/message_loop.h" |
12 #include "base/run_loop.h" | 12 #include "base/run_loop.h" |
13 #include "base/strings/stringprintf.h" | 13 #include "base/strings/stringprintf.h" |
14 #include "base/synchronization/waitable_event.h" | 14 #include "base/synchronization/waitable_event.h" |
15 #include "base/test/test_io_thread.h" | 15 #include "base/test/test_io_thread.h" |
16 #include "base/test/trace_event_analyzer.h" | 16 #include "base/test/trace_event_analyzer.h" |
17 #include "base/thread_task_runner_handle.h" | 17 #include "base/thread_task_runner_handle.h" |
18 #include "base/threading/platform_thread.h" | |
18 #include "base/threading/thread.h" | 19 #include "base/threading/thread.h" |
19 #include "base/trace_event/memory_dump_provider.h" | 20 #include "base/trace_event/memory_dump_provider.h" |
20 #include "base/trace_event/process_memory_dump.h" | 21 #include "base/trace_event/process_memory_dump.h" |
21 #include "base/trace_event/trace_buffer.h" | 22 #include "base/trace_event/trace_buffer.h" |
22 #include "base/trace_event/trace_config_memory_test_util.h" | 23 #include "base/trace_event/trace_config_memory_test_util.h" |
23 #include "testing/gmock/include/gmock/gmock.h" | 24 #include "testing/gmock/include/gmock/gmock.h" |
24 #include "testing/gtest/include/gtest/gtest.h" | 25 #include "testing/gtest/include/gtest/gtest.h" |
25 | 26 |
26 using testing::_; | 27 using testing::_; |
27 using testing::AnyNumber; | 28 using testing::AnyNumber; |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
84 const MemoryDumpCallback& callback)); | 85 const MemoryDumpCallback& callback)); |
85 | 86 |
86 uint64 GetTracingProcessId() const override { | 87 uint64 GetTracingProcessId() const override { |
87 NOTREACHED(); | 88 NOTREACHED(); |
88 return MemoryDumpManager::kInvalidTracingProcessId; | 89 return MemoryDumpManager::kInvalidTracingProcessId; |
89 } | 90 } |
90 }; | 91 }; |
91 | 92 |
92 class MockMemoryDumpProvider : public MemoryDumpProvider { | 93 class MockMemoryDumpProvider : public MemoryDumpProvider { |
93 public: | 94 public: |
95 MOCK_METHOD0(Destructor, void()); | |
94 MOCK_METHOD2(OnMemoryDump, | 96 MOCK_METHOD2(OnMemoryDump, |
95 bool(const MemoryDumpArgs& args, ProcessMemoryDump* pmd)); | 97 bool(const MemoryDumpArgs& args, ProcessMemoryDump* pmd)); |
98 | |
99 MockMemoryDumpProvider() : enable_mock_destructor(false) {} | |
100 ~MockMemoryDumpProvider() override { | |
101 if (enable_mock_destructor) | |
102 Destructor(); | |
103 } | |
104 | |
105 bool enable_mock_destructor; | |
96 }; | 106 }; |
97 | 107 |
98 class MemoryDumpManagerTest : public testing::Test { | 108 class MemoryDumpManagerTest : public testing::Test { |
99 public: | 109 public: |
100 MemoryDumpManagerTest() : testing::Test(), kDefaultOptions() {} | 110 MemoryDumpManagerTest() : testing::Test(), kDefaultOptions() {} |
101 | 111 |
102 void SetUp() override { | 112 void SetUp() override { |
103 last_callback_success_ = false; | 113 last_callback_success_ = false; |
104 message_loop_.reset(new MessageLoop()); | 114 message_loop_.reset(new MessageLoop()); |
105 mdm_.reset(new MemoryDumpManager()); | 115 mdm_.reset(new MemoryDumpManager()); |
(...skipping 762 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
868 | 878 |
869 ASSERT_EQ(3u, events.size()); | 879 ASSERT_EQ(3u, events.size()); |
870 ASSERT_EQ(1u, trace_analyzer::CountMatches(events, Query::EventPidIs(123))); | 880 ASSERT_EQ(1u, trace_analyzer::CountMatches(events, Query::EventPidIs(123))); |
871 ASSERT_EQ(1u, trace_analyzer::CountMatches(events, Query::EventPidIs(456))); | 881 ASSERT_EQ(1u, trace_analyzer::CountMatches(events, Query::EventPidIs(456))); |
872 ASSERT_EQ(1u, trace_analyzer::CountMatches( | 882 ASSERT_EQ(1u, trace_analyzer::CountMatches( |
873 events, Query::EventPidIs(GetCurrentProcId()))); | 883 events, Query::EventPidIs(GetCurrentProcId()))); |
874 ASSERT_EQ(events[0]->id, events[1]->id); | 884 ASSERT_EQ(events[0]->id, events[1]->id); |
875 ASSERT_EQ(events[0]->id, events[2]->id); | 885 ASSERT_EQ(events[0]->id, events[2]->id); |
876 } | 886 } |
877 | 887 |
888 // Tests the basics of the UnregisterAndDeleteDumpProviderAsync(): the | |
889 // unregistration should actually delete the providers and not leak them. | |
890 TEST_F(MemoryDumpManagerTest, UnregisterAndDeleteDumpProviderAsync) { | |
891 InitializeMemoryDumpManager(false /* is_coordinator */); | |
892 static const int kNumProviders = 3; | |
893 int dtor_count = 0; | |
894 std::vector<scoped_ptr<MemoryDumpProvider>> mdps; | |
895 for (int i = 0; i < kNumProviders; ++i) { | |
896 scoped_ptr<MockMemoryDumpProvider> mdp(new MockMemoryDumpProvider); | |
897 mdp->enable_mock_destructor = true; | |
898 EXPECT_CALL(*mdp, Destructor()) | |
899 .WillOnce(Invoke([&dtor_count]() -> void { dtor_count++; })); | |
Ruud van Asseldonk
2015/12/29 11:32:46
The |-> void| part can be omitted.
Primiano Tucci (use gerrit)
2016/01/04 14:44:38
Did I already say this week that I hate C++11 lam
| |
900 RegisterDumpProvider(mdp.get()); | |
901 mdps.push_back(std::move(mdp)); | |
902 } | |
903 | |
904 while (!mdps.empty()) { | |
905 mdm_->UnregisterAndDeleteDumpProviderAsync(std::move(mdps.back())); | |
Ruud van Asseldonk
2015/12/29 11:32:46
So actually deletion is happening synchronously he
Primiano Tucci (use gerrit)
2016/01/04 14:44:38
Ok, Ok. I see what you mean. I renamed the method
| |
906 mdps.pop_back(); | |
907 } | |
908 | |
909 ASSERT_EQ(kNumProviders, dtor_count); | |
910 } | |
911 | |
912 // This test checks against races when unregistering an unbound dump provider | |
913 // from another thread while dumping. It register one MDP and when | |
ssid
2015/12/22 16:14:56
s/register/registers/
Primiano Tucci (use gerrit)
2016/01/04 14:44:38
Done.
| |
914 // OnMemoryDump() is called, it invokes UnregisterAndDeleteDumpProviderAsync() | |
915 // from another thread. The OnMemoryDump() and the dtor call are expected to | |
916 // happen on the same thread (the MemoryDumpManager utility thread). | |
917 TEST_F(MemoryDumpManagerTest, UnregisterAndDeleteDumpProviderAsyncDuringDump) { | |
918 InitializeMemoryDumpManager(false /* is_coordinator */); | |
919 scoped_ptr<MockMemoryDumpProvider> mdp(new MockMemoryDumpProvider); | |
920 mdp->enable_mock_destructor = true; | |
921 RegisterDumpProvider(mdp.get()); | |
922 | |
923 base::PlatformThreadRef thread_ref; | |
924 auto self_unregister_from_another_thread = [&mdp, &thread_ref]( | |
925 const MemoryDumpArgs&, ProcessMemoryDump*) -> bool { | |
926 thread_ref = PlatformThread::CurrentRef(); | |
927 TestIOThread thread_for_unregistration(TestIOThread::kAutoStart); | |
928 thread_for_unregistration.PostTaskAndWait( | |
929 FROM_HERE, | |
930 base::Bind( | |
931 &MemoryDumpManager::UnregisterAndDeleteDumpProviderAsync, | |
932 base::Unretained(MemoryDumpManager::GetInstance()), | |
933 base::Passed(scoped_ptr<MemoryDumpProvider>(std::move(mdp))))); | |
Ruud van Asseldonk
2015/12/29 11:32:46
Why is the extra |scoped_ptr| temporary required?
Primiano Tucci (use gerrit)
2016/01/04 14:44:38
I know but this is for upcasting from scoped_ptr<M
Ruud van Asseldonk
2016/01/04 15:43:01
Ah, I see.
| |
934 thread_for_unregistration.Stop(); | |
935 return true; | |
936 }; | |
937 EXPECT_CALL(*mdp, OnMemoryDump(_, _)) | |
938 .Times(1) | |
939 .WillOnce(Invoke(self_unregister_from_another_thread)); | |
940 EXPECT_CALL(*mdp, Destructor()) | |
941 .Times(1) | |
942 .WillOnce(Invoke([&thread_ref]() -> void { | |
Ruud van Asseldonk
2015/12/29 11:32:46
The |-> void| part can be omitted.
Primiano Tucci (use gerrit)
2016/01/04 14:44:38
Done.
| |
943 EXPECT_EQ(thread_ref, PlatformThread::CurrentRef()); | |
944 })); | |
945 | |
946 EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory); | |
947 EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(2); | |
948 for (int i = 0; i < 2; ++i) { | |
949 RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED, | |
950 MemoryDumpLevelOfDetail::DETAILED); | |
951 } | |
952 DisableTracing(); | |
953 | |
954 // Ownership of |mdp| should have been transferred to the MemoryDumpManager at | |
955 // the time UnregisterAndDeleteDumpProviderAsync() was called. | |
956 ASSERT_FALSE(mdp); | |
Ruud van Asseldonk
2015/12/29 11:32:46
I would say |ASSERT_NE(nullptr, mdp.get())|, |mdp|
Primiano Tucci (use gerrit)
2016/01/04 14:44:38
I think you are right. What I am really doing here
| |
957 } | |
958 | |
878 } // namespace trace_event | 959 } // namespace trace_event |
879 } // namespace base | 960 } // namespace base |
OLD | NEW |