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.