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 "base/basictypes.h"
6 #include "base/memory/discardable_shared_memory.h"
7 #include "testing/gtest/include/gtest/gtest.h"
12 class TestDiscardableSharedMemory
: public DiscardableSharedMemory
{
14 TestDiscardableSharedMemory() {}
16 explicit TestDiscardableSharedMemory(SharedMemoryHandle handle
)
17 : DiscardableSharedMemory(handle
) {}
19 void SetNow(Time now
) { now_
= now
; }
22 // Overriden from DiscardableSharedMemory:
23 virtual Time
Now() const override
{ return now_
; }
28 TEST(DiscardableSharedMemoryTest
, CreateAndMap
) {
29 const uint32 kDataSize
= 1024;
31 TestDiscardableSharedMemory memory
;
32 bool rv
= memory
.CreateAndMap(kDataSize
);
34 EXPECT_GE(memory
.mapped_size(), kDataSize
);
37 TEST(DiscardableSharedMemoryTest
, CreateFromHandle
) {
38 const uint32 kDataSize
= 1024;
40 TestDiscardableSharedMemory memory1
;
41 bool rv
= memory1
.CreateAndMap(kDataSize
);
44 SharedMemoryHandle shared_handle
;
46 memory1
.ShareToProcess(GetCurrentProcessHandle(), &shared_handle
));
47 ASSERT_TRUE(SharedMemory::IsHandleValid(shared_handle
));
49 TestDiscardableSharedMemory
memory2(shared_handle
);
50 rv
= memory2
.Map(kDataSize
);
54 TEST(DiscardableSharedMemoryTest
, LockAndUnlock
) {
55 const uint32 kDataSize
= 1024;
57 TestDiscardableSharedMemory memory1
;
58 bool rv
= memory1
.CreateAndMap(kDataSize
);
61 // Memory is initially locked. Unlock it.
62 memory1
.SetNow(Time::FromDoubleT(1));
65 // Lock and unlock memory.
68 memory1
.SetNow(Time::FromDoubleT(2));
71 SharedMemoryHandle shared_handle
;
73 memory1
.ShareToProcess(GetCurrentProcessHandle(), &shared_handle
));
74 ASSERT_TRUE(SharedMemory::IsHandleValid(shared_handle
));
76 TestDiscardableSharedMemory
memory2(shared_handle
);
77 rv
= memory2
.Map(kDataSize
);
80 // Lock first instance again.
84 // Unlock second instance.
85 memory2
.SetNow(Time::FromDoubleT(3));
88 // Lock and unlock second instance.
91 memory2
.SetNow(Time::FromDoubleT(4));
94 // Try to lock first instance again. Should fail as first instance has an
95 // incorrect last know usage time.
99 // Memory should still be resident.
100 rv
= memory1
.IsMemoryResident();
103 // Second attempt to lock first instance should succeed as last known usage
104 // time is now correct.
107 memory1
.SetNow(Time::FromDoubleT(5));
111 TEST(DiscardableSharedMemoryTest
, Purge
) {
112 const uint32 kDataSize
= 1024;
114 TestDiscardableSharedMemory memory1
;
115 bool rv
= memory1
.CreateAndMap(kDataSize
);
118 SharedMemoryHandle shared_handle
;
120 memory1
.ShareToProcess(GetCurrentProcessHandle(), &shared_handle
));
121 ASSERT_TRUE(SharedMemory::IsHandleValid(shared_handle
));
123 TestDiscardableSharedMemory
memory2(shared_handle
);
124 rv
= memory2
.Map(kDataSize
);
127 // This should fail as memory is locked.
128 rv
= memory1
.Purge(Time::FromDoubleT(1));
131 memory2
.SetNow(Time::FromDoubleT(2));
134 ASSERT_TRUE(memory2
.IsMemoryResident());
136 // Memory is unlocked, but our usage timestamp is incorrect.
137 rv
= memory1
.Purge(Time::FromDoubleT(3));
140 ASSERT_TRUE(memory2
.IsMemoryResident());
142 // Memory is unlocked and our usage timestamp should be correct.
143 rv
= memory1
.Purge(Time::FromDoubleT(4));
146 // Lock should fail as memory has been purged.
150 ASSERT_FALSE(memory2
.IsMemoryResident());
153 TEST(DiscardableSharedMemoryTest
, LastUsed
) {
154 const uint32 kDataSize
= 1024;
156 TestDiscardableSharedMemory memory1
;
157 bool rv
= memory1
.CreateAndMap(kDataSize
);
160 SharedMemoryHandle shared_handle
;
162 memory1
.ShareToProcess(GetCurrentProcessHandle(), &shared_handle
));
163 ASSERT_TRUE(SharedMemory::IsHandleValid(shared_handle
));
165 TestDiscardableSharedMemory
memory2(shared_handle
);
166 rv
= memory2
.Map(kDataSize
);
169 memory2
.SetNow(Time::FromDoubleT(1));
172 EXPECT_EQ(memory2
.last_known_usage(), Time::FromDoubleT(1));
177 // This should fail as memory is locked.
178 rv
= memory1
.Purge(Time::FromDoubleT(2));
181 // Last usage should have been updated to timestamp passed to Purge above.
182 EXPECT_EQ(memory1
.last_known_usage(), Time::FromDoubleT(2));
184 memory2
.SetNow(Time::FromDoubleT(3));
187 // Usage time should be correct for |memory2| instance.
188 EXPECT_EQ(memory2
.last_known_usage(), Time::FromDoubleT(3));
190 // However, usage time has not changed as far as |memory1| instance knows.
191 EXPECT_EQ(memory1
.last_known_usage(), Time::FromDoubleT(2));
193 // Memory is unlocked, but our usage timestamp is incorrect.
194 rv
= memory1
.Purge(Time::FromDoubleT(4));
197 // The failed purge attempt should have updated usage time to the correct
199 EXPECT_EQ(memory1
.last_known_usage(), Time::FromDoubleT(3));
201 // Purge memory through |memory2| instance. The last usage time should be
202 // set to 0 as a result of this.
203 rv
= memory2
.Purge(Time::FromDoubleT(5));
205 EXPECT_TRUE(memory2
.last_known_usage().is_null());
207 // This should fail as memory has already been purged and |memory1|'s usage
208 // time is incorrect as a result.
209 rv
= memory1
.Purge(Time::FromDoubleT(6));
212 // The failed purge attempt should have updated usage time to the correct
214 EXPECT_TRUE(memory1
.last_known_usage().is_null());
216 // Purge should succeed now that usage time is correct.
217 rv
= memory1
.Purge(Time::FromDoubleT(7));
221 TEST(DiscardableSharedMemoryTest
, LockShouldAlwaysFailAfterSuccessfulPurge
) {
222 const uint32 kDataSize
= 1024;
224 TestDiscardableSharedMemory memory1
;
225 bool rv
= memory1
.CreateAndMap(kDataSize
);
228 SharedMemoryHandle shared_handle
;
230 memory1
.ShareToProcess(GetCurrentProcessHandle(), &shared_handle
));
231 ASSERT_TRUE(SharedMemory::IsHandleValid(shared_handle
));
233 TestDiscardableSharedMemory
memory2(shared_handle
);
234 rv
= memory2
.Map(kDataSize
);
237 memory2
.SetNow(Time::FromDoubleT(1));
240 rv
= memory2
.Purge(Time::FromDoubleT(2));
243 // Lock should fail as memory has been purged.