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