• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2024 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/structured_shared_memory.h"
6 
7 #include <atomic>
8 #include <optional>
9 #include <utility>
10 
11 #include "base/containers/span.h"
12 #include "base/memory/platform_shared_memory_handle.h"
13 #include "base/memory/read_only_shared_memory_region.h"
14 #include "base/memory/shared_memory_mapper.h"
15 #include "base/test/gtest_util.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 
18 namespace base {
19 
20 namespace {
21 
22 // A SharedMemoryMapper that always fails to map memory.
23 class FailingSharedMemoryMapper final : public SharedMemoryMapper {
24  public:
Map(subtle::PlatformSharedMemoryHandle handle,bool write_allowed,uint64_t offset,size_t size)25   std::optional<span<uint8_t>> Map(subtle::PlatformSharedMemoryHandle handle,
26                                    bool write_allowed,
27                                    uint64_t offset,
28                                    size_t size) final {
29     return std::nullopt;
30   }
31 
Unmap(span<uint8_t> mapping)32   void Unmap(span<uint8_t> mapping) final {}
33 };
34 
TEST(StructuredSharedMemoryTest,ReadWrite)35 TEST(StructuredSharedMemoryTest, ReadWrite) {
36   auto writable_memory = StructuredSharedMemory<double>::Create();
37   ASSERT_TRUE(writable_memory.has_value());
38   EXPECT_EQ(writable_memory->WritablePtr(), &writable_memory->WritableRef());
39   EXPECT_EQ(writable_memory->WritablePtr(), writable_memory->ReadOnlyPtr());
40   EXPECT_EQ(writable_memory->ReadOnlyPtr(), &writable_memory->ReadOnlyRef());
41   EXPECT_EQ(writable_memory->ReadOnlyRef(), 0.0);
42 
43   auto read_only_memory = StructuredSharedMemory<double>::MapReadOnlyRegion(
44       writable_memory->TakeReadOnlyRegion());
45   ASSERT_TRUE(read_only_memory.has_value());
46   EXPECT_EQ(read_only_memory->ReadOnlyPtr(), &read_only_memory->ReadOnlyRef());
47   EXPECT_EQ(read_only_memory->ReadOnlyRef(), 0.0);
48 
49   writable_memory->WritableRef() += 0.5;
50   EXPECT_EQ(read_only_memory->ReadOnlyRef(), 0.5);
51 }
52 
TEST(StructuredSharedMemoryTest,Initialize)53 TEST(StructuredSharedMemoryTest, Initialize) {
54   // Default initialize.
55   auto writable_memory = StructuredSharedMemory<double>::Create();
56   ASSERT_TRUE(writable_memory.has_value());
57   EXPECT_EQ(writable_memory->ReadOnlyRef(), 0.0);
58 
59   // Initialize from same type.
60   writable_memory = StructuredSharedMemory<double>::Create(1.2);
61   ASSERT_TRUE(writable_memory.has_value());
62   EXPECT_EQ(writable_memory->ReadOnlyRef(), 1.2);
63 
64   // Initialize from compatible type.
65   writable_memory = StructuredSharedMemory<double>::Create(3);
66   ASSERT_TRUE(writable_memory.has_value());
67   EXPECT_EQ(writable_memory->ReadOnlyRef(), 3);
68 }
69 
TEST(StructuredSharedMemoryTest,MapFailure)70 TEST(StructuredSharedMemoryTest, MapFailure) {
71   // Fail to map writable memory.
72   FailingSharedMemoryMapper failing_mapper;
73   auto writable_memory =
74       StructuredSharedMemory<double>::CreateWithCustomMapper(&failing_mapper);
75   EXPECT_FALSE(writable_memory.has_value());
76 
77   // Initialize from same type, but fail.
78   writable_memory = StructuredSharedMemory<double>::CreateWithCustomMapper(
79       1.2, &failing_mapper);
80   EXPECT_FALSE(writable_memory.has_value());
81 
82   // Initialize from compatible type, but fail.
83   writable_memory = StructuredSharedMemory<double>::CreateWithCustomMapper(
84       3, &failing_mapper);
85   EXPECT_FALSE(writable_memory.has_value());
86 
87   // Fail to create read-only region (bad handle).
88   ReadOnlySharedMemoryRegion region;
89   EXPECT_FALSE(region.IsValid());
90   auto read_only_memory =
91       StructuredSharedMemory<double>::MapReadOnlyRegion(std::move(region));
92   EXPECT_FALSE(read_only_memory.has_value());
93 
94   // Valid handle for read-only region, but fail to map memory.
95   writable_memory = StructuredSharedMemory<double>::Create();
96   ASSERT_TRUE(writable_memory.has_value());
97   region = writable_memory->TakeReadOnlyRegion();
98   EXPECT_TRUE(region.IsValid());
99   read_only_memory = StructuredSharedMemory<double>::MapReadOnlyRegion(
100       std::move(region), &failing_mapper);
101   EXPECT_FALSE(read_only_memory.has_value());
102 }
103 
TEST(StructuredSharedMemoryDeathTest,DuplicateRegion)104 TEST(StructuredSharedMemoryDeathTest, DuplicateRegion) {
105   auto writable_memory = StructuredSharedMemory<double>::Create();
106   ASSERT_TRUE(writable_memory.has_value());
107   ReadOnlySharedMemoryRegion region =
108       writable_memory->DuplicateReadOnlyRegion();
109   ReadOnlySharedMemoryRegion region2 =
110       writable_memory->DuplicateReadOnlyRegion();
111   EXPECT_EQ(region.GetGUID(), region2.GetGUID());
112   ReadOnlySharedMemoryRegion region3 = writable_memory->TakeReadOnlyRegion();
113   EXPECT_EQ(region.GetGUID(), region3.GetGUID());
114   // Region is no longer valid.
115   EXPECT_CHECK_DEATH(writable_memory->DuplicateReadOnlyRegion());
116   EXPECT_CHECK_DEATH(writable_memory->TakeReadOnlyRegion());
117 }
118 
TEST(StructuredSharedMemoryTest,AtomicReadWrite)119 TEST(StructuredSharedMemoryTest, AtomicReadWrite) {
120   auto writable_memory = AtomicSharedMemory<int>::Create();
121   ASSERT_TRUE(writable_memory.has_value());
122   EXPECT_EQ(writable_memory->WritablePtr(), &writable_memory->WritableRef());
123   EXPECT_EQ(writable_memory->WritablePtr(), writable_memory->ReadOnlyPtr());
124   EXPECT_EQ(writable_memory->ReadOnlyPtr(), &writable_memory->ReadOnlyRef());
125   EXPECT_EQ(writable_memory->ReadOnlyRef().load(std::memory_order_relaxed), 0);
126 
127   auto read_only_memory = AtomicSharedMemory<int>::MapReadOnlyRegion(
128       writable_memory->TakeReadOnlyRegion());
129   ASSERT_TRUE(read_only_memory.has_value());
130   EXPECT_EQ(read_only_memory->ReadOnlyPtr(), &read_only_memory->ReadOnlyRef());
131   EXPECT_EQ(read_only_memory->ReadOnlyRef().load(std::memory_order_relaxed), 0);
132 
133   writable_memory->WritableRef().store(1, std::memory_order_relaxed);
134   EXPECT_EQ(read_only_memory->ReadOnlyRef().load(std::memory_order_relaxed), 1);
135 }
136 
TEST(StructuredSharedMemoryTest,AtomicInitialize)137 TEST(StructuredSharedMemoryTest, AtomicInitialize) {
138   auto writable_memory = AtomicSharedMemory<int>::Create();
139   ASSERT_TRUE(writable_memory.has_value());
140   EXPECT_EQ(writable_memory->ReadOnlyRef().load(std::memory_order_relaxed), 0);
141 
142   writable_memory = AtomicSharedMemory<int>::Create(1);
143   ASSERT_TRUE(writable_memory.has_value());
144   EXPECT_EQ(writable_memory->ReadOnlyRef().load(std::memory_order_relaxed), 1);
145 }
146 
147 }  // namespace
148 
149 }  // namespace base
150