• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifdef UNSAFE_BUFFERS_BUILD
6 // TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
7 #pragma allow_unsafe_buffers
8 #endif
9 
10 #include "base/profiler/stack_buffer.h"
11 
12 #include "base/memory/aligned_memory.h"
13 #include "build/build_config.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 
16 #if BUILDFLAG(IS_CHROMEOS)
17 #include "base/bits.h"
18 #include "base/memory/page_size.h"
19 #endif  // #if BUILDFLAG(IS_CHROMEOS)
20 
21 namespace base {
22 
TEST(StackBufferTest,BufferAllocated)23 TEST(StackBufferTest, BufferAllocated) {
24   const unsigned int kBufferSize = 32 * 1024;
25   StackBuffer stack_buffer(kBufferSize);
26   EXPECT_EQ(stack_buffer.size(), kBufferSize);
27   // Without volatile, the compiler could simply optimize away the entire for
28   // loop below.
29   volatile uintptr_t* buffer = stack_buffer.buffer();
30   ASSERT_NE(nullptr, buffer);
31   EXPECT_TRUE(IsAligned(const_cast<uintptr_t*>(buffer),
32                         StackBuffer::kPlatformStackAlignment));
33 
34   // Memory pointed to by buffer should be writable.
35   for (unsigned int i = 0; i < (kBufferSize / sizeof(buffer[0])); i++) {
36     buffer[i] = i;
37     EXPECT_EQ(buffer[i], i);
38   }
39 }
40 
41 #if BUILDFLAG(IS_CHROMEOS)
TEST(StackBufferTest,MarkBufferContentsAsUnneeded)42 TEST(StackBufferTest, MarkBufferContentsAsUnneeded) {
43   const unsigned int kBufferSize = 32 * GetPageSize();
44   StackBuffer stack_buffer(kBufferSize);
45   volatile uintptr_t* buffer = stack_buffer.buffer();
46   ASSERT_NE(nullptr, buffer);
47 
48   // Force the kernel to allocate backing store for the buffer.
49   for (unsigned int i = 0; i < (kBufferSize / sizeof(uintptr_t)); i++) {
50     buffer[i] = i;
51     EXPECT_EQ(buffer[i], i);
52   }
53 
54   // Tell kernel to discard (most of) the memory.
55   constexpr size_t kUndiscardedElements = 100;
56   stack_buffer.MarkUpperBufferContentsAsUnneeded(kUndiscardedElements *
57                                                  sizeof(buffer[0]));
58 
59   // The first 100 elements shouldn't have been discarded.
60   for (size_t i = 0; i < kUndiscardedElements; i++) {
61     EXPECT_EQ(buffer[i], i);
62   }
63 
64   // Pages past the discard point should be zero-filled now.
65   const size_t kExpectedDiscardStartPoint =
66       bits::AlignUp(kUndiscardedElements * sizeof(buffer[0]), GetPageSize()) /
67       sizeof(buffer[0]);
68   for (size_t i = kExpectedDiscardStartPoint;
69        i < kBufferSize / sizeof(buffer[0]); i++) {
70     EXPECT_EQ(buffer[i], 0U);
71   }
72 
73   // Writing to the memory (both discarded and undiscarded parts) shouldn't
74   // cause segmentation faults and should remember the value we write.
75   for (unsigned int i = 0; i < (kBufferSize / sizeof(buffer[0])); i++) {
76     buffer[i] = i + 7;
77     EXPECT_EQ(buffer[i], i + 7);
78   }
79 }
80 #endif  // #if BUILDFLAG(IS_CHROMEOS)
81 
82 }  // namespace base
83