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"
6 #include "testing/gtest/include/gtest/gtest.h"
11 class TestDiscardableSharedMemory
: public base::DiscardableSharedMemory
{
13 TestDiscardableSharedMemory() {}
15 explicit TestDiscardableSharedMemory(base::SharedMemoryHandle handle
)
16 : DiscardableSharedMemory(handle
) {}
18 void SetNow(base::Time now
) { now_
= now
; }
21 // Overriden from base::DiscardableSharedMemory:
22 base::Time
Now() const override
{ return now_
; }
27 class TestHostDiscardableSharedMemoryManager
28 : public HostDiscardableSharedMemoryManager
{
30 TestHostDiscardableSharedMemoryManager()
31 : enforce_memory_policy_pending_(false) {}
33 void SetNow(base::Time now
) { now_
= now
; }
35 void set_enforce_memory_policy_pending(bool enforce_memory_policy_pending
) {
36 enforce_memory_policy_pending_
= enforce_memory_policy_pending
;
38 bool enforce_memory_policy_pending() const {
39 return enforce_memory_policy_pending_
;
43 // Overriden from HostDiscardableSharedMemoryManager:
44 base::Time
Now() const override
{ return now_
; }
45 void ScheduleEnforceMemoryPolicy() override
{
46 enforce_memory_policy_pending_
= true;
50 bool enforce_memory_policy_pending_
;
53 class HostDiscardableSharedMemoryManagerTest
: public testing::Test
{
55 // Overridden from testing::Test:
56 void SetUp() override
{
57 manager_
.reset(new TestHostDiscardableSharedMemoryManager
);
60 scoped_ptr
<TestHostDiscardableSharedMemoryManager
> manager_
;
63 TEST_F(HostDiscardableSharedMemoryManagerTest
, AllocateForChild
) {
64 const int kDataSize
= 1024;
65 uint8 data
[kDataSize
];
66 memset(data
, 0x80, kDataSize
);
68 base::SharedMemoryHandle shared_handle
;
69 manager_
->AllocateLockedDiscardableSharedMemoryForChild(
70 base::GetCurrentProcessHandle(), kDataSize
, 0, &shared_handle
);
71 ASSERT_TRUE(base::SharedMemory::IsHandleValid(shared_handle
));
73 TestDiscardableSharedMemory
memory(shared_handle
);
74 bool rv
= memory
.Map(kDataSize
);
77 memcpy(memory
.memory(), data
, kDataSize
);
78 memory
.SetNow(base::Time::FromDoubleT(1));
81 ASSERT_EQ(base::DiscardableSharedMemory::SUCCESS
, memory
.Lock(0, 0));
82 EXPECT_EQ(memcmp(data
, memory
.memory(), kDataSize
), 0);
86 TEST_F(HostDiscardableSharedMemoryManagerTest
, Purge
) {
87 const int kDataSize
= 1024;
89 base::SharedMemoryHandle shared_handle1
;
90 manager_
->AllocateLockedDiscardableSharedMemoryForChild(
91 base::GetCurrentProcessHandle(), kDataSize
, 1, &shared_handle1
);
92 ASSERT_TRUE(base::SharedMemory::IsHandleValid(shared_handle1
));
94 TestDiscardableSharedMemory
memory1(shared_handle1
);
95 bool rv
= memory1
.Map(kDataSize
);
98 base::SharedMemoryHandle shared_handle2
;
99 manager_
->AllocateLockedDiscardableSharedMemoryForChild(
100 base::GetCurrentProcessHandle(), kDataSize
, 2, &shared_handle2
);
101 ASSERT_TRUE(base::SharedMemory::IsHandleValid(shared_handle2
));
103 TestDiscardableSharedMemory
memory2(shared_handle2
);
104 rv
= memory2
.Map(kDataSize
);
107 // Enough memory for both allocations.
108 manager_
->SetNow(base::Time::FromDoubleT(1));
109 manager_
->SetMemoryLimit(memory1
.mapped_size() + memory2
.mapped_size());
111 memory1
.SetNow(base::Time::FromDoubleT(2));
112 memory1
.Unlock(0, 0);
113 memory2
.SetNow(base::Time::FromDoubleT(2));
114 memory2
.Unlock(0, 0);
116 // Manager should not have to schedule another call to EnforceMemoryPolicy().
117 manager_
->SetNow(base::Time::FromDoubleT(3));
118 manager_
->EnforceMemoryPolicy();
119 EXPECT_FALSE(manager_
->enforce_memory_policy_pending());
121 // Memory should still be resident.
122 EXPECT_TRUE(memory1
.IsMemoryResident());
123 EXPECT_TRUE(memory2
.IsMemoryResident());
125 auto lock_rv
= memory1
.Lock(0, 0);
126 EXPECT_EQ(base::DiscardableSharedMemory::SUCCESS
, lock_rv
);
127 lock_rv
= memory2
.Lock(0, 0);
128 EXPECT_EQ(base::DiscardableSharedMemory::SUCCESS
, lock_rv
);
130 memory1
.SetNow(base::Time::FromDoubleT(4));
131 memory1
.Unlock(0, 0);
132 memory2
.SetNow(base::Time::FromDoubleT(5));
133 memory2
.Unlock(0, 0);
135 // Just enough memory for one allocation.
136 manager_
->SetNow(base::Time::FromDoubleT(6));
137 manager_
->SetMemoryLimit(memory2
.mapped_size());
138 EXPECT_FALSE(manager_
->enforce_memory_policy_pending());
140 // LRU allocation should still be resident.
141 EXPECT_FALSE(memory1
.IsMemoryResident());
142 EXPECT_TRUE(memory2
.IsMemoryResident());
144 lock_rv
= memory1
.Lock(0, 0);
145 EXPECT_EQ(base::DiscardableSharedMemory::FAILED
, lock_rv
);
146 lock_rv
= memory2
.Lock(0, 0);
147 EXPECT_EQ(base::DiscardableSharedMemory::SUCCESS
, lock_rv
);
150 TEST_F(HostDiscardableSharedMemoryManagerTest
, EnforceMemoryPolicy
) {
151 const int kDataSize
= 1024;
153 base::SharedMemoryHandle shared_handle
;
154 manager_
->AllocateLockedDiscardableSharedMemoryForChild(
155 base::GetCurrentProcessHandle(), kDataSize
, 0, &shared_handle
);
156 ASSERT_TRUE(base::SharedMemory::IsHandleValid(shared_handle
));
158 TestDiscardableSharedMemory
memory(shared_handle
);
159 bool rv
= memory
.Map(kDataSize
);
162 // Not enough memory for one allocation.
163 manager_
->SetNow(base::Time::FromDoubleT(1));
164 manager_
->SetMemoryLimit(memory
.mapped_size() - 1);
165 // We need to enforce memory policy as our memory usage is currently above
167 EXPECT_TRUE(manager_
->enforce_memory_policy_pending());
169 manager_
->set_enforce_memory_policy_pending(false);
170 manager_
->SetNow(base::Time::FromDoubleT(2));
171 manager_
->EnforceMemoryPolicy();
172 // Still need to enforce memory policy as nothing can be purged.
173 EXPECT_TRUE(manager_
->enforce_memory_policy_pending());
175 memory
.SetNow(base::Time::FromDoubleT(3));
178 manager_
->set_enforce_memory_policy_pending(false);
179 manager_
->SetNow(base::Time::FromDoubleT(4));
180 manager_
->EnforceMemoryPolicy();
181 // Memory policy should have successfully been enforced.
182 EXPECT_FALSE(manager_
->enforce_memory_policy_pending());
184 EXPECT_EQ(base::DiscardableSharedMemory::FAILED
, memory
.Lock(0, 0));
188 } // namespace content