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