Home | History | Annotate | Download | only in system
      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