OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 #include "components/discardable_memory/common/discardable_shared_memory_manager .h" |
5 #include "content/common/host_discardable_shared_memory_manager.h" | |
6 | 5 |
7 #include <stddef.h> | 6 #include <stddef.h> |
8 #include <stdint.h> | 7 #include <stdint.h> |
9 #include <string.h> | 8 #include <string.h> |
10 | 9 |
10 #include "base/message_loop/message_loop.h" | |
11 #include "base/threading/simple_thread.h" | 11 #include "base/threading/simple_thread.h" |
12 #include "content/public/common/child_process_host.h" | |
13 #include "testing/gtest/include/gtest/gtest.h" | 12 #include "testing/gtest/include/gtest/gtest.h" |
14 | 13 |
15 namespace content { | 14 namespace discardable_memory { |
16 namespace { | 15 namespace { |
17 | 16 |
17 const int kInvalidUniqueID = -1; | |
18 | |
18 class TestDiscardableSharedMemory : public base::DiscardableSharedMemory { | 19 class TestDiscardableSharedMemory : public base::DiscardableSharedMemory { |
19 public: | 20 public: |
20 TestDiscardableSharedMemory() {} | 21 TestDiscardableSharedMemory() {} |
21 | 22 |
22 explicit TestDiscardableSharedMemory(base::SharedMemoryHandle handle) | 23 explicit TestDiscardableSharedMemory(base::SharedMemoryHandle handle) |
23 : DiscardableSharedMemory(handle) {} | 24 : DiscardableSharedMemory(handle) {} |
24 | 25 |
25 void SetNow(base::Time now) { now_ = now; } | 26 void SetNow(base::Time now) { now_ = now; } |
26 | 27 |
27 private: | 28 private: |
28 // Overriden from base::DiscardableSharedMemory: | 29 // Overriden from base::DiscardableSharedMemory: |
29 base::Time Now() const override { return now_; } | 30 base::Time Now() const override { return now_; } |
30 | 31 |
31 base::Time now_; | 32 base::Time now_; |
32 }; | 33 }; |
33 | 34 |
34 class TestHostDiscardableSharedMemoryManager | 35 class TestDiscardableSharedMemoryManager |
35 : public HostDiscardableSharedMemoryManager { | 36 : public DiscardableSharedMemoryManager { |
36 public: | 37 public: |
37 TestHostDiscardableSharedMemoryManager() | 38 TestDiscardableSharedMemoryManager() |
38 : enforce_memory_policy_pending_(false) {} | 39 : enforce_memory_policy_pending_(false) {} |
39 | 40 |
40 void SetNow(base::Time now) { now_ = now; } | 41 void SetNow(base::Time now) { now_ = now; } |
41 | 42 |
42 void set_enforce_memory_policy_pending(bool enforce_memory_policy_pending) { | 43 void set_enforce_memory_policy_pending(bool enforce_memory_policy_pending) { |
43 enforce_memory_policy_pending_ = enforce_memory_policy_pending; | 44 enforce_memory_policy_pending_ = enforce_memory_policy_pending; |
44 } | 45 } |
45 bool enforce_memory_policy_pending() const { | 46 bool enforce_memory_policy_pending() const { |
46 return enforce_memory_policy_pending_; | 47 return enforce_memory_policy_pending_; |
47 } | 48 } |
48 | 49 |
49 private: | 50 private: |
50 // Overriden from HostDiscardableSharedMemoryManager: | 51 // Overriden from DiscardableSharedMemoryManager: |
51 base::Time Now() const override { return now_; } | 52 base::Time Now() const override { return now_; } |
52 void ScheduleEnforceMemoryPolicy() override { | 53 void ScheduleEnforceMemoryPolicy() override { |
53 enforce_memory_policy_pending_ = true; | 54 enforce_memory_policy_pending_ = true; |
54 } | 55 } |
55 | 56 |
56 base::Time now_; | 57 base::Time now_; |
57 bool enforce_memory_policy_pending_; | 58 bool enforce_memory_policy_pending_; |
58 }; | 59 }; |
59 | 60 |
60 class HostDiscardableSharedMemoryManagerTest : public testing::Test { | 61 class DiscardableSharedMemoryManagerTest : public testing::Test { |
61 protected: | 62 protected: |
62 // Overridden from testing::Test: | 63 // Overridden from testing::Test: |
63 void SetUp() override { | 64 void SetUp() override { |
64 manager_.reset(new TestHostDiscardableSharedMemoryManager); | 65 manager_.reset(new TestDiscardableSharedMemoryManager); |
65 } | 66 } |
66 | 67 |
67 // HostDiscardableSharedMemoryManager requires a message loop. | 68 // DiscardableSharedMemoryManager requires a message loop. |
68 base::MessageLoop message_loop_; | 69 base::MessageLoop message_loop_; |
69 std::unique_ptr<TestHostDiscardableSharedMemoryManager> manager_; | 70 std::unique_ptr<TestDiscardableSharedMemoryManager> manager_; |
70 }; | 71 }; |
71 | 72 |
72 TEST_F(HostDiscardableSharedMemoryManagerTest, AllocateForChild) { | 73 TEST_F(DiscardableSharedMemoryManagerTest, AllocateForChild) { |
reveman
2016/11/01 17:18:39
nit: s/Child/Client/
Peng
2016/11/01 18:38:30
Done.
| |
73 const int kDataSize = 1024; | 74 const int kDataSize = 1024; |
74 uint8_t data[kDataSize]; | 75 uint8_t data[kDataSize]; |
75 memset(data, 0x80, kDataSize); | 76 memset(data, 0x80, kDataSize); |
76 | 77 |
77 base::SharedMemoryHandle shared_handle; | 78 base::SharedMemoryHandle shared_handle; |
78 manager_->AllocateLockedDiscardableSharedMemoryForChild( | 79 manager_->AllocateLockedDiscardableSharedMemoryForChild( |
79 base::GetCurrentProcessHandle(), ChildProcessHost::kInvalidUniqueID, | 80 base::GetCurrentProcessHandle(), kInvalidUniqueID, kDataSize, 0, |
80 kDataSize, 0, &shared_handle); | 81 &shared_handle); |
81 ASSERT_TRUE(base::SharedMemory::IsHandleValid(shared_handle)); | 82 ASSERT_TRUE(base::SharedMemory::IsHandleValid(shared_handle)); |
82 | 83 |
83 TestDiscardableSharedMemory memory(shared_handle); | 84 TestDiscardableSharedMemory memory(shared_handle); |
84 bool rv = memory.Map(kDataSize); | 85 bool rv = memory.Map(kDataSize); |
85 ASSERT_TRUE(rv); | 86 ASSERT_TRUE(rv); |
86 | 87 |
87 memcpy(memory.memory(), data, kDataSize); | 88 memcpy(memory.memory(), data, kDataSize); |
88 memory.SetNow(base::Time::FromDoubleT(1)); | 89 memory.SetNow(base::Time::FromDoubleT(1)); |
89 memory.Unlock(0, 0); | 90 memory.Unlock(0, 0); |
90 | 91 |
91 ASSERT_EQ(base::DiscardableSharedMemory::SUCCESS, memory.Lock(0, 0)); | 92 ASSERT_EQ(base::DiscardableSharedMemory::SUCCESS, memory.Lock(0, 0)); |
92 EXPECT_EQ(memcmp(data, memory.memory(), kDataSize), 0); | 93 EXPECT_EQ(memcmp(data, memory.memory(), kDataSize), 0); |
93 memory.Unlock(0, 0); | 94 memory.Unlock(0, 0); |
94 } | 95 } |
95 | 96 |
96 TEST_F(HostDiscardableSharedMemoryManagerTest, Purge) { | 97 TEST_F(DiscardableSharedMemoryManagerTest, Purge) { |
97 const int kDataSize = 1024; | 98 const int kDataSize = 1024; |
98 | 99 |
99 base::SharedMemoryHandle shared_handle1; | 100 base::SharedMemoryHandle shared_handle1; |
100 manager_->AllocateLockedDiscardableSharedMemoryForChild( | 101 manager_->AllocateLockedDiscardableSharedMemoryForChild( |
101 base::GetCurrentProcessHandle(), ChildProcessHost::kInvalidUniqueID, | 102 base::GetCurrentProcessHandle(), kInvalidUniqueID, kDataSize, 1, |
102 kDataSize, 1, &shared_handle1); | 103 &shared_handle1); |
103 ASSERT_TRUE(base::SharedMemory::IsHandleValid(shared_handle1)); | 104 ASSERT_TRUE(base::SharedMemory::IsHandleValid(shared_handle1)); |
104 | 105 |
105 TestDiscardableSharedMemory memory1(shared_handle1); | 106 TestDiscardableSharedMemory memory1(shared_handle1); |
106 bool rv = memory1.Map(kDataSize); | 107 bool rv = memory1.Map(kDataSize); |
107 ASSERT_TRUE(rv); | 108 ASSERT_TRUE(rv); |
108 | 109 |
109 base::SharedMemoryHandle shared_handle2; | 110 base::SharedMemoryHandle shared_handle2; |
110 manager_->AllocateLockedDiscardableSharedMemoryForChild( | 111 manager_->AllocateLockedDiscardableSharedMemoryForChild( |
111 base::GetCurrentProcessHandle(), ChildProcessHost::kInvalidUniqueID, | 112 base::GetCurrentProcessHandle(), kInvalidUniqueID, kDataSize, 2, |
112 kDataSize, 2, &shared_handle2); | 113 &shared_handle2); |
113 ASSERT_TRUE(base::SharedMemory::IsHandleValid(shared_handle2)); | 114 ASSERT_TRUE(base::SharedMemory::IsHandleValid(shared_handle2)); |
114 | 115 |
115 TestDiscardableSharedMemory memory2(shared_handle2); | 116 TestDiscardableSharedMemory memory2(shared_handle2); |
116 rv = memory2.Map(kDataSize); | 117 rv = memory2.Map(kDataSize); |
117 ASSERT_TRUE(rv); | 118 ASSERT_TRUE(rv); |
118 | 119 |
119 // Enough memory for both allocations. | 120 // Enough memory for both allocations. |
120 manager_->SetNow(base::Time::FromDoubleT(1)); | 121 manager_->SetNow(base::Time::FromDoubleT(1)); |
121 manager_->SetMemoryLimit(memory1.mapped_size() + memory2.mapped_size()); | 122 manager_->SetMemoryLimit(memory1.mapped_size() + memory2.mapped_size()); |
122 | 123 |
(...skipping 29 matching lines...) Expand all Loading... | |
152 // LRU allocation should still be resident. | 153 // LRU allocation should still be resident. |
153 EXPECT_FALSE(memory1.IsMemoryResident()); | 154 EXPECT_FALSE(memory1.IsMemoryResident()); |
154 EXPECT_TRUE(memory2.IsMemoryResident()); | 155 EXPECT_TRUE(memory2.IsMemoryResident()); |
155 | 156 |
156 lock_rv = memory1.Lock(0, 0); | 157 lock_rv = memory1.Lock(0, 0); |
157 EXPECT_EQ(base::DiscardableSharedMemory::FAILED, lock_rv); | 158 EXPECT_EQ(base::DiscardableSharedMemory::FAILED, lock_rv); |
158 lock_rv = memory2.Lock(0, 0); | 159 lock_rv = memory2.Lock(0, 0); |
159 EXPECT_EQ(base::DiscardableSharedMemory::SUCCESS, lock_rv); | 160 EXPECT_EQ(base::DiscardableSharedMemory::SUCCESS, lock_rv); |
160 } | 161 } |
161 | 162 |
162 TEST_F(HostDiscardableSharedMemoryManagerTest, EnforceMemoryPolicy) { | 163 TEST_F(DiscardableSharedMemoryManagerTest, EnforceMemoryPolicy) { |
163 const int kDataSize = 1024; | 164 const int kDataSize = 1024; |
164 | 165 |
165 base::SharedMemoryHandle shared_handle; | 166 base::SharedMemoryHandle shared_handle; |
166 manager_->AllocateLockedDiscardableSharedMemoryForChild( | 167 manager_->AllocateLockedDiscardableSharedMemoryForChild( |
167 base::GetCurrentProcessHandle(), ChildProcessHost::kInvalidUniqueID, | 168 base::GetCurrentProcessHandle(), kInvalidUniqueID, kDataSize, 0, |
168 kDataSize, 0, &shared_handle); | 169 &shared_handle); |
169 ASSERT_TRUE(base::SharedMemory::IsHandleValid(shared_handle)); | 170 ASSERT_TRUE(base::SharedMemory::IsHandleValid(shared_handle)); |
170 | 171 |
171 TestDiscardableSharedMemory memory(shared_handle); | 172 TestDiscardableSharedMemory memory(shared_handle); |
172 bool rv = memory.Map(kDataSize); | 173 bool rv = memory.Map(kDataSize); |
173 ASSERT_TRUE(rv); | 174 ASSERT_TRUE(rv); |
174 | 175 |
175 // Not enough memory for one allocation. | 176 // Not enough memory for one allocation. |
176 manager_->SetNow(base::Time::FromDoubleT(1)); | 177 manager_->SetNow(base::Time::FromDoubleT(1)); |
177 manager_->SetMemoryLimit(memory.mapped_size() - 1); | 178 manager_->SetMemoryLimit(memory.mapped_size() - 1); |
178 // We need to enforce memory policy as our memory usage is currently above | 179 // We need to enforce memory policy as our memory usage is currently above |
(...skipping 11 matching lines...) Expand all Loading... | |
190 | 191 |
191 manager_->set_enforce_memory_policy_pending(false); | 192 manager_->set_enforce_memory_policy_pending(false); |
192 manager_->SetNow(base::Time::FromDoubleT(4)); | 193 manager_->SetNow(base::Time::FromDoubleT(4)); |
193 manager_->EnforceMemoryPolicy(); | 194 manager_->EnforceMemoryPolicy(); |
194 // Memory policy should have successfully been enforced. | 195 // Memory policy should have successfully been enforced. |
195 EXPECT_FALSE(manager_->enforce_memory_policy_pending()); | 196 EXPECT_FALSE(manager_->enforce_memory_policy_pending()); |
196 | 197 |
197 EXPECT_EQ(base::DiscardableSharedMemory::FAILED, memory.Lock(0, 0)); | 198 EXPECT_EQ(base::DiscardableSharedMemory::FAILED, memory.Lock(0, 0)); |
198 } | 199 } |
199 | 200 |
200 TEST_F(HostDiscardableSharedMemoryManagerTest, | 201 TEST_F(DiscardableSharedMemoryManagerTest, |
201 ReduceMemoryAfterSegmentHasBeenDeleted) { | 202 ReduceMemoryAfterSegmentHasBeenDeleted) { |
202 const int kDataSize = 1024; | 203 const int kDataSize = 1024; |
203 | 204 |
204 base::SharedMemoryHandle shared_handle1; | 205 base::SharedMemoryHandle shared_handle1; |
205 manager_->AllocateLockedDiscardableSharedMemoryForChild( | 206 manager_->AllocateLockedDiscardableSharedMemoryForChild( |
206 base::GetCurrentProcessHandle(), ChildProcessHost::kInvalidUniqueID, | 207 base::GetCurrentProcessHandle(), kInvalidUniqueID, kDataSize, 1, |
207 kDataSize, 1, &shared_handle1); | 208 &shared_handle1); |
208 ASSERT_TRUE(base::SharedMemory::IsHandleValid(shared_handle1)); | 209 ASSERT_TRUE(base::SharedMemory::IsHandleValid(shared_handle1)); |
209 | 210 |
210 TestDiscardableSharedMemory memory1(shared_handle1); | 211 TestDiscardableSharedMemory memory1(shared_handle1); |
211 bool rv = memory1.Map(kDataSize); | 212 bool rv = memory1.Map(kDataSize); |
212 ASSERT_TRUE(rv); | 213 ASSERT_TRUE(rv); |
213 | 214 |
214 base::SharedMemoryHandle shared_handle2; | 215 base::SharedMemoryHandle shared_handle2; |
215 manager_->AllocateLockedDiscardableSharedMemoryForChild( | 216 manager_->AllocateLockedDiscardableSharedMemoryForChild( |
216 base::GetCurrentProcessHandle(), ChildProcessHost::kInvalidUniqueID, | 217 base::GetCurrentProcessHandle(), kInvalidUniqueID, kDataSize, 2, |
217 kDataSize, 2, &shared_handle2); | 218 &shared_handle2); |
218 ASSERT_TRUE(base::SharedMemory::IsHandleValid(shared_handle2)); | 219 ASSERT_TRUE(base::SharedMemory::IsHandleValid(shared_handle2)); |
219 | 220 |
220 TestDiscardableSharedMemory memory2(shared_handle2); | 221 TestDiscardableSharedMemory memory2(shared_handle2); |
221 rv = memory2.Map(kDataSize); | 222 rv = memory2.Map(kDataSize); |
222 ASSERT_TRUE(rv); | 223 ASSERT_TRUE(rv); |
223 | 224 |
224 // Unlock and delete segment 1. | 225 // Unlock and delete segment 1. |
225 memory1.SetNow(base::Time::FromDoubleT(1)); | 226 memory1.SetNow(base::Time::FromDoubleT(1)); |
226 memory1.Unlock(0, 0); | 227 memory1.Unlock(0, 0); |
227 memory1.Unmap(); | 228 memory1.Unmap(); |
228 memory1.Close(); | 229 memory1.Close(); |
229 manager_->ChildDeletedDiscardableSharedMemory( | 230 manager_->ChildDeletedDiscardableSharedMemory(1, kInvalidUniqueID); |
230 1, ChildProcessHost::kInvalidUniqueID); | |
231 | 231 |
232 // Make sure the manager is able to reduce memory after the segment 1 was | 232 // Make sure the manager is able to reduce memory after the segment 1 was |
233 // deleted. | 233 // deleted. |
234 manager_->SetNow(base::Time::FromDoubleT(2)); | 234 manager_->SetNow(base::Time::FromDoubleT(2)); |
235 manager_->SetMemoryLimit(0); | 235 manager_->SetMemoryLimit(0); |
236 | 236 |
237 // Unlock segment 2. | 237 // Unlock segment 2. |
238 memory2.SetNow(base::Time::FromDoubleT(3)); | 238 memory2.SetNow(base::Time::FromDoubleT(3)); |
239 memory2.Unlock(0, 0); | 239 memory2.Unlock(0, 0); |
240 } | 240 } |
241 | 241 |
242 class HostDiscardableSharedMemoryManagerScheduleEnforceMemoryPolicyTest | 242 class DiscardableSharedMemoryManagerScheduleEnforceMemoryPolicyTest |
243 : public testing::Test { | 243 : public testing::Test { |
244 protected: | 244 protected: |
245 // Overridden from testing::Test: | 245 // Overridden from testing::Test: |
246 void SetUp() override { | 246 void SetUp() override { manager_.reset(new DiscardableSharedMemoryManager); } |
247 manager_.reset(new HostDiscardableSharedMemoryManager); | |
248 } | |
249 | 247 |
250 // HostDiscardableSharedMemoryManager requires a message loop. | 248 // DiscardableSharedMemoryManager requires a message loop. |
251 base::MessageLoop message_loop_; | 249 base::MessageLoop message_loop_; |
252 std::unique_ptr<HostDiscardableSharedMemoryManager> manager_; | 250 std::unique_ptr<DiscardableSharedMemoryManager> manager_; |
253 }; | 251 }; |
254 | 252 |
255 class SetMemoryLimitRunner : public base::DelegateSimpleThread::Delegate { | 253 class SetMemoryLimitRunner : public base::DelegateSimpleThread::Delegate { |
256 public: | 254 public: |
257 SetMemoryLimitRunner(HostDiscardableSharedMemoryManager* manager, | 255 SetMemoryLimitRunner(DiscardableSharedMemoryManager* manager, size_t limit) |
258 size_t limit) | |
259 : manager_(manager), limit_(limit) {} | 256 : manager_(manager), limit_(limit) {} |
260 ~SetMemoryLimitRunner() override {} | 257 ~SetMemoryLimitRunner() override {} |
261 | 258 |
262 void Run() override { manager_->SetMemoryLimit(limit_); } | 259 void Run() override { manager_->SetMemoryLimit(limit_); } |
263 | 260 |
264 private: | 261 private: |
265 HostDiscardableSharedMemoryManager* const manager_; | 262 DiscardableSharedMemoryManager* const manager_; |
266 const size_t limit_; | 263 const size_t limit_; |
267 }; | 264 }; |
268 | 265 |
269 TEST_F(HostDiscardableSharedMemoryManagerScheduleEnforceMemoryPolicyTest, | 266 TEST_F(DiscardableSharedMemoryManagerScheduleEnforceMemoryPolicyTest, |
270 SetMemoryLimitOnSimpleThread) { | 267 SetMemoryLimitOnSimpleThread) { |
271 const int kDataSize = 1024; | 268 const int kDataSize = 1024; |
272 | 269 |
273 base::SharedMemoryHandle shared_handle; | 270 base::SharedMemoryHandle shared_handle; |
274 manager_->AllocateLockedDiscardableSharedMemoryForChild( | 271 manager_->AllocateLockedDiscardableSharedMemoryForChild( |
275 base::GetCurrentProcessHandle(), ChildProcessHost::kInvalidUniqueID, | 272 base::GetCurrentProcessHandle(), kInvalidUniqueID, kDataSize, 0, |
276 kDataSize, 0, &shared_handle); | 273 &shared_handle); |
277 ASSERT_TRUE(base::SharedMemory::IsHandleValid(shared_handle)); | 274 ASSERT_TRUE(base::SharedMemory::IsHandleValid(shared_handle)); |
278 | 275 |
279 // Set the memory limit to a value that will require EnforceMemoryPolicy() | 276 // Set the memory limit to a value that will require EnforceMemoryPolicy() |
280 // to be schedule on a thread without a message loop. | 277 // to be schedule on a thread without a message loop. |
281 SetMemoryLimitRunner runner(manager_.get(), kDataSize - 1); | 278 SetMemoryLimitRunner runner(manager_.get(), kDataSize - 1); |
282 base::DelegateSimpleThread thread(&runner, "memory_limit_setter"); | 279 base::DelegateSimpleThread thread(&runner, "memory_limit_setter"); |
283 thread.Start(); | 280 thread.Start(); |
284 thread.Join(); | 281 thread.Join(); |
285 } | 282 } |
286 | 283 |
287 } // namespace | 284 } // namespace |
288 } // namespace content | 285 } // namespace discardable_memory |
OLD | NEW |