diff options
Diffstat (limited to 'mojo/system/shared_buffer_dispatcher_unittest.cc')
-rw-r--r-- | mojo/system/shared_buffer_dispatcher_unittest.cc | 299 |
1 files changed, 299 insertions, 0 deletions
diff --git a/mojo/system/shared_buffer_dispatcher_unittest.cc b/mojo/system/shared_buffer_dispatcher_unittest.cc new file mode 100644 index 0000000..397040b --- /dev/null +++ b/mojo/system/shared_buffer_dispatcher_unittest.cc @@ -0,0 +1,299 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/system/shared_buffer_dispatcher.h" + +#include <limits> + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "mojo/embedder/platform_shared_buffer.h" +#include "mojo/embedder/simple_platform_support.h" +#include "mojo/system/dispatcher.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo { +namespace system { +namespace { + +// NOTE(vtl): There's currently not much to test for in +// |SharedBufferDispatcher::ValidateCreateOptions()|, but the tests should be +// expanded if/when options are added, so I've kept the general form of the +// tests from data_pipe_unittest.cc. + +const uint32_t kSizeOfCreateOptions = sizeof(MojoCreateSharedBufferOptions); + +// Does a cursory sanity check of |validated_options|. Calls +// |ValidateCreateOptions()| on already-validated options. The validated options +// should be valid, and the revalidated copy should be the same. +void RevalidateCreateOptions( + const MojoCreateSharedBufferOptions& validated_options) { + EXPECT_EQ(kSizeOfCreateOptions, validated_options.struct_size); + // Nothing to check for flags. + + MojoCreateSharedBufferOptions revalidated_options = {}; + EXPECT_EQ(MOJO_RESULT_OK, + SharedBufferDispatcher::ValidateCreateOptions( + MakeUserPointer(&validated_options), &revalidated_options)); + EXPECT_EQ(validated_options.struct_size, revalidated_options.struct_size); + EXPECT_EQ(validated_options.flags, revalidated_options.flags); +} + +class SharedBufferDispatcherTest : public testing::Test { + public: + SharedBufferDispatcherTest() {} + virtual ~SharedBufferDispatcherTest() {} + + embedder::PlatformSupport* platform_support() { return &platform_support_; } + + private: + embedder::SimplePlatformSupport platform_support_; + + DISALLOW_COPY_AND_ASSIGN(SharedBufferDispatcherTest); +}; + +// Tests valid inputs to |ValidateCreateOptions()|. +TEST_F(SharedBufferDispatcherTest, ValidateCreateOptionsValid) { + // Default options. + { + MojoCreateSharedBufferOptions validated_options = {}; + EXPECT_EQ(MOJO_RESULT_OK, + SharedBufferDispatcher::ValidateCreateOptions( + NullUserPointer(), &validated_options)); + RevalidateCreateOptions(validated_options); + } + + // Different flags. + MojoCreateSharedBufferOptionsFlags flags_values[] = { + MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE}; + for (size_t i = 0; i < arraysize(flags_values); i++) { + const MojoCreateSharedBufferOptionsFlags flags = flags_values[i]; + + // Different capacities (size 1). + for (uint32_t capacity = 1; capacity <= 100 * 1000 * 1000; capacity *= 10) { + MojoCreateSharedBufferOptions options = { + kSizeOfCreateOptions, // |struct_size|. + flags // |flags|. + }; + MojoCreateSharedBufferOptions validated_options = {}; + EXPECT_EQ(MOJO_RESULT_OK, + SharedBufferDispatcher::ValidateCreateOptions( + MakeUserPointer(&options), &validated_options)) + << capacity; + RevalidateCreateOptions(validated_options); + EXPECT_EQ(options.flags, validated_options.flags); + } + } +} + +TEST_F(SharedBufferDispatcherTest, ValidateCreateOptionsInvalid) { + // Invalid |struct_size|. + { + MojoCreateSharedBufferOptions options = { + 1, // |struct_size|. + MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE // |flags|. + }; + MojoCreateSharedBufferOptions unused; + EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, + SharedBufferDispatcher::ValidateCreateOptions( + MakeUserPointer(&options), &unused)); + } + + // Unknown |flags|. + { + MojoCreateSharedBufferOptions options = { + kSizeOfCreateOptions, // |struct_size|. + ~0u // |flags|. + }; + MojoCreateSharedBufferOptions unused; + EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED, + SharedBufferDispatcher::ValidateCreateOptions( + MakeUserPointer(&options), &unused)); + } +} + +TEST_F(SharedBufferDispatcherTest, CreateAndMapBuffer) { + scoped_refptr<SharedBufferDispatcher> dispatcher; + EXPECT_EQ(MOJO_RESULT_OK, + SharedBufferDispatcher::Create( + platform_support(), + SharedBufferDispatcher::kDefaultCreateOptions, + 100, + &dispatcher)); + ASSERT_TRUE(dispatcher.get()); + EXPECT_EQ(Dispatcher::kTypeSharedBuffer, dispatcher->GetType()); + + // Make a couple of mappings. + scoped_ptr<embedder::PlatformSharedBufferMapping> mapping1; + EXPECT_EQ( + MOJO_RESULT_OK, + dispatcher->MapBuffer(0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping1)); + ASSERT_TRUE(mapping1); + ASSERT_TRUE(mapping1->GetBase()); + EXPECT_EQ(100u, mapping1->GetLength()); + // Write something. + static_cast<char*>(mapping1->GetBase())[50] = 'x'; + + scoped_ptr<embedder::PlatformSharedBufferMapping> mapping2; + EXPECT_EQ( + MOJO_RESULT_OK, + dispatcher->MapBuffer(50, 50, MOJO_MAP_BUFFER_FLAG_NONE, &mapping2)); + ASSERT_TRUE(mapping2); + ASSERT_TRUE(mapping2->GetBase()); + EXPECT_EQ(50u, mapping2->GetLength()); + EXPECT_EQ('x', static_cast<char*>(mapping2->GetBase())[0]); + + EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close()); + + // Check that we can still read/write to mappings after the dispatcher has + // gone away. + static_cast<char*>(mapping2->GetBase())[1] = 'y'; + EXPECT_EQ('y', static_cast<char*>(mapping1->GetBase())[51]); +} + +TEST_F(SharedBufferDispatcherTest, DuplicateBufferHandle) { + scoped_refptr<SharedBufferDispatcher> dispatcher1; + EXPECT_EQ(MOJO_RESULT_OK, + SharedBufferDispatcher::Create( + platform_support(), + SharedBufferDispatcher::kDefaultCreateOptions, + 100, + &dispatcher1)); + + // Map and write something. + scoped_ptr<embedder::PlatformSharedBufferMapping> mapping; + EXPECT_EQ( + MOJO_RESULT_OK, + dispatcher1->MapBuffer(0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping)); + static_cast<char*>(mapping->GetBase())[0] = 'x'; + mapping.reset(); + + // Duplicate |dispatcher1| and then close it. + scoped_refptr<Dispatcher> dispatcher2; + EXPECT_EQ( + MOJO_RESULT_OK, + dispatcher1->DuplicateBufferHandle(NullUserPointer(), &dispatcher2)); + ASSERT_TRUE(dispatcher2.get()); + EXPECT_EQ(Dispatcher::kTypeSharedBuffer, dispatcher2->GetType()); + + EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->Close()); + + // Map |dispatcher2| and read something. + EXPECT_EQ( + MOJO_RESULT_OK, + dispatcher2->MapBuffer(0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping)); + EXPECT_EQ('x', static_cast<char*>(mapping->GetBase())[0]); + + EXPECT_EQ(MOJO_RESULT_OK, dispatcher2->Close()); +} + +TEST_F(SharedBufferDispatcherTest, DuplicateBufferHandleOptionsValid) { + scoped_refptr<SharedBufferDispatcher> dispatcher1; + EXPECT_EQ(MOJO_RESULT_OK, + SharedBufferDispatcher::Create( + platform_support(), + SharedBufferDispatcher::kDefaultCreateOptions, + 100, + &dispatcher1)); + + MojoDuplicateBufferHandleOptions options[] = { + {sizeof(MojoDuplicateBufferHandleOptions), + MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE}, + {sizeof(MojoDuplicateBufferHandleOptionsFlags), ~0u}}; + for (size_t i = 0; i < arraysize(options); i++) { + scoped_refptr<Dispatcher> dispatcher2; + EXPECT_EQ(MOJO_RESULT_OK, + dispatcher1->DuplicateBufferHandle(MakeUserPointer(&options[i]), + &dispatcher2)); + ASSERT_TRUE(dispatcher2.get()); + EXPECT_EQ(Dispatcher::kTypeSharedBuffer, dispatcher2->GetType()); + EXPECT_EQ(MOJO_RESULT_OK, dispatcher2->Close()); + } + + EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->Close()); +} + +TEST_F(SharedBufferDispatcherTest, DuplicateBufferHandleOptionsInvalid) { + scoped_refptr<SharedBufferDispatcher> dispatcher1; + EXPECT_EQ(MOJO_RESULT_OK, + SharedBufferDispatcher::Create( + platform_support(), + SharedBufferDispatcher::kDefaultCreateOptions, + 100, + &dispatcher1)); + + // Invalid |struct_size|. + { + MojoDuplicateBufferHandleOptions options = { + 1u, MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE}; + scoped_refptr<Dispatcher> dispatcher2; + EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, + dispatcher1->DuplicateBufferHandle(MakeUserPointer(&options), + &dispatcher2)); + EXPECT_FALSE(dispatcher2.get()); + } + + // Unknown |flags|. + { + MojoDuplicateBufferHandleOptions options = { + sizeof(MojoDuplicateBufferHandleOptions), ~0u}; + scoped_refptr<Dispatcher> dispatcher2; + EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED, + dispatcher1->DuplicateBufferHandle(MakeUserPointer(&options), + &dispatcher2)); + EXPECT_FALSE(dispatcher2.get()); + } + + EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->Close()); +} + +TEST_F(SharedBufferDispatcherTest, CreateInvalidNumBytes) { + // Size too big. + scoped_refptr<SharedBufferDispatcher> dispatcher; + EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, + SharedBufferDispatcher::Create( + platform_support(), + SharedBufferDispatcher::kDefaultCreateOptions, + std::numeric_limits<uint64_t>::max(), + &dispatcher)); + EXPECT_FALSE(dispatcher.get()); + + // Zero size. + EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, + SharedBufferDispatcher::Create( + platform_support(), + SharedBufferDispatcher::kDefaultCreateOptions, + 0, + &dispatcher)); + EXPECT_FALSE(dispatcher.get()); +} + +TEST_F(SharedBufferDispatcherTest, MapBufferInvalidArguments) { + scoped_refptr<SharedBufferDispatcher> dispatcher; + EXPECT_EQ(MOJO_RESULT_OK, + SharedBufferDispatcher::Create( + platform_support(), + SharedBufferDispatcher::kDefaultCreateOptions, + 100, + &dispatcher)); + + scoped_ptr<embedder::PlatformSharedBufferMapping> mapping; + EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, + dispatcher->MapBuffer(0, 101, MOJO_MAP_BUFFER_FLAG_NONE, &mapping)); + EXPECT_FALSE(mapping); + + EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, + dispatcher->MapBuffer(1, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping)); + EXPECT_FALSE(mapping); + + EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, + dispatcher->MapBuffer(0, 0, MOJO_MAP_BUFFER_FLAG_NONE, &mapping)); + EXPECT_FALSE(mapping); + + EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close()); +} + +} // namespace +} // namespace system +} // namespace mojo |