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