| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 |
| 5 #include "base/metrics/persistent_memory_allocator.h" | 5 #include "base/metrics/persistent_memory_allocator.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 | 8 |
| 9 #include "base/files/file.h" | 9 #include "base/files/file.h" |
| 10 #include "base/files/file_util.h" | 10 #include "base/files/file_util.h" |
| (...skipping 22 matching lines...) Expand all Loading... |
| 33 typedef PersistentMemoryAllocator::Reference Reference; | 33 typedef PersistentMemoryAllocator::Reference Reference; |
| 34 | 34 |
| 35 class PersistentMemoryAllocatorTest : public testing::Test { | 35 class PersistentMemoryAllocatorTest : public testing::Test { |
| 36 public: | 36 public: |
| 37 // This can't be statically initialized because it's value isn't defined | 37 // This can't be statically initialized because it's value isn't defined |
| 38 // in the PersistentMemoryAllocator header file. Instead, it's simply set | 38 // in the PersistentMemoryAllocator header file. Instead, it's simply set |
| 39 // in the constructor. | 39 // in the constructor. |
| 40 uint32_t kAllocAlignment; | 40 uint32_t kAllocAlignment; |
| 41 | 41 |
| 42 struct TestObject1 { | 42 struct TestObject1 { |
| 43 static constexpr uint32_t kPersistentTypeId = 1; |
| 43 static constexpr size_t kExpectedInstanceSize = 4 + 1 + 3; | 44 static constexpr size_t kExpectedInstanceSize = 4 + 1 + 3; |
| 44 int32_t onething; | 45 int32_t onething; |
| 45 char oranother; | 46 char oranother; |
| 46 }; | 47 }; |
| 47 | 48 |
| 48 struct TestObject2 { | 49 struct TestObject2 { |
| 50 static constexpr uint32_t kPersistentTypeId = 2; |
| 49 static constexpr size_t kExpectedInstanceSize = 8 + 4 + 4 + 8 + 8; | 51 static constexpr size_t kExpectedInstanceSize = 8 + 4 + 4 + 8 + 8; |
| 50 int64_t thiis; | 52 int64_t thiis; |
| 51 int32_t that; | 53 int32_t that; |
| 52 float andthe; | 54 float andthe; |
| 53 double other; | 55 double other; |
| 54 char thing[8]; | 56 char thing[8]; |
| 55 }; | 57 }; |
| 56 | 58 |
| 57 PersistentMemoryAllocatorTest() { | 59 PersistentMemoryAllocatorTest() { |
| 58 kAllocAlignment = GetAllocAlignment(); | 60 kAllocAlignment = GetAllocAlignment(); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 102 allocator_->allocs_histogram_->histogram_name()); | 104 allocator_->allocs_histogram_->histogram_name()); |
| 103 | 105 |
| 104 // Get base memory info for later comparison. | 106 // Get base memory info for later comparison. |
| 105 PersistentMemoryAllocator::MemoryInfo meminfo0; | 107 PersistentMemoryAllocator::MemoryInfo meminfo0; |
| 106 allocator_->GetMemoryInfo(&meminfo0); | 108 allocator_->GetMemoryInfo(&meminfo0); |
| 107 EXPECT_EQ(TEST_MEMORY_SIZE, meminfo0.total); | 109 EXPECT_EQ(TEST_MEMORY_SIZE, meminfo0.total); |
| 108 EXPECT_GT(meminfo0.total, meminfo0.free); | 110 EXPECT_GT(meminfo0.total, meminfo0.free); |
| 109 | 111 |
| 110 // Validate allocation of test object and make sure it can be referenced | 112 // Validate allocation of test object and make sure it can be referenced |
| 111 // and all metadata looks correct. | 113 // and all metadata looks correct. |
| 112 Reference block1 = allocator_->Allocate(sizeof(TestObject1), 1); | 114 TestObject1* obj1 = allocator_->AllocateObject<TestObject1>(); |
| 113 EXPECT_NE(0U, block1); | 115 ASSERT_TRUE(obj1); |
| 114 EXPECT_NE(nullptr, allocator_->GetAsObject<TestObject1>(block1, 1)); | 116 Reference block1 = allocator_->GetAsReference(obj1); |
| 115 EXPECT_EQ(nullptr, allocator_->GetAsObject<TestObject2>(block1, 1)); | 117 ASSERT_NE(0U, block1); |
| 118 EXPECT_NE(nullptr, allocator_->GetAsObject<TestObject1>(block1)); |
| 119 EXPECT_EQ(nullptr, allocator_->GetAsObject<TestObject2>(block1)); |
| 116 EXPECT_LE(sizeof(TestObject1), allocator_->GetAllocSize(block1)); | 120 EXPECT_LE(sizeof(TestObject1), allocator_->GetAllocSize(block1)); |
| 117 EXPECT_GT(sizeof(TestObject1) + kAllocAlignment, | 121 EXPECT_GT(sizeof(TestObject1) + kAllocAlignment, |
| 118 allocator_->GetAllocSize(block1)); | 122 allocator_->GetAllocSize(block1)); |
| 119 PersistentMemoryAllocator::MemoryInfo meminfo1; | 123 PersistentMemoryAllocator::MemoryInfo meminfo1; |
| 120 allocator_->GetMemoryInfo(&meminfo1); | 124 allocator_->GetMemoryInfo(&meminfo1); |
| 121 EXPECT_EQ(meminfo0.total, meminfo1.total); | 125 EXPECT_EQ(meminfo0.total, meminfo1.total); |
| 122 EXPECT_GT(meminfo0.free, meminfo1.free); | 126 EXPECT_GT(meminfo0.free, meminfo1.free); |
| 123 | 127 |
| 124 // Verify that pointers can be turned back into references and that invalid | 128 // Verify that pointers can be turned back into references and that invalid |
| 125 // addresses return null. | 129 // addresses return null. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 140 EXPECT_EQ(0U, iter1a.GetNext(&type)); | 144 EXPECT_EQ(0U, iter1a.GetNext(&type)); |
| 141 allocator_->MakeIterable(block1); | 145 allocator_->MakeIterable(block1); |
| 142 EXPECT_EQ(block1, iter1a.GetNext(&type)); | 146 EXPECT_EQ(block1, iter1a.GetNext(&type)); |
| 143 EXPECT_EQ(1U, type); | 147 EXPECT_EQ(1U, type); |
| 144 EXPECT_EQ(block1, iter1a.GetLast()); | 148 EXPECT_EQ(block1, iter1a.GetLast()); |
| 145 EXPECT_EQ(0U, iter1a.GetNext(&type)); | 149 EXPECT_EQ(0U, iter1a.GetNext(&type)); |
| 146 EXPECT_EQ(block1, iter1a.GetLast()); | 150 EXPECT_EQ(block1, iter1a.GetLast()); |
| 147 | 151 |
| 148 // Create second test-object and ensure everything is good and it cannot | 152 // Create second test-object and ensure everything is good and it cannot |
| 149 // be confused with test-object of another type. | 153 // be confused with test-object of another type. |
| 150 Reference block2 = allocator_->Allocate(sizeof(TestObject2), 2); | 154 TestObject2* obj2 = allocator_->AllocateObject<TestObject2>(); |
| 151 EXPECT_NE(0U, block2); | 155 ASSERT_TRUE(obj2); |
| 152 EXPECT_NE(nullptr, allocator_->GetAsObject<TestObject2>(block2, 2)); | 156 Reference block2 = allocator_->GetAsReference(obj2); |
| 153 EXPECT_EQ(nullptr, allocator_->GetAsObject<TestObject2>(block2, 1)); | 157 ASSERT_NE(0U, block2); |
| 158 EXPECT_NE(nullptr, allocator_->GetAsObject<TestObject2>(block2)); |
| 159 EXPECT_EQ(nullptr, allocator_->GetAsObject<TestObject1>(block2)); |
| 154 EXPECT_LE(sizeof(TestObject2), allocator_->GetAllocSize(block2)); | 160 EXPECT_LE(sizeof(TestObject2), allocator_->GetAllocSize(block2)); |
| 155 EXPECT_GT(sizeof(TestObject2) + kAllocAlignment, | 161 EXPECT_GT(sizeof(TestObject2) + kAllocAlignment, |
| 156 allocator_->GetAllocSize(block2)); | 162 allocator_->GetAllocSize(block2)); |
| 157 PersistentMemoryAllocator::MemoryInfo meminfo2; | 163 PersistentMemoryAllocator::MemoryInfo meminfo2; |
| 158 allocator_->GetMemoryInfo(&meminfo2); | 164 allocator_->GetMemoryInfo(&meminfo2); |
| 159 EXPECT_EQ(meminfo1.total, meminfo2.total); | 165 EXPECT_EQ(meminfo1.total, meminfo2.total); |
| 160 EXPECT_GT(meminfo1.free, meminfo2.free); | 166 EXPECT_GT(meminfo1.free, meminfo2.free); |
| 161 | 167 |
| 162 // Ensure that second test-object can also be made iterable. | 168 // Ensure that second test-object can also be made iterable. |
| 163 allocator_->MakeIterable(block2); | 169 allocator_->MakeIterable(obj2); |
| 164 EXPECT_EQ(block2, iter1a.GetNext(&type)); | 170 EXPECT_EQ(block2, iter1a.GetNext(&type)); |
| 165 EXPECT_EQ(2U, type); | 171 EXPECT_EQ(2U, type); |
| 166 EXPECT_EQ(block2, iter1a.GetLast()); | 172 EXPECT_EQ(block2, iter1a.GetLast()); |
| 167 EXPECT_EQ(0U, iter1a.GetNext(&type)); | 173 EXPECT_EQ(0U, iter1a.GetNext(&type)); |
| 168 EXPECT_EQ(block2, iter1a.GetLast()); | 174 EXPECT_EQ(block2, iter1a.GetLast()); |
| 169 | 175 |
| 170 // Check that the iterator can be reset to the beginning. | 176 // Check that the iterator can be reset to the beginning. |
| 171 iter1a.Reset(); | 177 iter1a.Reset(); |
| 172 EXPECT_EQ(0U, iter1a.GetLast()); | 178 EXPECT_EQ(0U, iter1a.GetLast()); |
| 173 EXPECT_EQ(block1, iter1a.GetNext(&type)); | 179 EXPECT_EQ(block1, iter1a.GetNext(&type)); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 207 EXPECT_EQ(0, allocs_samples->GetCount(0)); | 213 EXPECT_EQ(0, allocs_samples->GetCount(0)); |
| 208 EXPECT_EQ(1, allocs_samples->GetCount(sizeof(TestObject1))); | 214 EXPECT_EQ(1, allocs_samples->GetCount(sizeof(TestObject1))); |
| 209 EXPECT_EQ(1, allocs_samples->GetCount(sizeof(TestObject2))); | 215 EXPECT_EQ(1, allocs_samples->GetCount(sizeof(TestObject2))); |
| 210 #if !DCHECK_IS_ON() // DCHECK builds will die at a NOTREACHED(). | 216 #if !DCHECK_IS_ON() // DCHECK builds will die at a NOTREACHED(). |
| 211 EXPECT_EQ(0U, allocator_->Allocate(TEST_MEMORY_SIZE + 1, 0)); | 217 EXPECT_EQ(0U, allocator_->Allocate(TEST_MEMORY_SIZE + 1, 0)); |
| 212 allocs_samples = allocator_->allocs_histogram_->SnapshotSamples(); | 218 allocs_samples = allocator_->allocs_histogram_->SnapshotSamples(); |
| 213 EXPECT_EQ(3, allocs_samples->TotalCount()); | 219 EXPECT_EQ(3, allocs_samples->TotalCount()); |
| 214 EXPECT_EQ(1, allocs_samples->GetCount(0)); | 220 EXPECT_EQ(1, allocs_samples->GetCount(0)); |
| 215 #endif | 221 #endif |
| 216 | 222 |
| 217 // Check that an objcet's type can be changed. | 223 // Check that an object's type can be changed. |
| 218 EXPECT_EQ(2U, allocator_->GetType(block2)); | 224 EXPECT_EQ(2U, allocator_->GetType(block2)); |
| 219 allocator_->ChangeType(block2, 3, 2); | 225 allocator_->ChangeType(block2, 3, 2); |
| 220 EXPECT_EQ(3U, allocator_->GetType(block2)); | 226 EXPECT_EQ(3U, allocator_->GetType(block2)); |
| 221 allocator_->ChangeType(block2, 2, 3); | 227 allocator_->ChangeObject<TestObject2>(block2, 3); |
| 222 EXPECT_EQ(2U, allocator_->GetType(block2)); | 228 EXPECT_EQ(2U, allocator_->GetType(block2)); |
| 223 | 229 |
| 224 // Create second allocator (read/write) using the same memory segment. | 230 // Create second allocator (read/write) using the same memory segment. |
| 225 std::unique_ptr<PersistentMemoryAllocator> allocator2( | 231 std::unique_ptr<PersistentMemoryAllocator> allocator2( |
| 226 new PersistentMemoryAllocator(mem_segment_.get(), TEST_MEMORY_SIZE, | 232 new PersistentMemoryAllocator(mem_segment_.get(), TEST_MEMORY_SIZE, |
| 227 TEST_MEMORY_PAGE, 0, "", false)); | 233 TEST_MEMORY_PAGE, 0, "", false)); |
| 228 EXPECT_EQ(TEST_ID, allocator2->Id()); | 234 EXPECT_EQ(TEST_ID, allocator2->Id()); |
| 229 EXPECT_FALSE(allocator2->used_histogram_); | 235 EXPECT_FALSE(allocator2->used_histogram_); |
| 230 EXPECT_FALSE(allocator2->allocs_histogram_); | 236 EXPECT_FALSE(allocator2->allocs_histogram_); |
| 231 EXPECT_NE(allocator2->allocs_histogram_, allocator_->allocs_histogram_); | 237 EXPECT_NE(allocator2->allocs_histogram_, allocator_->allocs_histogram_); |
| 232 | 238 |
| 233 // Ensure that iteration and access through second allocator works. | 239 // Ensure that iteration and access through second allocator works. |
| 234 PersistentMemoryAllocator::Iterator iter2(allocator2.get()); | 240 PersistentMemoryAllocator::Iterator iter2(allocator2.get()); |
| 235 EXPECT_EQ(block1, iter2.GetNext(&type)); | 241 EXPECT_EQ(block1, iter2.GetNext(&type)); |
| 236 EXPECT_EQ(block2, iter2.GetNext(&type)); | 242 EXPECT_EQ(block2, iter2.GetNext(&type)); |
| 237 EXPECT_EQ(0U, iter2.GetNext(&type)); | 243 EXPECT_EQ(0U, iter2.GetNext(&type)); |
| 238 EXPECT_NE(nullptr, allocator2->GetAsObject<TestObject1>(block1, 1)); | 244 EXPECT_NE(nullptr, allocator2->GetAsObject<TestObject1>(block1)); |
| 239 EXPECT_NE(nullptr, allocator2->GetAsObject<TestObject2>(block2, 2)); | 245 EXPECT_NE(nullptr, allocator2->GetAsObject<TestObject2>(block2)); |
| 240 | 246 |
| 241 // Create a third allocator (read-only) using the same memory segment. | 247 // Create a third allocator (read-only) using the same memory segment. |
| 242 std::unique_ptr<const PersistentMemoryAllocator> allocator3( | 248 std::unique_ptr<const PersistentMemoryAllocator> allocator3( |
| 243 new PersistentMemoryAllocator(mem_segment_.get(), TEST_MEMORY_SIZE, | 249 new PersistentMemoryAllocator(mem_segment_.get(), TEST_MEMORY_SIZE, |
| 244 TEST_MEMORY_PAGE, 0, "", true)); | 250 TEST_MEMORY_PAGE, 0, "", true)); |
| 245 EXPECT_EQ(TEST_ID, allocator3->Id()); | 251 EXPECT_EQ(TEST_ID, allocator3->Id()); |
| 246 EXPECT_FALSE(allocator3->used_histogram_); | 252 EXPECT_FALSE(allocator3->used_histogram_); |
| 247 EXPECT_FALSE(allocator3->allocs_histogram_); | 253 EXPECT_FALSE(allocator3->allocs_histogram_); |
| 248 | 254 |
| 249 // Ensure that iteration and access through third allocator works. | 255 // Ensure that iteration and access through third allocator works. |
| 250 PersistentMemoryAllocator::Iterator iter3(allocator3.get()); | 256 PersistentMemoryAllocator::Iterator iter3(allocator3.get()); |
| 251 EXPECT_EQ(block1, iter3.GetNext(&type)); | 257 EXPECT_EQ(block1, iter3.GetNext(&type)); |
| 252 EXPECT_EQ(block2, iter3.GetNext(&type)); | 258 EXPECT_EQ(block2, iter3.GetNext(&type)); |
| 253 EXPECT_EQ(0U, iter3.GetNext(&type)); | 259 EXPECT_EQ(0U, iter3.GetNext(&type)); |
| 254 EXPECT_NE(nullptr, allocator3->GetAsObject<TestObject1>(block1, 1)); | 260 EXPECT_NE(nullptr, allocator3->GetAsObject<TestObject1>(block1)); |
| 255 EXPECT_NE(nullptr, allocator3->GetAsObject<TestObject2>(block2, 2)); | 261 EXPECT_NE(nullptr, allocator3->GetAsObject<TestObject2>(block2)); |
| 256 | 262 |
| 257 // Ensure that GetNextOfType works. | 263 // Ensure that GetNextOfType works. |
| 258 PersistentMemoryAllocator::Iterator iter1c(allocator_.get()); | 264 PersistentMemoryAllocator::Iterator iter1c(allocator_.get()); |
| 259 EXPECT_EQ(block2, iter1c.GetNextOfType(2)); | 265 EXPECT_EQ(block2, iter1c.GetNextOfType<TestObject2>()); |
| 260 EXPECT_EQ(0U, iter1c.GetNextOfType(2)); | 266 EXPECT_EQ(0U, iter1c.GetNextOfType(2)); |
| 267 |
| 268 // Ensure that GetNextOfObject works. |
| 269 PersistentMemoryAllocator::Iterator iter1d(allocator_.get()); |
| 270 EXPECT_EQ(obj2, iter1d.GetNextOfObject<TestObject2>()); |
| 271 EXPECT_EQ(nullptr, iter1d.GetNextOfObject<TestObject2>()); |
| 272 |
| 273 // Ensure that deleting an object works. |
| 274 allocator_->DeleteObject(obj2); |
| 275 PersistentMemoryAllocator::Iterator iter1z(allocator_.get()); |
| 276 EXPECT_EQ(nullptr, iter1z.GetNextOfObject<TestObject2>()); |
| 261 } | 277 } |
| 262 | 278 |
| 263 TEST_F(PersistentMemoryAllocatorTest, PageTest) { | 279 TEST_F(PersistentMemoryAllocatorTest, PageTest) { |
| 264 // This allocation will go into the first memory page. | 280 // This allocation will go into the first memory page. |
| 265 Reference block1 = allocator_->Allocate(TEST_MEMORY_PAGE / 2, 1); | 281 Reference block1 = allocator_->Allocate(TEST_MEMORY_PAGE / 2, 1); |
| 266 EXPECT_LT(0U, block1); | 282 EXPECT_LT(0U, block1); |
| 267 EXPECT_GT(TEST_MEMORY_PAGE, block1); | 283 EXPECT_GT(TEST_MEMORY_PAGE, block1); |
| 268 | 284 |
| 269 // This allocation won't fit in same page as previous block. | 285 // This allocation won't fit in same page as previous block. |
| 270 Reference block2 = | 286 Reference block2 = |
| (...skipping 571 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 842 // For filesize >= minsize, the file must be acceptable. This | 858 // For filesize >= minsize, the file must be acceptable. This |
| 843 // else clause (file-not-acceptable) should be reached only if | 859 // else clause (file-not-acceptable) should be reached only if |
| 844 // filesize < minsize. | 860 // filesize < minsize. |
| 845 EXPECT_GT(minsize, filesize); | 861 EXPECT_GT(minsize, filesize); |
| 846 } | 862 } |
| 847 } | 863 } |
| 848 } | 864 } |
| 849 #endif // !defined(OS_NACL) | 865 #endif // !defined(OS_NACL) |
| 850 | 866 |
| 851 } // namespace base | 867 } // namespace base |
| OLD | NEW |