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
3 // found in the LICENSE file.
5 #include "content/common/host_discardable_shared_memory_manager.h"
7 #include "content/public/common/child_process_host.h"
8 #include "testing/gtest/include/gtest/gtest.h"
13 class TestDiscardableSharedMemory
: public base::DiscardableSharedMemory
{
15 TestDiscardableSharedMemory() {}
17 explicit TestDiscardableSharedMemory(base::SharedMemoryHandle handle
)
18 : DiscardableSharedMemory(handle
) {}
20 void SetNow(base::Time now
) { now_
= now
; }
23 // Overriden from base::DiscardableSharedMemory:
24 base::Time
Now() const override
{ return now_
; }
29 class TestHostDiscardableSharedMemoryManager
30 : public HostDiscardableSharedMemoryManager
{
32 TestHostDiscardableSharedMemoryManager()
33 : enforce_memory_policy_pending_(false) {}
35 void SetNow(base::Time now
) { now_
= now
; }
37 void set_enforce_memory_policy_pending(bool enforce_memory_policy_pending
) {
38 enforce_memory_policy_pending_
= enforce_memory_policy_pending
;
40 bool enforce_memory_policy_pending() const {
41 return enforce_memory_policy_pending_
;
45 // Overriden from HostDiscardableSharedMemoryManager:
46 base::Time
Now() const override
{ return now_
; }
47 void ScheduleEnforceMemoryPolicy() override
{
48 enforce_memory_policy_pending_
= true;
52 bool enforce_memory_policy_pending_
;
55 class HostDiscardableSharedMemoryManagerTest
: public testing::Test
{
57 // Overridden from testing::Test:
58 void SetUp() override
{
59 manager_
.reset(new TestHostDiscardableSharedMemoryManager
);
62 scoped_ptr
<TestHostDiscardableSharedMemoryManager
> manager_
;
65 TEST_F(HostDiscardableSharedMemoryManagerTest
, AllocateForChild
) {
66 const int kDataSize
= 1024;
67 uint8 data
[kDataSize
];
68 memset(data
, 0x80, kDataSize
);
70 base::SharedMemoryHandle shared_handle
;
71 manager_
->AllocateLockedDiscardableSharedMemoryForChild(
72 base::GetCurrentProcessHandle(), ChildProcessHost::kInvalidUniqueID
,
73 kDataSize
, 0, &shared_handle
);
74 ASSERT_TRUE(base::SharedMemory::IsHandleValid(shared_handle
));
76 TestDiscardableSharedMemory
memory(shared_handle
);
77 bool rv
= memory
.Map(kDataSize
);
80 memcpy(memory
.memory(), data
, kDataSize
);
81 memory
.SetNow(base::Time::FromDoubleT(1));
84 ASSERT_EQ(base::DiscardableSharedMemory::SUCCESS
, memory
.Lock(0, 0));
85 EXPECT_EQ(memcmp(data
, memory
.memory(), kDataSize
), 0);
89 TEST_F(HostDiscardableSharedMemoryManagerTest
, Purge
) {
90 const int kDataSize
= 1024;
92 base::SharedMemoryHandle shared_handle1
;
93 manager_
->AllocateLockedDiscardableSharedMemoryForChild(
94 base::GetCurrentProcessHandle(), ChildProcessHost::kInvalidUniqueID
,
95 kDataSize
, 1, &shared_handle1
);
96 ASSERT_TRUE(base::SharedMemory::IsHandleValid(shared_handle1
));
98 TestDiscardableSharedMemory
memory1(shared_handle1
);
99 bool rv
= memory1
.Map(kDataSize
);
102 base::SharedMemoryHandle shared_handle2
;
103 manager_
->AllocateLockedDiscardableSharedMemoryForChild(
104 base::GetCurrentProcessHandle(), ChildProcessHost::kInvalidUniqueID
,
105 kDataSize
, 2, &shared_handle2
);
106 ASSERT_TRUE(base::SharedMemory::IsHandleValid(shared_handle2
));
108 TestDiscardableSharedMemory
memory2(shared_handle2
);
109 rv
= memory2
.Map(kDataSize
);
112 // Enough memory for both allocations.
113 manager_
->SetNow(base::Time::FromDoubleT(1));
114 manager_
->SetMemoryLimit(memory1
.mapped_size() + memory2
.mapped_size());
116 memory1
.SetNow(base::Time::FromDoubleT(2));
117 memory1
.Unlock(0, 0);
118 memory2
.SetNow(base::Time::FromDoubleT(2));
119 memory2
.Unlock(0, 0);
121 // Manager should not have to schedule another call to EnforceMemoryPolicy().
122 manager_
->SetNow(base::Time::FromDoubleT(3));
123 manager_
->EnforceMemoryPolicy();
124 EXPECT_FALSE(manager_
->enforce_memory_policy_pending());
126 // Memory should still be resident.
127 EXPECT_TRUE(memory1
.IsMemoryResident());
128 EXPECT_TRUE(memory2
.IsMemoryResident());
130 auto lock_rv
= memory1
.Lock(0, 0);
131 EXPECT_EQ(base::DiscardableSharedMemory::SUCCESS
, lock_rv
);
132 lock_rv
= memory2
.Lock(0, 0);
133 EXPECT_EQ(base::DiscardableSharedMemory::SUCCESS
, lock_rv
);
135 memory1
.SetNow(base::Time::FromDoubleT(4));
136 memory1
.Unlock(0, 0);
137 memory2
.SetNow(base::Time::FromDoubleT(5));
138 memory2
.Unlock(0, 0);
140 // Just enough memory for one allocation.
141 manager_
->SetNow(base::Time::FromDoubleT(6));
142 manager_
->SetMemoryLimit(memory2
.mapped_size());
143 EXPECT_FALSE(manager_
->enforce_memory_policy_pending());
145 // LRU allocation should still be resident.
146 EXPECT_FALSE(memory1
.IsMemoryResident());
147 EXPECT_TRUE(memory2
.IsMemoryResident());
149 lock_rv
= memory1
.Lock(0, 0);
150 EXPECT_EQ(base::DiscardableSharedMemory::FAILED
, lock_rv
);
151 lock_rv
= memory2
.Lock(0, 0);
152 EXPECT_EQ(base::DiscardableSharedMemory::SUCCESS
, lock_rv
);
155 TEST_F(HostDiscardableSharedMemoryManagerTest
, EnforceMemoryPolicy
) {
156 const int kDataSize
= 1024;
158 base::SharedMemoryHandle shared_handle
;
159 manager_
->AllocateLockedDiscardableSharedMemoryForChild(
160 base::GetCurrentProcessHandle(), ChildProcessHost::kInvalidUniqueID
,
161 kDataSize
, 0, &shared_handle
);
162 ASSERT_TRUE(base::SharedMemory::IsHandleValid(shared_handle
));
164 TestDiscardableSharedMemory
memory(shared_handle
);
165 bool rv
= memory
.Map(kDataSize
);
168 // Not enough memory for one allocation.
169 manager_
->SetNow(base::Time::FromDoubleT(1));
170 manager_
->SetMemoryLimit(memory
.mapped_size() - 1);
171 // We need to enforce memory policy as our memory usage is currently above
173 EXPECT_TRUE(manager_
->enforce_memory_policy_pending());
175 manager_
->set_enforce_memory_policy_pending(false);
176 manager_
->SetNow(base::Time::FromDoubleT(2));
177 manager_
->EnforceMemoryPolicy();
178 // Still need to enforce memory policy as nothing can be purged.
179 EXPECT_TRUE(manager_
->enforce_memory_policy_pending());
181 memory
.SetNow(base::Time::FromDoubleT(3));
184 manager_
->set_enforce_memory_policy_pending(false);
185 manager_
->SetNow(base::Time::FromDoubleT(4));
186 manager_
->EnforceMemoryPolicy();
187 // Memory policy should have successfully been enforced.
188 EXPECT_FALSE(manager_
->enforce_memory_policy_pending());
190 EXPECT_EQ(base::DiscardableSharedMemory::FAILED
, memory
.Lock(0, 0));
194 } // namespace content