Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(697)

Side by Side Diff: base/metrics/persistent_memory_allocator_unittest.cc

Issue 1803253002: Improved iterator for persistent memory allocator. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@refactor-hp
Patch Set: rebased Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/metrics/persistent_memory_allocator.cc ('k') | base/metrics/persistent_sample_map.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
11 #include "base/files/memory_mapped_file.h" 11 #include "base/files/memory_mapped_file.h"
12 #include "base/files/scoped_temp_dir.h" 12 #include "base/files/scoped_temp_dir.h"
13 #include "base/memory/shared_memory.h" 13 #include "base/memory/shared_memory.h"
14 #include "base/metrics/histogram.h" 14 #include "base/metrics/histogram.h"
15 #include "base/rand_util.h" 15 #include "base/rand_util.h"
16 #include "base/strings/safe_sprintf.h" 16 #include "base/strings/safe_sprintf.h"
17 #include "base/synchronization/condition_variable.h"
18 #include "base/synchronization/lock.h"
17 #include "base/threading/simple_thread.h" 19 #include "base/threading/simple_thread.h"
18 #include "testing/gmock/include/gmock/gmock.h" 20 #include "testing/gmock/include/gmock/gmock.h"
19 21
20 namespace { 22 namespace {
21 23
22 const uint32_t TEST_MEMORY_SIZE = 1 << 20; // 1 MiB 24 const uint32_t TEST_MEMORY_SIZE = 1 << 20; // 1 MiB
23 const uint32_t TEST_MEMORY_PAGE = 64 << 10; // 64 KiB 25 const uint32_t TEST_MEMORY_PAGE = 64 << 10; // 64 KiB
24 const uint32_t TEST_ID = 12345; 26 const uint32_t TEST_ID = 12345;
25 const char TEST_NAME[] = "TestAllocator"; 27 const char TEST_NAME[] = "TestAllocator";
26 28
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
62 mem_segment_.get(), TEST_MEMORY_SIZE, TEST_MEMORY_PAGE, 64 mem_segment_.get(), TEST_MEMORY_SIZE, TEST_MEMORY_PAGE,
63 TEST_ID, TEST_NAME, false)); 65 TEST_ID, TEST_NAME, false));
64 allocator_->CreateTrackingHistograms(allocator_->Name()); 66 allocator_->CreateTrackingHistograms(allocator_->Name());
65 } 67 }
66 68
67 void TearDown() override { 69 void TearDown() override {
68 allocator_.reset(); 70 allocator_.reset();
69 } 71 }
70 72
71 unsigned CountIterables() { 73 unsigned CountIterables() {
72 PersistentMemoryAllocator::Iterator iter; 74 PersistentMemoryAllocator::Iterator iter(allocator_.get());
73 uint32_t type; 75 uint32_t type;
74 unsigned count = 0; 76 unsigned count = 0;
75 for (allocator_->CreateIterator(&iter); 77 while (iter.GetNext(&type) != 0) {
76 allocator_->GetNextIterable(&iter, &type) != 0;) { 78 ++count;
77 count++;
78 } 79 }
79 return count; 80 return count;
80 } 81 }
81 82
82 protected: 83 protected:
83 std::unique_ptr<char[]> mem_segment_; 84 std::unique_ptr<char[]> mem_segment_;
84 std::unique_ptr<PersistentMemoryAllocator> allocator_; 85 std::unique_ptr<PersistentMemoryAllocator> allocator_;
85 }; 86 };
86 87
87 TEST_F(PersistentMemoryAllocatorTest, AllocateAndIterate) { 88 TEST_F(PersistentMemoryAllocatorTest, AllocateAndIterate) {
(...skipping 20 matching lines...) Expand all
108 EXPECT_EQ(nullptr, allocator_->GetAsObject<TestObject2>(block1, 1)); 109 EXPECT_EQ(nullptr, allocator_->GetAsObject<TestObject2>(block1, 1));
109 EXPECT_LE(sizeof(TestObject1), allocator_->GetAllocSize(block1)); 110 EXPECT_LE(sizeof(TestObject1), allocator_->GetAllocSize(block1));
110 EXPECT_GT(sizeof(TestObject1) + kAllocAlignment, 111 EXPECT_GT(sizeof(TestObject1) + kAllocAlignment,
111 allocator_->GetAllocSize(block1)); 112 allocator_->GetAllocSize(block1));
112 PersistentMemoryAllocator::MemoryInfo meminfo1; 113 PersistentMemoryAllocator::MemoryInfo meminfo1;
113 allocator_->GetMemoryInfo(&meminfo1); 114 allocator_->GetMemoryInfo(&meminfo1);
114 EXPECT_EQ(meminfo0.total, meminfo1.total); 115 EXPECT_EQ(meminfo0.total, meminfo1.total);
115 EXPECT_GT(meminfo0.free, meminfo1.free); 116 EXPECT_GT(meminfo0.free, meminfo1.free);
116 117
117 // Ensure that the test-object can be made iterable. 118 // Ensure that the test-object can be made iterable.
118 PersistentMemoryAllocator::Iterator iter; 119 PersistentMemoryAllocator::Iterator iter1a(allocator_.get());
119 uint32_t type; 120 uint32_t type;
120 allocator_->CreateIterator(&iter); 121 EXPECT_EQ(0U, iter1a.GetNext(&type));
121 EXPECT_EQ(0U, allocator_->GetNextIterable(&iter, &type));
122 allocator_->MakeIterable(block1); 122 allocator_->MakeIterable(block1);
123 EXPECT_EQ(block1, allocator_->GetNextIterable(&iter, &type)); 123 EXPECT_EQ(block1, iter1a.GetNext(&type));
124 EXPECT_EQ(1U, type); 124 EXPECT_EQ(1U, type);
125 EXPECT_EQ(0U, allocator_->GetNextIterable(&iter, &type)); 125 EXPECT_EQ(0U, iter1a.GetNext(&type));
126 126
127 // Create second test-object and ensure everything is good and it cannot 127 // Create second test-object and ensure everything is good and it cannot
128 // be confused with test-object of another type. 128 // be confused with test-object of another type.
129 Reference block2 = allocator_->Allocate(sizeof(TestObject2), 2); 129 Reference block2 = allocator_->Allocate(sizeof(TestObject2), 2);
130 EXPECT_NE(0U, block2); 130 EXPECT_NE(0U, block2);
131 EXPECT_NE(nullptr, allocator_->GetAsObject<TestObject2>(block2, 2)); 131 EXPECT_NE(nullptr, allocator_->GetAsObject<TestObject2>(block2, 2));
132 EXPECT_EQ(nullptr, allocator_->GetAsObject<TestObject2>(block2, 1)); 132 EXPECT_EQ(nullptr, allocator_->GetAsObject<TestObject2>(block2, 1));
133 EXPECT_LE(sizeof(TestObject2), allocator_->GetAllocSize(block2)); 133 EXPECT_LE(sizeof(TestObject2), allocator_->GetAllocSize(block2));
134 EXPECT_GT(sizeof(TestObject2) + kAllocAlignment, 134 EXPECT_GT(sizeof(TestObject2) + kAllocAlignment,
135 allocator_->GetAllocSize(block2)); 135 allocator_->GetAllocSize(block2));
136 PersistentMemoryAllocator::MemoryInfo meminfo2; 136 PersistentMemoryAllocator::MemoryInfo meminfo2;
137 allocator_->GetMemoryInfo(&meminfo2); 137 allocator_->GetMemoryInfo(&meminfo2);
138 EXPECT_EQ(meminfo1.total, meminfo2.total); 138 EXPECT_EQ(meminfo1.total, meminfo2.total);
139 EXPECT_GT(meminfo1.free, meminfo2.free); 139 EXPECT_GT(meminfo1.free, meminfo2.free);
140 140
141 // Ensure that second test-object can also be made iterable. 141 // Ensure that second test-object can also be made iterable.
142 allocator_->MakeIterable(block2); 142 allocator_->MakeIterable(block2);
143 EXPECT_EQ(block2, allocator_->GetNextIterable(&iter, &type)); 143 EXPECT_EQ(block2, iter1a.GetNext(&type));
144 EXPECT_EQ(2U, type); 144 EXPECT_EQ(2U, type);
145 EXPECT_EQ(0U, allocator_->GetNextIterable(&iter, &type)); 145 EXPECT_EQ(0U, iter1a.GetNext(&type));
146 146
147 // Check that iteration can begin after an arbitrary location. 147 // Check that iteration can begin after an arbitrary location.
148 allocator_->CreateIterator(&iter, block1); 148 PersistentMemoryAllocator::Iterator iter1b(allocator_.get(), block1);
149 EXPECT_EQ(block2, allocator_->GetNextIterable(&iter, &type)); 149 EXPECT_EQ(block2, iter1b.GetNext(&type));
150 EXPECT_EQ(0U, allocator_->GetNextIterable(&iter, &type)); 150 EXPECT_EQ(0U, iter1b.GetNext(&type));
151 151
152 // Ensure nothing has gone noticably wrong. 152 // Ensure nothing has gone noticably wrong.
153 EXPECT_FALSE(allocator_->IsFull()); 153 EXPECT_FALSE(allocator_->IsFull());
154 EXPECT_FALSE(allocator_->IsCorrupt()); 154 EXPECT_FALSE(allocator_->IsCorrupt());
155 155
156 // Check the internal histogram record of used memory. 156 // Check the internal histogram record of used memory.
157 allocator_->UpdateTrackingHistograms(); 157 allocator_->UpdateTrackingHistograms();
158 std::unique_ptr<HistogramSamples> used_samples( 158 std::unique_ptr<HistogramSamples> used_samples(
159 allocator_->used_histogram_->SnapshotSamples()); 159 allocator_->used_histogram_->SnapshotSamples());
160 EXPECT_TRUE(used_samples); 160 EXPECT_TRUE(used_samples);
(...skipping 24 matching lines...) Expand all
185 // Create second allocator (read/write) using the same memory segment. 185 // Create second allocator (read/write) using the same memory segment.
186 std::unique_ptr<PersistentMemoryAllocator> allocator2( 186 std::unique_ptr<PersistentMemoryAllocator> allocator2(
187 new PersistentMemoryAllocator(mem_segment_.get(), TEST_MEMORY_SIZE, 187 new PersistentMemoryAllocator(mem_segment_.get(), TEST_MEMORY_SIZE,
188 TEST_MEMORY_PAGE, 0, "", false)); 188 TEST_MEMORY_PAGE, 0, "", false));
189 EXPECT_EQ(TEST_ID, allocator2->Id()); 189 EXPECT_EQ(TEST_ID, allocator2->Id());
190 EXPECT_FALSE(allocator2->used_histogram_); 190 EXPECT_FALSE(allocator2->used_histogram_);
191 EXPECT_FALSE(allocator2->allocs_histogram_); 191 EXPECT_FALSE(allocator2->allocs_histogram_);
192 EXPECT_NE(allocator2->allocs_histogram_, allocator_->allocs_histogram_); 192 EXPECT_NE(allocator2->allocs_histogram_, allocator_->allocs_histogram_);
193 193
194 // Ensure that iteration and access through second allocator works. 194 // Ensure that iteration and access through second allocator works.
195 allocator2->CreateIterator(&iter); 195 PersistentMemoryAllocator::Iterator iter2(allocator2.get());
196 EXPECT_EQ(block1, allocator2->GetNextIterable(&iter, &type)); 196 EXPECT_EQ(block1, iter2.GetNext(&type));
197 EXPECT_EQ(block2, allocator2->GetNextIterable(&iter, &type)); 197 EXPECT_EQ(block2, iter2.GetNext(&type));
198 EXPECT_EQ(0U, allocator2->GetNextIterable(&iter, &type)); 198 EXPECT_EQ(0U, iter2.GetNext(&type));
199 EXPECT_NE(nullptr, allocator2->GetAsObject<TestObject1>(block1, 1)); 199 EXPECT_NE(nullptr, allocator2->GetAsObject<TestObject1>(block1, 1));
200 EXPECT_NE(nullptr, allocator2->GetAsObject<TestObject2>(block2, 2)); 200 EXPECT_NE(nullptr, allocator2->GetAsObject<TestObject2>(block2, 2));
201 201
202 // Create a third allocator (read-only) using the same memory segment. 202 // Create a third allocator (read-only) using the same memory segment.
203 std::unique_ptr<const PersistentMemoryAllocator> allocator3( 203 std::unique_ptr<const PersistentMemoryAllocator> allocator3(
204 new PersistentMemoryAllocator(mem_segment_.get(), TEST_MEMORY_SIZE, 204 new PersistentMemoryAllocator(mem_segment_.get(), TEST_MEMORY_SIZE,
205 TEST_MEMORY_PAGE, 0, "", true)); 205 TEST_MEMORY_PAGE, 0, "", true));
206 EXPECT_EQ(TEST_ID, allocator3->Id()); 206 EXPECT_EQ(TEST_ID, allocator3->Id());
207 EXPECT_FALSE(allocator3->used_histogram_); 207 EXPECT_FALSE(allocator3->used_histogram_);
208 EXPECT_FALSE(allocator3->allocs_histogram_); 208 EXPECT_FALSE(allocator3->allocs_histogram_);
209 209
210 // Ensure that iteration and access through third allocator works. 210 // Ensure that iteration and access through third allocator works.
211 allocator3->CreateIterator(&iter); 211 PersistentMemoryAllocator::Iterator iter3(allocator3.get());
212 EXPECT_EQ(block1, allocator3->GetNextIterable(&iter, &type)); 212 EXPECT_EQ(block1, iter3.GetNext(&type));
213 EXPECT_EQ(block2, allocator3->GetNextIterable(&iter, &type)); 213 EXPECT_EQ(block2, iter3.GetNext(&type));
214 EXPECT_EQ(0U, allocator3->GetNextIterable(&iter, &type)); 214 EXPECT_EQ(0U, iter3.GetNext(&type));
215 EXPECT_NE(nullptr, allocator3->GetAsObject<TestObject1>(block1, 1)); 215 EXPECT_NE(nullptr, allocator3->GetAsObject<TestObject1>(block1, 1));
216 EXPECT_NE(nullptr, allocator3->GetAsObject<TestObject2>(block2, 2)); 216 EXPECT_NE(nullptr, allocator3->GetAsObject<TestObject2>(block2, 2));
217
218 // Ensure that GetNextOfType works.
219 PersistentMemoryAllocator::Iterator iter1c(allocator_.get());
220 EXPECT_EQ(block2, iter1c.GetNextOfType(2));
221 EXPECT_EQ(0U, iter1c.GetNextOfType(2));
217 } 222 }
218 223
219 TEST_F(PersistentMemoryAllocatorTest, PageTest) { 224 TEST_F(PersistentMemoryAllocatorTest, PageTest) {
220 // This allocation will go into the first memory page. 225 // This allocation will go into the first memory page.
221 Reference block1 = allocator_->Allocate(TEST_MEMORY_PAGE / 2, 1); 226 Reference block1 = allocator_->Allocate(TEST_MEMORY_PAGE / 2, 1);
222 EXPECT_LT(0U, block1); 227 EXPECT_LT(0U, block1);
223 EXPECT_GT(TEST_MEMORY_PAGE, block1); 228 EXPECT_GT(TEST_MEMORY_PAGE, block1);
224 229
225 // This allocation won't fit in same page as previous block. 230 // This allocation won't fit in same page as previous block.
226 Reference block2 = 231 Reference block2 =
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 t4.Join(); 303 t4.Join();
299 t5.Join(); 304 t5.Join();
300 305
301 EXPECT_FALSE(allocator_->IsCorrupt()); 306 EXPECT_FALSE(allocator_->IsCorrupt());
302 EXPECT_TRUE(allocator_->IsFull()); 307 EXPECT_TRUE(allocator_->IsFull());
303 EXPECT_EQ(CountIterables(), 308 EXPECT_EQ(CountIterables(),
304 t1.iterable() + t2.iterable() + t3.iterable() + t4.iterable() + 309 t1.iterable() + t2.iterable() + t3.iterable() + t4.iterable() +
305 t5.iterable()); 310 t5.iterable());
306 } 311 }
307 312
313 // A simple thread that counts objects by iterating through an allocator.
314 class CounterThread : public SimpleThread {
315 public:
316 CounterThread(const std::string& name,
317 PersistentMemoryAllocator::Iterator* iterator,
318 Lock* lock,
319 ConditionVariable* condition)
320 : SimpleThread(name, Options()),
321 iterator_(iterator),
322 lock_(lock),
323 condition_(condition),
324 count_(0) {}
325
326 void Run() override {
327 // Wait so all threads can start at approximately the same time.
328 // Best performance comes from releasing a single worker which then
329 // releases the next, etc., etc.
330 {
331 AutoLock autolock(*lock_);
332 condition_->Wait();
333 condition_->Signal();
334 }
335
336 uint32_t type;
337 while (iterator_->GetNext(&type) != 0) {
338 ++count_;
339 }
340 }
341
342 unsigned count() { return count_; }
343
344 private:
345 PersistentMemoryAllocator::Iterator* iterator_;
346 Lock* lock_;
347 ConditionVariable* condition_;
348 unsigned count_;
349 };
350
351 // Ensure that parallel iteration returns the same number of objects as
352 // single-threaded iteration.
353 TEST_F(PersistentMemoryAllocatorTest, IteratorParallelismTest) {
354 // Fill the memory segment with random allocations.
355 unsigned iterable_count = 0;
356 for (;;) {
357 uint32_t size = RandInt(1, 99);
358 uint32_t type = RandInt(100, 999);
359 Reference block = allocator_->Allocate(size, type);
360 if (!block)
361 break;
362 allocator_->MakeIterable(block);
363 ++iterable_count;
364 }
365 EXPECT_FALSE(allocator_->IsCorrupt());
366 EXPECT_TRUE(allocator_->IsFull());
367 EXPECT_EQ(iterable_count, CountIterables());
368
369 PersistentMemoryAllocator::Iterator iter(allocator_.get());
370 Lock lock;
371 ConditionVariable condition(&lock);
372
373 CounterThread t1("t1", &iter, &lock, &condition);
374 CounterThread t2("t2", &iter, &lock, &condition);
375 CounterThread t3("t3", &iter, &lock, &condition);
376 CounterThread t4("t4", &iter, &lock, &condition);
377 CounterThread t5("t5", &iter, &lock, &condition);
378
379 t1.Start();
380 t2.Start();
381 t3.Start();
382 t4.Start();
383 t5.Start();
384
385 // This will release all the waiting threads.
386 condition.Signal();
387
388 t1.Join();
389 t2.Join();
390 t3.Join();
391 t4.Join();
392 t5.Join();
393
394 EXPECT_EQ(iterable_count,
395 t1.count() + t2.count() + t3.count() + t4.count() + t5.count());
396
397 #if 0
398 // These ensure that the threads don't run sequentially. It shouldn't be
399 // enabled in general because it could lead to a flaky test if it happens
400 // simply by chance but it is useful during development to ensure that the
401 // test is working correctly.
402 EXPECT_NE(iterable_count, t1.count());
403 EXPECT_NE(iterable_count, t2.count());
404 EXPECT_NE(iterable_count, t3.count());
405 EXPECT_NE(iterable_count, t4.count());
406 EXPECT_NE(iterable_count, t5.count());
407 #endif
408 }
409
308 // This test doesn't verify anything other than it doesn't crash. Its goal 410 // This test doesn't verify anything other than it doesn't crash. Its goal
309 // is to find coding errors that aren't otherwise tested for, much like a 411 // is to find coding errors that aren't otherwise tested for, much like a
310 // "fuzzer" would. 412 // "fuzzer" would.
311 // This test is suppsoed to fail on TSAN bot (crbug.com/579867). 413 // This test is suppsoed to fail on TSAN bot (crbug.com/579867).
312 #if defined(THREAD_SANITIZER) 414 #if defined(THREAD_SANITIZER)
313 #define MAYBE_CorruptionTest DISABLED_CorruptionTest 415 #define MAYBE_CorruptionTest DISABLED_CorruptionTest
314 #else 416 #else
315 #define MAYBE_CorruptionTest CorruptionTest 417 #define MAYBE_CorruptionTest CorruptionTest
316 #endif 418 #endif
317 TEST_F(PersistentMemoryAllocatorTest, MAYBE_CorruptionTest) { 419 TEST_F(PersistentMemoryAllocatorTest, MAYBE_CorruptionTest) {
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 std::unique_ptr<SharedMemory> shmem2(new SharedMemory(shared_handle, 522 std::unique_ptr<SharedMemory> shmem2(new SharedMemory(shared_handle,
421 /*readonly=*/true)); 523 /*readonly=*/true));
422 ASSERT_TRUE(shmem2->Map(TEST_MEMORY_SIZE)); 524 ASSERT_TRUE(shmem2->Map(TEST_MEMORY_SIZE));
423 525
424 SharedPersistentMemoryAllocator shalloc2(std::move(shmem2), 0, "", true); 526 SharedPersistentMemoryAllocator shalloc2(std::move(shmem2), 0, "", true);
425 EXPECT_TRUE(shalloc2.IsReadonly()); 527 EXPECT_TRUE(shalloc2.IsReadonly());
426 EXPECT_EQ(TEST_ID, shalloc2.Id()); 528 EXPECT_EQ(TEST_ID, shalloc2.Id());
427 EXPECT_FALSE(shalloc2.IsFull()); 529 EXPECT_FALSE(shalloc2.IsFull());
428 EXPECT_FALSE(shalloc2.IsCorrupt()); 530 EXPECT_FALSE(shalloc2.IsCorrupt());
429 531
430 PersistentMemoryAllocator::Iterator iter2; 532 PersistentMemoryAllocator::Iterator iter2(&shalloc2);
431 uint32_t type; 533 uint32_t type;
432 shalloc2.CreateIterator(&iter2); 534 EXPECT_EQ(r123, iter2.GetNext(&type));
433 EXPECT_EQ(r123, shalloc2.GetNextIterable(&iter2, &type)); 535 EXPECT_EQ(r789, iter2.GetNext(&type));
434 EXPECT_EQ(r789, shalloc2.GetNextIterable(&iter2, &type)); 536 EXPECT_EQ(0U, iter2.GetNext(&type));
435 EXPECT_EQ(0U, shalloc2.GetNextIterable(&iter2, &type));
436 537
437 EXPECT_EQ(123U, shalloc2.GetType(r123)); 538 EXPECT_EQ(123U, shalloc2.GetType(r123));
438 EXPECT_EQ(654U, shalloc2.GetType(r456)); 539 EXPECT_EQ(654U, shalloc2.GetType(r456));
439 EXPECT_EQ(789U, shalloc2.GetType(r789)); 540 EXPECT_EQ(789U, shalloc2.GetType(r789));
440 541
441 PersistentMemoryAllocator::MemoryInfo meminfo2; 542 PersistentMemoryAllocator::MemoryInfo meminfo2;
442 shalloc2.GetMemoryInfo(&meminfo2); 543 shalloc2.GetMemoryInfo(&meminfo2);
443 EXPECT_EQ(meminfo1.total, meminfo2.total); 544 EXPECT_EQ(meminfo1.total, meminfo2.total);
444 EXPECT_EQ(meminfo1.free, meminfo2.free); 545 EXPECT_EQ(meminfo1.free, meminfo2.free);
445 546
446 // Read/write test. 547 // Read/write test.
447 std::unique_ptr<SharedMemory> shmem3(new SharedMemory(shared_handle, 548 std::unique_ptr<SharedMemory> shmem3(new SharedMemory(shared_handle,
448 /*readonly=*/false)); 549 /*readonly=*/false));
449 ASSERT_TRUE(shmem3->Map(TEST_MEMORY_SIZE)); 550 ASSERT_TRUE(shmem3->Map(TEST_MEMORY_SIZE));
450 551
451 SharedPersistentMemoryAllocator shalloc3(std::move(shmem3), 0, "", false); 552 SharedPersistentMemoryAllocator shalloc3(std::move(shmem3), 0, "", false);
452 EXPECT_FALSE(shalloc3.IsReadonly()); 553 EXPECT_FALSE(shalloc3.IsReadonly());
453 EXPECT_EQ(TEST_ID, shalloc3.Id()); 554 EXPECT_EQ(TEST_ID, shalloc3.Id());
454 EXPECT_FALSE(shalloc3.IsFull()); 555 EXPECT_FALSE(shalloc3.IsFull());
455 EXPECT_FALSE(shalloc3.IsCorrupt()); 556 EXPECT_FALSE(shalloc3.IsCorrupt());
456 557
457 PersistentMemoryAllocator::Iterator iter3; 558 PersistentMemoryAllocator::Iterator iter3(&shalloc3);
458 shalloc3.CreateIterator(&iter3); 559 EXPECT_EQ(r123, iter3.GetNext(&type));
459 EXPECT_EQ(r123, shalloc3.GetNextIterable(&iter3, &type)); 560 EXPECT_EQ(r789, iter3.GetNext(&type));
460 EXPECT_EQ(r789, shalloc3.GetNextIterable(&iter3, &type)); 561 EXPECT_EQ(0U, iter3.GetNext(&type));
461 EXPECT_EQ(0U, shalloc3.GetNextIterable(&iter3, &type));
462 562
463 EXPECT_EQ(123U, shalloc3.GetType(r123)); 563 EXPECT_EQ(123U, shalloc3.GetType(r123));
464 EXPECT_EQ(654U, shalloc3.GetType(r456)); 564 EXPECT_EQ(654U, shalloc3.GetType(r456));
465 EXPECT_EQ(789U, shalloc3.GetType(r789)); 565 EXPECT_EQ(789U, shalloc3.GetType(r789));
466 566
467 PersistentMemoryAllocator::MemoryInfo meminfo3; 567 PersistentMemoryAllocator::MemoryInfo meminfo3;
468 shalloc3.GetMemoryInfo(&meminfo3); 568 shalloc3.GetMemoryInfo(&meminfo3);
469 EXPECT_EQ(meminfo1.total, meminfo3.total); 569 EXPECT_EQ(meminfo1.total, meminfo3.total);
470 EXPECT_EQ(meminfo1.free, meminfo3.free); 570 EXPECT_EQ(meminfo1.free, meminfo3.free);
471 571
472 // Interconnectivity test. 572 // Interconnectivity test.
473 Reference obj = shalloc3.Allocate(42, 42); 573 Reference obj = shalloc3.Allocate(42, 42);
474 ASSERT_TRUE(obj); 574 ASSERT_TRUE(obj);
475 shalloc3.MakeIterable(obj); 575 shalloc3.MakeIterable(obj);
476 EXPECT_EQ(obj, shalloc2.GetNextIterable(&iter2, &type)); 576 EXPECT_EQ(obj, iter2.GetNext(&type));
477 EXPECT_EQ(42U, type); 577 EXPECT_EQ(42U, type);
478 } 578 }
479 579
480 580
481 //----- FilePersistentMemoryAllocator ------------------------------------------ 581 //----- FilePersistentMemoryAllocator ------------------------------------------
482 582
483 TEST(FilePersistentMemoryAllocatorTest, CreationTest) { 583 TEST(FilePersistentMemoryAllocatorTest, CreationTest) {
484 ScopedTempDir temp_dir; 584 ScopedTempDir temp_dir;
485 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 585 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
486 FilePath file_path = temp_dir.path().AppendASCII("persistent_memory"); 586 FilePath file_path = temp_dir.path().AppendASCII("persistent_memory");
(...skipping 23 matching lines...) Expand all
510 EXPECT_TRUE(mmfile->IsValid()); 610 EXPECT_TRUE(mmfile->IsValid());
511 const size_t mmlength = mmfile->length(); 611 const size_t mmlength = mmfile->length();
512 EXPECT_GE(meminfo1.total, mmlength); 612 EXPECT_GE(meminfo1.total, mmlength);
513 613
514 FilePersistentMemoryAllocator file(std::move(mmfile), 0, ""); 614 FilePersistentMemoryAllocator file(std::move(mmfile), 0, "");
515 EXPECT_TRUE(file.IsReadonly()); 615 EXPECT_TRUE(file.IsReadonly());
516 EXPECT_EQ(TEST_ID, file.Id()); 616 EXPECT_EQ(TEST_ID, file.Id());
517 EXPECT_FALSE(file.IsFull()); 617 EXPECT_FALSE(file.IsFull());
518 EXPECT_FALSE(file.IsCorrupt()); 618 EXPECT_FALSE(file.IsCorrupt());
519 619
520 PersistentMemoryAllocator::Iterator iter; 620 PersistentMemoryAllocator::Iterator iter(&file);
521 uint32_t type; 621 uint32_t type;
522 file.CreateIterator(&iter); 622 EXPECT_EQ(r123, iter.GetNext(&type));
523 EXPECT_EQ(r123, file.GetNextIterable(&iter, &type)); 623 EXPECT_EQ(r789, iter.GetNext(&type));
524 EXPECT_EQ(r789, file.GetNextIterable(&iter, &type)); 624 EXPECT_EQ(0U, iter.GetNext(&type));
525 EXPECT_EQ(0U, file.GetNextIterable(&iter, &type));
526 625
527 EXPECT_EQ(123U, file.GetType(r123)); 626 EXPECT_EQ(123U, file.GetType(r123));
528 EXPECT_EQ(654U, file.GetType(r456)); 627 EXPECT_EQ(654U, file.GetType(r456));
529 EXPECT_EQ(789U, file.GetType(r789)); 628 EXPECT_EQ(789U, file.GetType(r789));
530 629
531 PersistentMemoryAllocator::MemoryInfo meminfo2; 630 PersistentMemoryAllocator::MemoryInfo meminfo2;
532 file.GetMemoryInfo(&meminfo2); 631 file.GetMemoryInfo(&meminfo2);
533 EXPECT_GE(meminfo1.total, meminfo2.total); 632 EXPECT_GE(meminfo1.total, meminfo2.total);
534 EXPECT_GE(meminfo1.free, meminfo2.free); 633 EXPECT_GE(meminfo1.free, meminfo2.free);
535 EXPECT_EQ(mmlength, meminfo2.total); 634 EXPECT_EQ(mmlength, meminfo2.total);
536 EXPECT_EQ(0U, meminfo2.free); 635 EXPECT_EQ(0U, meminfo2.free);
537 } 636 }
538 637
539 TEST(FilePersistentMemoryAllocatorTest, AcceptableTest) { 638 TEST(FilePersistentMemoryAllocatorTest, AcceptableTest) {
540 ScopedTempDir temp_dir; 639 ScopedTempDir temp_dir;
541 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 640 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
542 FilePath file_path_base = temp_dir.path().AppendASCII("persistent_memory_"); 641 FilePath file_path_base = temp_dir.path().AppendASCII("persistent_memory_");
543 642
544 LocalPersistentMemoryAllocator local(TEST_MEMORY_SIZE, TEST_ID, ""); 643 LocalPersistentMemoryAllocator local(TEST_MEMORY_SIZE, TEST_ID, "");
545 local.Allocate(1, 1); 644 local.MakeIterable(local.Allocate(1, 1));
546 local.Allocate(11, 11); 645 local.MakeIterable(local.Allocate(11, 11));
547 const size_t minsize = local.used(); 646 const size_t minsize = local.used();
548 std::unique_ptr<char[]> garbage(new char[minsize]); 647 std::unique_ptr<char[]> garbage(new char[minsize]);
549 RandBytes(garbage.get(), minsize); 648 RandBytes(garbage.get(), minsize);
550 649
551 std::unique_ptr<MemoryMappedFile> mmfile; 650 std::unique_ptr<MemoryMappedFile> mmfile;
552 char filename[100]; 651 char filename[100];
553 for (size_t filesize = minsize; filesize > 0; --filesize) { 652 for (size_t filesize = minsize; filesize > 0; --filesize) {
554 strings::SafeSPrintf(filename, "memory_%d_A", filesize); 653 strings::SafeSPrintf(filename, "memory_%d_A", filesize);
555 FilePath file_path = temp_dir.path().AppendASCII(filename); 654 FilePath file_path = temp_dir.path().AppendASCII(filename);
556 ASSERT_FALSE(PathExists(file_path)); 655 ASSERT_FALSE(PathExists(file_path));
557 { 656 {
558 File writer(file_path, File::FLAG_CREATE | File::FLAG_WRITE); 657 File writer(file_path, File::FLAG_CREATE | File::FLAG_WRITE);
559 ASSERT_TRUE(writer.IsValid()); 658 ASSERT_TRUE(writer.IsValid());
560 writer.Write(0, (const char*)local.data(), filesize); 659 writer.Write(0, (const char*)local.data(), filesize);
561 } 660 }
562 ASSERT_TRUE(PathExists(file_path)); 661 ASSERT_TRUE(PathExists(file_path));
563 662
564 mmfile.reset(new MemoryMappedFile()); 663 mmfile.reset(new MemoryMappedFile());
565 mmfile->Initialize(file_path); 664 mmfile->Initialize(file_path);
566 EXPECT_EQ(filesize, mmfile->length()); 665 EXPECT_EQ(filesize, mmfile->length());
567 if (FilePersistentMemoryAllocator::IsFileAcceptable(*mmfile)) { 666 if (FilePersistentMemoryAllocator::IsFileAcceptable(*mmfile)) {
568 // Make sure construction doesn't crash. It will, however, cause 667 // Make sure construction doesn't crash. It will, however, cause
569 // error messages warning about about a corrupted memory segment. 668 // error messages warning about about a corrupted memory segment.
570 FilePersistentMemoryAllocator allocator(std::move(mmfile), 0, ""); 669 FilePersistentMemoryAllocator allocator(std::move(mmfile), 0, "");
571 // Also make sure that iteration doesn't crash. 670 // Also make sure that iteration doesn't crash.
572 PersistentMemoryAllocator::Iterator iter; 671 PersistentMemoryAllocator::Iterator iter(&allocator);
573 allocator.CreateIterator(&iter); 672 uint32_t type_id;
574 for (;;) { 673 Reference ref;
575 Reference ref = allocator.GetNextIterable(&iter, 0); 674 while ((ref = iter.GetNext(&type_id)) != 0) {
576 if (!ref)
577 break;
578 const char* data = allocator.GetAsObject<char>(ref, 0); 675 const char* data = allocator.GetAsObject<char>(ref, 0);
579 uint32_t type = allocator.GetType(ref); 676 uint32_t type = allocator.GetType(ref);
580 size_t size = allocator.GetAllocSize(ref); 677 size_t size = allocator.GetAllocSize(ref);
581 // Ensure compiler can't optimize-out above variables. 678 // Ensure compiler can't optimize-out above variables.
582 (void)data; 679 (void)data;
583 (void)type; 680 (void)type;
584 (void)size; 681 (void)size;
585 // Ensure that corruption-detected flag gets properly set.
586 EXPECT_EQ(filesize != minsize, allocator.IsCorrupt());
587 } 682 }
683 // Ensure that short files are detected as corrupt and full files are not.
684 EXPECT_EQ(filesize != minsize, allocator.IsCorrupt());
588 } else { 685 } else {
589 // For filesize >= minsize, the file must be acceptable. This 686 // For filesize >= minsize, the file must be acceptable. This
590 // else clause (file-not-acceptable) should be reached only if 687 // else clause (file-not-acceptable) should be reached only if
591 // filesize < minsize. 688 // filesize < minsize.
592 EXPECT_LT(filesize, minsize); 689 EXPECT_LT(filesize, minsize);
593 } 690 }
594 691
595 strings::SafeSPrintf(filename, "memory_%d_B", filesize); 692 strings::SafeSPrintf(filename, "memory_%d_B", filesize);
596 file_path = temp_dir.path().AppendASCII(filename); 693 file_path = temp_dir.path().AppendASCII(filename);
597 ASSERT_FALSE(PathExists(file_path)); 694 ASSERT_FALSE(PathExists(file_path));
(...skipping 15 matching lines...) Expand all
613 } else { 710 } else {
614 // For filesize >= minsize, the file must be acceptable. This 711 // For filesize >= minsize, the file must be acceptable. This
615 // else clause (file-not-acceptable) should be reached only if 712 // else clause (file-not-acceptable) should be reached only if
616 // filesize < minsize. 713 // filesize < minsize.
617 EXPECT_GT(minsize, filesize); 714 EXPECT_GT(minsize, filesize);
618 } 715 }
619 } 716 }
620 } 717 }
621 718
622 } // namespace base 719 } // namespace base
OLDNEW
« no previous file with comments | « base/metrics/persistent_memory_allocator.cc ('k') | base/metrics/persistent_sample_map.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698