xref: /aosp_15_r20/external/cronet/base/memory/shared_memory_mapping_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2018 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 #include "base/memory/shared_memory_mapping.h"
6 
7 #include <stdint.h>
8 
9 #include <limits>
10 
11 #include "base/containers/span.h"
12 #include "base/memory/read_only_shared_memory_region.h"
13 #include "base/memory/writable_shared_memory_region.h"
14 #include "base/ranges/algorithm.h"
15 #include "build/build_config.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 
19 namespace base {
20 
21 class SharedMemoryMappingTest : public ::testing::Test {
22  protected:
CreateMapping(size_t size)23   void CreateMapping(size_t size) {
24     auto result = ReadOnlySharedMemoryRegion::Create(size);
25     ASSERT_TRUE(result.IsValid());
26     write_mapping_ = std::move(result.mapping);
27     read_mapping_ = result.region.Map();
28     ASSERT_TRUE(read_mapping_.IsValid());
29   }
30 
31   WritableSharedMemoryMapping write_mapping_;
32   ReadOnlySharedMemoryMapping read_mapping_;
33 };
34 
TEST_F(SharedMemoryMappingTest,Invalid)35 TEST_F(SharedMemoryMappingTest, Invalid) {
36   EXPECT_EQ(nullptr, write_mapping_.GetMemoryAs<uint8_t>());
37   EXPECT_EQ(nullptr, read_mapping_.GetMemoryAs<uint8_t>());
38   EXPECT_TRUE(write_mapping_.GetMemoryAsSpan<uint8_t>().empty());
39   EXPECT_TRUE(read_mapping_.GetMemoryAsSpan<uint8_t>().empty());
40   EXPECT_TRUE(write_mapping_.GetMemoryAsSpan<uint8_t>(1).empty());
41   EXPECT_TRUE(read_mapping_.GetMemoryAsSpan<uint8_t>(1).empty());
42 }
43 
TEST_F(SharedMemoryMappingTest,Scalar)44 TEST_F(SharedMemoryMappingTest, Scalar) {
45   CreateMapping(sizeof(uint32_t));
46 
47   uint32_t* write_ptr = write_mapping_.GetMemoryAs<uint32_t>();
48   EXPECT_NE(nullptr, write_ptr);
49 
50   const uint32_t* read_ptr = read_mapping_.GetMemoryAs<uint32_t>();
51   EXPECT_NE(nullptr, read_ptr);
52 
53   *write_ptr = 0u;
54   EXPECT_EQ(0u, *read_ptr);
55 
56   *write_ptr = 0x12345678u;
57   EXPECT_EQ(0x12345678u, *read_ptr);
58 }
59 
TEST_F(SharedMemoryMappingTest,SpanWithAutoDeducedElementCount)60 TEST_F(SharedMemoryMappingTest, SpanWithAutoDeducedElementCount) {
61   CreateMapping(sizeof(uint8_t) * 8);
62 
63   span<uint8_t> write_span = write_mapping_.GetMemoryAsSpan<uint8_t>();
64   ASSERT_EQ(8u, write_span.size());
65 
66   span<const uint32_t> read_span = read_mapping_.GetMemoryAsSpan<uint32_t>();
67   ASSERT_EQ(2u, read_span.size());
68 
69   ranges::fill(write_span, 0);
70   EXPECT_EQ(0u, read_span[0]);
71   EXPECT_EQ(0u, read_span[1]);
72 
73   for (size_t i = 0; i < write_span.size(); ++i)
74     write_span[i] = i + 1;
75   EXPECT_EQ(0x04030201u, read_span[0]);
76   EXPECT_EQ(0x08070605u, read_span[1]);
77 }
78 
TEST_F(SharedMemoryMappingTest,SpanWithExplicitElementCount)79 TEST_F(SharedMemoryMappingTest, SpanWithExplicitElementCount) {
80   CreateMapping(sizeof(uint8_t) * 8);
81 
82   span<uint8_t> write_span = write_mapping_.GetMemoryAsSpan<uint8_t>(8);
83   ASSERT_EQ(8u, write_span.size());
84 
85   span<uint8_t> write_span_2 = write_mapping_.GetMemoryAsSpan<uint8_t>(4);
86   ASSERT_EQ(4u, write_span_2.size());
87 
88   span<const uint32_t> read_span = read_mapping_.GetMemoryAsSpan<uint32_t>(2);
89   ASSERT_EQ(2u, read_span.size());
90 
91   span<const uint32_t> read_span_2 = read_mapping_.GetMemoryAsSpan<uint32_t>(1);
92   ASSERT_EQ(1u, read_span_2.size());
93 
94   ranges::fill(write_span, 0);
95   EXPECT_EQ(0u, read_span[0]);
96   EXPECT_EQ(0u, read_span[1]);
97   EXPECT_EQ(0u, read_span_2[0]);
98 
99   for (size_t i = 0; i < write_span.size(); ++i)
100     write_span[i] = i + 1;
101   EXPECT_EQ(0x04030201u, read_span[0]);
102   EXPECT_EQ(0x08070605u, read_span[1]);
103   EXPECT_EQ(0x04030201u, read_span_2[0]);
104 
105   ranges::fill(write_span_2, 0);
106   EXPECT_EQ(0u, read_span[0]);
107   EXPECT_EQ(0x08070605u, read_span[1]);
108   EXPECT_EQ(0u, read_span_2[0]);
109 }
110 
TEST_F(SharedMemoryMappingTest,SpanWithZeroElementCount)111 TEST_F(SharedMemoryMappingTest, SpanWithZeroElementCount) {
112   CreateMapping(sizeof(uint8_t) * 8);
113 
114   EXPECT_TRUE(write_mapping_.GetMemoryAsSpan<uint8_t>(0).empty());
115 
116   EXPECT_TRUE(read_mapping_.GetMemoryAsSpan<uint8_t>(0).empty());
117 }
118 
TEST_F(SharedMemoryMappingTest,TooBigScalar)119 TEST_F(SharedMemoryMappingTest, TooBigScalar) {
120   CreateMapping(sizeof(uint8_t));
121 
122   EXPECT_EQ(nullptr, write_mapping_.GetMemoryAs<uint32_t>());
123 
124   EXPECT_EQ(nullptr, read_mapping_.GetMemoryAs<uint32_t>());
125 }
126 
TEST_F(SharedMemoryMappingTest,TooBigSpanWithAutoDeducedElementCount)127 TEST_F(SharedMemoryMappingTest, TooBigSpanWithAutoDeducedElementCount) {
128   CreateMapping(sizeof(uint8_t));
129 
130   EXPECT_TRUE(write_mapping_.GetMemoryAsSpan<uint32_t>().empty());
131 
132   EXPECT_TRUE(read_mapping_.GetMemoryAsSpan<uint32_t>().empty());
133 }
134 
TEST_F(SharedMemoryMappingTest,TooBigSpanWithExplicitElementCount)135 TEST_F(SharedMemoryMappingTest, TooBigSpanWithExplicitElementCount) {
136   CreateMapping(sizeof(uint8_t));
137 
138   // Deliberately pick element counts such that a naive bounds calculation would
139   // overflow.
140   EXPECT_TRUE(write_mapping_
141                   .GetMemoryAsSpan<uint32_t>(std::numeric_limits<size_t>::max())
142                   .empty());
143 
144   EXPECT_TRUE(read_mapping_
145                   .GetMemoryAsSpan<uint32_t>(std::numeric_limits<size_t>::max())
146                   .empty());
147 }
148 
149 // TODO(dcheng): This test is temporarily disabled on iOS. iOS devices allow
150 // the creation of a 1GB shared memory region, but don't allow the region to be
151 // mapped.
152 #if !BUILDFLAG(IS_IOS)
153 // TODO(crbug.com/1334079) Fix flakiness and re-enable on Linux and ChromeOS.
154 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
155 #define MAYBE_TotalMappedSizeLimit DISABLED_TotalMappedSizeLimit
156 #else
157 #define MAYBE_TotalMappedSizeLimit TotalMappedSizeLimit
158 #endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
TEST_F(SharedMemoryMappingTest,MAYBE_TotalMappedSizeLimit)159 TEST_F(SharedMemoryMappingTest, MAYBE_TotalMappedSizeLimit) {
160   // Nothing interesting to test if the address space isn't 64 bits, since
161   // there's no real limit enforced on 32 bits other than complete address
162   // space exhaustion.
163   // Also exclude NaCl since pointers are 32 bits on all architectures:
164   // https://bugs.chromium.org/p/nativeclient/issues/detail?id=1162
165 #if defined(ARCH_CPU_64_BITS) && !BUILDFLAG(IS_NACL)
166   auto region = WritableSharedMemoryRegion::Create(1024 * 1024 * 1024);
167   ASSERT_TRUE(region.IsValid());
168   // The limit is 32GB of mappings on 64-bit platforms, so the final mapping
169   // should fail.
170   std::vector<WritableSharedMemoryMapping> mappings(32);
171   for (size_t i = 0; i < mappings.size(); ++i) {
172     SCOPED_TRACE(i);
173     auto& mapping = mappings[i];
174     mapping = region.Map();
175     EXPECT_EQ(&mapping != &mappings.back(), mapping.IsValid());
176   }
177 #endif  // defined(ARCH_CPU_64_BITS)
178 }
179 #endif  // !BUILDFLAG(IS_IOS)
180 
181 }  // namespace base
182