• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 The Chromium Authors. All rights reserved.
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 "mojo/core/shared_buffer_dispatcher.h"
6 
7 #include <stddef.h>
8 #include <stdint.h>
9 
10 #include <limits>
11 
12 #include "base/macros.h"
13 #include "base/memory/platform_shared_memory_region.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/memory/writable_shared_memory_region.h"
16 #include "mojo/core/dispatcher.h"
17 #include "mojo/core/platform_shared_memory_mapping.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 
20 namespace mojo {
21 namespace core {
22 namespace {
23 
24 // NOTE(vtl): There's currently not much to test for in
25 // |SharedBufferDispatcher::ValidateCreateOptions()|, but the tests should be
26 // expanded if/when options are added, so I've kept the general form of the
27 // tests from data_pipe_unittest.cc.
28 
29 const uint32_t kSizeOfCreateOptions = sizeof(MojoCreateSharedBufferOptions);
30 
31 // Does a cursory sanity check of |validated_options|. Calls
32 // |ValidateCreateOptions()| on already-validated options. The validated options
33 // should be valid, and the revalidated copy should be the same.
RevalidateCreateOptions(const MojoCreateSharedBufferOptions & validated_options)34 void RevalidateCreateOptions(
35     const MojoCreateSharedBufferOptions& validated_options) {
36   EXPECT_EQ(kSizeOfCreateOptions, validated_options.struct_size);
37   // Nothing to check for flags.
38 
39   MojoCreateSharedBufferOptions revalidated_options = {};
40   EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::ValidateCreateOptions(
41                                 &validated_options, &revalidated_options));
42   EXPECT_EQ(validated_options.struct_size, revalidated_options.struct_size);
43   EXPECT_EQ(validated_options.flags, revalidated_options.flags);
44 }
45 
46 class SharedBufferDispatcherTest : public testing::Test {
47  public:
SharedBufferDispatcherTest()48   SharedBufferDispatcherTest() {}
~SharedBufferDispatcherTest()49   ~SharedBufferDispatcherTest() override {}
50 
51  private:
52   DISALLOW_COPY_AND_ASSIGN(SharedBufferDispatcherTest);
53 };
54 
55 // Tests valid inputs to |ValidateCreateOptions()|.
TEST_F(SharedBufferDispatcherTest,ValidateCreateOptionsValid)56 TEST_F(SharedBufferDispatcherTest, ValidateCreateOptionsValid) {
57   // Default options.
58   {
59     MojoCreateSharedBufferOptions validated_options = {};
60     EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::ValidateCreateOptions(
61                                   nullptr, &validated_options));
62     RevalidateCreateOptions(validated_options);
63   }
64 
65   // Different flags.
66   MojoCreateSharedBufferFlags flags_values[] = {
67       MOJO_CREATE_SHARED_BUFFER_FLAG_NONE};
68   for (size_t i = 0; i < arraysize(flags_values); i++) {
69     const MojoCreateSharedBufferFlags flags = flags_values[i];
70 
71     // Different capacities (size 1).
72     for (uint32_t capacity = 1; capacity <= 100 * 1000 * 1000; capacity *= 10) {
73       MojoCreateSharedBufferOptions options = {
74           kSizeOfCreateOptions,  // |struct_size|.
75           flags                  // |flags|.
76       };
77       MojoCreateSharedBufferOptions validated_options = {};
78       EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::ValidateCreateOptions(
79                                     &options, &validated_options))
80           << capacity;
81       RevalidateCreateOptions(validated_options);
82       EXPECT_EQ(options.flags, validated_options.flags);
83     }
84   }
85 }
86 
TEST_F(SharedBufferDispatcherTest,ValidateCreateOptionsInvalid)87 TEST_F(SharedBufferDispatcherTest, ValidateCreateOptionsInvalid) {
88   // Invalid |struct_size|.
89   {
90     MojoCreateSharedBufferOptions options = {
91         1,                                   // |struct_size|.
92         MOJO_CREATE_SHARED_BUFFER_FLAG_NONE  // |flags|.
93     };
94     MojoCreateSharedBufferOptions unused;
95     EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
96               SharedBufferDispatcher::ValidateCreateOptions(&options, &unused));
97   }
98 
99   // Unknown |flags|.
100   {
101     MojoCreateSharedBufferOptions options = {
102         kSizeOfCreateOptions,  // |struct_size|.
103         ~0u                    // |flags|.
104     };
105     MojoCreateSharedBufferOptions unused;
106     EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED,
107               SharedBufferDispatcher::ValidateCreateOptions(&options, &unused));
108   }
109 }
110 
TEST_F(SharedBufferDispatcherTest,CreateAndMapBuffer)111 TEST_F(SharedBufferDispatcherTest, CreateAndMapBuffer) {
112   scoped_refptr<SharedBufferDispatcher> dispatcher;
113   EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::Create(
114                                 SharedBufferDispatcher::kDefaultCreateOptions,
115                                 nullptr, 100, &dispatcher));
116   ASSERT_TRUE(dispatcher);
117   EXPECT_EQ(Dispatcher::Type::SHARED_BUFFER, dispatcher->GetType());
118 
119   // Make a couple of mappings.
120   std::unique_ptr<PlatformSharedMemoryMapping> mapping1;
121   EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer(0, 100, &mapping1));
122   ASSERT_TRUE(mapping1);
123   ASSERT_TRUE(mapping1->GetBase());
124   EXPECT_EQ(100u, mapping1->GetLength());
125   // Write something.
126   static_cast<char*>(mapping1->GetBase())[50] = 'x';
127 
128   std::unique_ptr<PlatformSharedMemoryMapping> mapping2;
129   EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer(50, 50, &mapping2));
130   ASSERT_TRUE(mapping2);
131   ASSERT_TRUE(mapping2->GetBase());
132   EXPECT_EQ(50u, mapping2->GetLength());
133   EXPECT_EQ('x', static_cast<char*>(mapping2->GetBase())[0]);
134 
135   EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close());
136 
137   // Check that we can still read/write to mappings after the dispatcher has
138   // gone away.
139   static_cast<char*>(mapping2->GetBase())[1] = 'y';
140   EXPECT_EQ('y', static_cast<char*>(mapping1->GetBase())[51]);
141 }
142 
TEST_F(SharedBufferDispatcherTest,CreateAndMapBufferFromPlatformBuffer)143 TEST_F(SharedBufferDispatcherTest, CreateAndMapBufferFromPlatformBuffer) {
144   base::WritableSharedMemoryRegion region =
145       base::WritableSharedMemoryRegion::Create(100);
146   ASSERT_TRUE(region.IsValid());
147   scoped_refptr<SharedBufferDispatcher> dispatcher;
148   EXPECT_EQ(MOJO_RESULT_OK,
149             SharedBufferDispatcher::CreateFromPlatformSharedMemoryRegion(
150                 base::WritableSharedMemoryRegion::TakeHandleForSerialization(
151                     std::move(region)),
152                 &dispatcher));
153   ASSERT_TRUE(dispatcher);
154   EXPECT_EQ(Dispatcher::Type::SHARED_BUFFER, dispatcher->GetType());
155 
156   // Make a couple of mappings.
157   std::unique_ptr<PlatformSharedMemoryMapping> mapping1;
158   EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer(0, 100, &mapping1));
159   ASSERT_TRUE(mapping1);
160   ASSERT_TRUE(mapping1->GetBase());
161   EXPECT_EQ(100u, mapping1->GetLength());
162   // Write something.
163   static_cast<char*>(mapping1->GetBase())[50] = 'x';
164 
165   std::unique_ptr<PlatformSharedMemoryMapping> mapping2;
166   EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer(50, 50, &mapping2));
167   ASSERT_TRUE(mapping2);
168   ASSERT_TRUE(mapping2->GetBase());
169   EXPECT_EQ(50u, mapping2->GetLength());
170   EXPECT_EQ('x', static_cast<char*>(mapping2->GetBase())[0]);
171 
172   EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close());
173 
174   // Check that we can still read/write to mappings after the dispatcher has
175   // gone away.
176   static_cast<char*>(mapping2->GetBase())[1] = 'y';
177   EXPECT_EQ('y', static_cast<char*>(mapping1->GetBase())[51]);
178 }
179 
TEST_F(SharedBufferDispatcherTest,DuplicateBufferHandle)180 TEST_F(SharedBufferDispatcherTest, DuplicateBufferHandle) {
181   scoped_refptr<SharedBufferDispatcher> dispatcher1;
182   EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::Create(
183                                 SharedBufferDispatcher::kDefaultCreateOptions,
184                                 nullptr, 100, &dispatcher1));
185 
186   // Map and write something.
187   std::unique_ptr<PlatformSharedMemoryMapping> mapping;
188   EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->MapBuffer(0, 100, &mapping));
189   static_cast<char*>(mapping->GetBase())[0] = 'x';
190   mapping.reset();
191 
192   // Duplicate |dispatcher1| and then close it.
193   scoped_refptr<Dispatcher> dispatcher2;
194   EXPECT_EQ(MOJO_RESULT_OK,
195             dispatcher1->DuplicateBufferHandle(nullptr, &dispatcher2));
196   ASSERT_TRUE(dispatcher2);
197   EXPECT_EQ(Dispatcher::Type::SHARED_BUFFER, dispatcher2->GetType());
198 
199   EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->Close());
200 
201   // Map |dispatcher2| and read something.
202   EXPECT_EQ(MOJO_RESULT_OK, dispatcher2->MapBuffer(0, 100, &mapping));
203   EXPECT_EQ('x', static_cast<char*>(mapping->GetBase())[0]);
204 
205   EXPECT_EQ(MOJO_RESULT_OK, dispatcher2->Close());
206 }
207 
TEST_F(SharedBufferDispatcherTest,DuplicateBufferHandleOptionsValid)208 TEST_F(SharedBufferDispatcherTest, DuplicateBufferHandleOptionsValid) {
209   scoped_refptr<SharedBufferDispatcher> dispatcher1;
210   EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::Create(
211                                 SharedBufferDispatcher::kDefaultCreateOptions,
212                                 nullptr, 100, &dispatcher1));
213 
214   scoped_refptr<SharedBufferDispatcher> dispatcher2;
215   EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::Create(
216                                 SharedBufferDispatcher::kDefaultCreateOptions,
217                                 nullptr, 100, &dispatcher2));
218 
219   MojoDuplicateBufferHandleOptions kReadOnlyOptions = {
220       sizeof(MojoCreateSharedBufferOptions),
221       MOJO_DUPLICATE_BUFFER_HANDLE_FLAG_READ_ONLY};
222 
223   // NOTE: We forbid handles from being duplicated read-only after they've been
224   // duplicated non-read-only; conversely we also forbid handles from being
225   // duplicated non-read-only after they've been duplicated read-only.
226   scoped_refptr<Dispatcher> writable_duped_dispatcher1;
227   scoped_refptr<Dispatcher> read_only_duped_dispatcher1;
228   EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->DuplicateBufferHandle(
229                                 nullptr, &writable_duped_dispatcher1));
230   EXPECT_TRUE(writable_duped_dispatcher1);
231   EXPECT_EQ(Dispatcher::Type::SHARED_BUFFER,
232             writable_duped_dispatcher1->GetType());
233   {
234     std::unique_ptr<PlatformSharedMemoryMapping> mapping;
235     EXPECT_EQ(MOJO_RESULT_OK,
236               writable_duped_dispatcher1->MapBuffer(0, 100, &mapping));
237   }
238   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
239             dispatcher1->DuplicateBufferHandle(&kReadOnlyOptions,
240                                                &read_only_duped_dispatcher1));
241   EXPECT_FALSE(read_only_duped_dispatcher1);
242 
243   scoped_refptr<Dispatcher> read_only_duped_dispatcher2;
244   scoped_refptr<Dispatcher> writable_duped_dispatcher2;
245   EXPECT_EQ(MOJO_RESULT_OK,
246             dispatcher2->DuplicateBufferHandle(&kReadOnlyOptions,
247                                                &read_only_duped_dispatcher2));
248   EXPECT_TRUE(read_only_duped_dispatcher2);
249   EXPECT_EQ(Dispatcher::Type::SHARED_BUFFER,
250             read_only_duped_dispatcher2->GetType());
251   {
252     std::unique_ptr<PlatformSharedMemoryMapping> mapping;
253     EXPECT_EQ(MOJO_RESULT_OK,
254               read_only_duped_dispatcher2->MapBuffer(0, 100, &mapping));
255   }
256   EXPECT_EQ(
257       MOJO_RESULT_FAILED_PRECONDITION,
258       dispatcher2->DuplicateBufferHandle(nullptr, &writable_duped_dispatcher2));
259   EXPECT_FALSE(writable_duped_dispatcher2);
260 
261   EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->Close());
262   EXPECT_EQ(MOJO_RESULT_OK, writable_duped_dispatcher1->Close());
263   EXPECT_EQ(MOJO_RESULT_OK, dispatcher2->Close());
264   EXPECT_EQ(MOJO_RESULT_OK, read_only_duped_dispatcher2->Close());
265 }
266 
TEST_F(SharedBufferDispatcherTest,DuplicateBufferHandleOptionsInvalid)267 TEST_F(SharedBufferDispatcherTest, DuplicateBufferHandleOptionsInvalid) {
268   scoped_refptr<SharedBufferDispatcher> dispatcher1;
269   EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::Create(
270                                 SharedBufferDispatcher::kDefaultCreateOptions,
271                                 nullptr, 100, &dispatcher1));
272 
273   // Invalid |struct_size|.
274   {
275     MojoDuplicateBufferHandleOptions options = {
276         1u, MOJO_DUPLICATE_BUFFER_HANDLE_FLAG_NONE};
277     scoped_refptr<Dispatcher> dispatcher2;
278     EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
279               dispatcher1->DuplicateBufferHandle(&options, &dispatcher2));
280     EXPECT_FALSE(dispatcher2);
281   }
282 
283   // Unknown |flags|.
284   {
285     MojoDuplicateBufferHandleOptions options = {
286         sizeof(MojoDuplicateBufferHandleOptions), ~0u};
287     scoped_refptr<Dispatcher> dispatcher2;
288     EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED,
289               dispatcher1->DuplicateBufferHandle(&options, &dispatcher2));
290     EXPECT_FALSE(dispatcher2);
291   }
292 
293   EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->Close());
294 }
295 
TEST_F(SharedBufferDispatcherTest,CreateInvalidNumBytes)296 TEST_F(SharedBufferDispatcherTest, CreateInvalidNumBytes) {
297   // Size too big.
298   scoped_refptr<SharedBufferDispatcher> dispatcher;
299   EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED,
300             SharedBufferDispatcher::Create(
301                 SharedBufferDispatcher::kDefaultCreateOptions, nullptr,
302                 std::numeric_limits<uint64_t>::max(), &dispatcher));
303   EXPECT_FALSE(dispatcher);
304 
305   // Zero size.
306   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
307             SharedBufferDispatcher::Create(
308                 SharedBufferDispatcher::kDefaultCreateOptions, nullptr, 0,
309                 &dispatcher));
310   EXPECT_FALSE(dispatcher);
311 }
312 
TEST_F(SharedBufferDispatcherTest,MapBufferInvalidArguments)313 TEST_F(SharedBufferDispatcherTest, MapBufferInvalidArguments) {
314   scoped_refptr<SharedBufferDispatcher> dispatcher;
315   EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::Create(
316                                 SharedBufferDispatcher::kDefaultCreateOptions,
317                                 nullptr, 100, &dispatcher));
318 
319   MojoSharedBufferInfo info = {sizeof(info), 0u};
320   EXPECT_EQ(MOJO_RESULT_OK, dispatcher->GetBufferInfo(&info));
321 
322   std::unique_ptr<PlatformSharedMemoryMapping> mapping;
323   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
324             dispatcher->MapBuffer(0, info.size + 1, &mapping));
325   EXPECT_FALSE(mapping);
326 
327   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
328             dispatcher->MapBuffer(1, info.size, &mapping));
329   EXPECT_FALSE(mapping);
330 
331   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
332             dispatcher->MapBuffer(0, 0, &mapping));
333   EXPECT_FALSE(mapping);
334 
335   EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close());
336 }
337 
338 }  // namespace
339 }  // namespace core
340 }  // namespace mojo
341