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. 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: 47 SharedBufferDispatcherTest() {} 48 ~SharedBufferDispatcherTest() override {} 49 50 private: 51 DISALLOW_COPY_AND_ASSIGN(SharedBufferDispatcherTest); 52 }; 53 54 // Tests valid inputs to |ValidateCreateOptions()|. 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 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 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 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 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 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 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 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 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