| // Copyright 2013 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/data_pipe.h" |
| |
| #include <stddef.h> |
| |
| #include <limits> |
| |
| #include "base/basictypes.h" |
| #include "mojo/system/constants.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace mojo { |
| namespace system { |
| namespace { |
| |
| const uint32_t kSizeOfCreateOptions = |
| static_cast<uint32_t>(sizeof(MojoCreateDataPipeOptions)); |
| |
| // 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 MojoCreateDataPipeOptions& validated_options) { |
| EXPECT_EQ(kSizeOfCreateOptions, validated_options.struct_size); |
| // Nothing to check for flags. |
| EXPECT_GT(validated_options.element_num_bytes, 0u); |
| EXPECT_GT(validated_options.capacity_num_bytes, 0u); |
| EXPECT_EQ(0u, |
| validated_options.capacity_num_bytes % |
| validated_options.element_num_bytes); |
| |
| MojoCreateDataPipeOptions revalidated_options = {}; |
| EXPECT_EQ(MOJO_RESULT_OK, |
| DataPipe::ValidateCreateOptions(&validated_options, |
| &revalidated_options)); |
| EXPECT_EQ(validated_options.struct_size, revalidated_options.struct_size); |
| EXPECT_EQ(validated_options.element_num_bytes, |
| revalidated_options.element_num_bytes); |
| EXPECT_EQ(validated_options.capacity_num_bytes, |
| revalidated_options.capacity_num_bytes); |
| EXPECT_EQ(validated_options.flags, revalidated_options.flags); |
| } |
| |
| // Checks that a default-computed capacity is correct. (Does not duplicate the |
| // checks done by |RevalidateCreateOptions()|.) |
| void CheckDefaultCapacity(const MojoCreateDataPipeOptions& validated_options) { |
| EXPECT_LE(validated_options.capacity_num_bytes, |
| kDefaultDataPipeCapacityBytes); |
| EXPECT_GT(validated_options.capacity_num_bytes + |
| validated_options.element_num_bytes, |
| kDefaultDataPipeCapacityBytes); |
| } |
| |
| // Tests valid inputs to |ValidateCreateOptions()|. |
| TEST(DataPipeTest, ValidateCreateOptionsValid) { |
| // Default options. |
| { |
| MojoCreateDataPipeOptions validated_options = {}; |
| EXPECT_EQ(MOJO_RESULT_OK, |
| DataPipe::ValidateCreateOptions(NULL, &validated_options)); |
| RevalidateCreateOptions(validated_options); |
| CheckDefaultCapacity(validated_options); |
| } |
| |
| // Size member, but nothing beyond. |
| { |
| MojoCreateDataPipeOptions options = { |
| offsetof(MojoCreateDataPipeOptions, flags) // |struct_size|. |
| }; |
| MojoCreateDataPipeOptions validated_options = {}; |
| EXPECT_EQ(MOJO_RESULT_OK, |
| DataPipe::ValidateCreateOptions(&options, &validated_options)); |
| RevalidateCreateOptions(validated_options); |
| CheckDefaultCapacity(validated_options); |
| } |
| |
| // Different flags. |
| MojoCreateDataPipeOptionsFlags flags_values[] = { |
| MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, |
| MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD |
| }; |
| for (size_t i = 0; i < arraysize(flags_values); i++) { |
| const MojoCreateDataPipeOptionsFlags flags = flags_values[i]; |
| |
| // Flags member, but nothing beyond. |
| { |
| MojoCreateDataPipeOptions options = { |
| // |struct_size|. |
| offsetof(MojoCreateDataPipeOptions, element_num_bytes), |
| flags // |flags|. |
| }; |
| MojoCreateDataPipeOptions validated_options = {}; |
| EXPECT_EQ(MOJO_RESULT_OK, |
| DataPipe::ValidateCreateOptions(&options, &validated_options)); |
| RevalidateCreateOptions(validated_options); |
| EXPECT_EQ(options.flags, validated_options.flags); |
| CheckDefaultCapacity(validated_options); |
| } |
| |
| // Different capacities (size 1). |
| for (uint32_t capacity = 1; capacity <= 100 * 1000 * 1000; capacity *= 10) { |
| MojoCreateDataPipeOptions options = { |
| kSizeOfCreateOptions, // |struct_size|. |
| flags, // |flags|. |
| 1, // |element_num_bytes|. |
| capacity // |capacity_num_bytes|. |
| }; |
| MojoCreateDataPipeOptions validated_options = {}; |
| EXPECT_EQ(MOJO_RESULT_OK, |
| DataPipe::ValidateCreateOptions(&options, &validated_options)) |
| << capacity; |
| RevalidateCreateOptions(validated_options); |
| EXPECT_EQ(options.flags, validated_options.flags); |
| EXPECT_EQ(options.element_num_bytes, |
| validated_options.element_num_bytes); |
| EXPECT_EQ(options.capacity_num_bytes, |
| validated_options.capacity_num_bytes); |
| } |
| |
| // Small sizes. |
| for (uint32_t size = 1; size < 100; size++) { |
| // Different capacities. |
| for (uint32_t elements = 1; elements <= 1000 * 1000; elements *= 10) { |
| MojoCreateDataPipeOptions options = { |
| kSizeOfCreateOptions, // |struct_size|. |
| flags, // |flags|. |
| size, // |element_num_bytes|. |
| size * elements // |capacity_num_bytes|. |
| }; |
| MojoCreateDataPipeOptions validated_options = {}; |
| EXPECT_EQ(MOJO_RESULT_OK, |
| DataPipe::ValidateCreateOptions(&options, &validated_options)) |
| << size << ", " << elements; |
| RevalidateCreateOptions(validated_options); |
| EXPECT_EQ(options.flags, validated_options.flags); |
| EXPECT_EQ(options.element_num_bytes, |
| validated_options.element_num_bytes); |
| EXPECT_EQ(options.capacity_num_bytes, |
| validated_options.capacity_num_bytes); |
| } |
| |
| // Default capacity. |
| { |
| MojoCreateDataPipeOptions options = { |
| kSizeOfCreateOptions, // |struct_size|. |
| flags, // |flags|. |
| size, // |element_num_bytes|. |
| 0 // |capacity_num_bytes|. |
| }; |
| MojoCreateDataPipeOptions validated_options = {}; |
| EXPECT_EQ(MOJO_RESULT_OK, |
| DataPipe::ValidateCreateOptions(&options, &validated_options)) |
| << size; |
| RevalidateCreateOptions(validated_options); |
| EXPECT_EQ(options.flags, validated_options.flags); |
| EXPECT_EQ(options.element_num_bytes, |
| validated_options.element_num_bytes); |
| CheckDefaultCapacity(validated_options); |
| } |
| |
| // No capacity field. |
| { |
| MojoCreateDataPipeOptions options = { |
| // |struct_size|. |
| offsetof(MojoCreateDataPipeOptions, capacity_num_bytes), |
| flags, // |flags|. |
| size // |element_num_bytes|. |
| }; |
| MojoCreateDataPipeOptions validated_options = {}; |
| EXPECT_EQ(MOJO_RESULT_OK, |
| DataPipe::ValidateCreateOptions(&options, &validated_options)) |
| << size; |
| RevalidateCreateOptions(validated_options); |
| EXPECT_EQ(options.flags, validated_options.flags); |
| EXPECT_EQ(options.element_num_bytes, |
| validated_options.element_num_bytes); |
| CheckDefaultCapacity(validated_options); |
| } |
| } |
| |
| // Larger sizes. |
| for (uint32_t size = 100; size <= 100 * 1000; size *= 10) { |
| // Capacity of 1000 elements. |
| { |
| MojoCreateDataPipeOptions options = { |
| kSizeOfCreateOptions, // |struct_size|. |
| flags, // |flags|. |
| size, // |element_num_bytes|. |
| 1000 * size // |capacity_num_bytes|. |
| }; |
| MojoCreateDataPipeOptions validated_options = {}; |
| EXPECT_EQ(MOJO_RESULT_OK, |
| DataPipe::ValidateCreateOptions(&options, &validated_options)) |
| << size; |
| RevalidateCreateOptions(validated_options); |
| EXPECT_EQ(options.flags, validated_options.flags); |
| EXPECT_EQ(options.element_num_bytes, |
| validated_options.element_num_bytes); |
| EXPECT_EQ(options.capacity_num_bytes, |
| validated_options.capacity_num_bytes); |
| } |
| |
| // Default capacity. |
| { |
| MojoCreateDataPipeOptions options = { |
| kSizeOfCreateOptions, // |struct_size|. |
| flags, // |flags|. |
| size, // |element_num_bytes|. |
| 0 // |capacity_num_bytes|. |
| }; |
| MojoCreateDataPipeOptions validated_options = {}; |
| EXPECT_EQ(MOJO_RESULT_OK, |
| DataPipe::ValidateCreateOptions(&options, &validated_options)) |
| << size; |
| RevalidateCreateOptions(validated_options); |
| EXPECT_EQ(options.flags, validated_options.flags); |
| EXPECT_EQ(options.element_num_bytes, |
| validated_options.element_num_bytes); |
| CheckDefaultCapacity(validated_options); |
| } |
| |
| // No capacity field. |
| { |
| MojoCreateDataPipeOptions options = { |
| // |struct_size|. |
| offsetof(MojoCreateDataPipeOptions, capacity_num_bytes), |
| flags, // |flags|. |
| size // |element_num_bytes|. |
| }; |
| MojoCreateDataPipeOptions validated_options = {}; |
| EXPECT_EQ(MOJO_RESULT_OK, |
| DataPipe::ValidateCreateOptions(&options, &validated_options)) |
| << size; |
| RevalidateCreateOptions(validated_options); |
| EXPECT_EQ(options.flags, validated_options.flags); |
| EXPECT_EQ(options.element_num_bytes, |
| validated_options.element_num_bytes); |
| CheckDefaultCapacity(validated_options); |
| } |
| } |
| } |
| } |
| |
| TEST(DataPipeTest, ValidateCreateOptionsInvalid) { |
| // Invalid |struct_size|. |
| { |
| MojoCreateDataPipeOptions options = { |
| 1, // |struct_size|. |
| MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. |
| 1, // |element_num_bytes|. |
| 0 // |capacity_num_bytes|. |
| }; |
| MojoCreateDataPipeOptions unused; |
| EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, |
| DataPipe::ValidateCreateOptions(&options, &unused)); |
| } |
| |
| // Unknown |flags|. |
| { |
| MojoCreateDataPipeOptions options = { |
| kSizeOfCreateOptions, // |struct_size|. |
| ~0u, // |flags|. |
| 1, // |element_num_bytes|. |
| 0 // |capacity_num_bytes|. |
| }; |
| MojoCreateDataPipeOptions unused; |
| EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED, |
| DataPipe::ValidateCreateOptions(&options, &unused)); |
| } |
| |
| // Invalid |element_num_bytes|. |
| { |
| MojoCreateDataPipeOptions options = { |
| kSizeOfCreateOptions, // |struct_size|. |
| MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. |
| 0, // |element_num_bytes|. |
| 1000 // |capacity_num_bytes|. |
| }; |
| MojoCreateDataPipeOptions unused; |
| EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, |
| DataPipe::ValidateCreateOptions(&options, &unused)); |
| } |
| // |element_num_bytes| too big. |
| { |
| MojoCreateDataPipeOptions options = { |
| kSizeOfCreateOptions, // |struct_size|. |
| MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. |
| std::numeric_limits<uint32_t>::max(), // |element_num_bytes|. |
| std::numeric_limits<uint32_t>::max() // |capacity_num_bytes|. |
| }; |
| MojoCreateDataPipeOptions unused; |
| EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, |
| DataPipe::ValidateCreateOptions(&options, &unused)); |
| } |
| { |
| MojoCreateDataPipeOptions options = { |
| kSizeOfCreateOptions, // |struct_size|. |
| MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. |
| std::numeric_limits<uint32_t>::max() - 1000, // |element_num_bytes|. |
| std::numeric_limits<uint32_t>::max() - 1000 // |capacity_num_bytes|. |
| }; |
| MojoCreateDataPipeOptions unused; |
| EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, |
| DataPipe::ValidateCreateOptions(&options, &unused)); |
| } |
| |
| // Invalid |capacity_num_bytes|. |
| { |
| MojoCreateDataPipeOptions options = { |
| kSizeOfCreateOptions, // |struct_size|. |
| MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. |
| 2, // |element_num_bytes|. |
| 1 // |capacity_num_bytes|. |
| }; |
| MojoCreateDataPipeOptions unused; |
| EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, |
| DataPipe::ValidateCreateOptions(&options, &unused)); |
| } |
| { |
| MojoCreateDataPipeOptions options = { |
| kSizeOfCreateOptions, // |struct_size|. |
| MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. |
| 2, // |element_num_bytes|. |
| 111 // |capacity_num_bytes|. |
| }; |
| MojoCreateDataPipeOptions unused; |
| EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, |
| DataPipe::ValidateCreateOptions(&options, &unused)); |
| } |
| { |
| MojoCreateDataPipeOptions options = { |
| kSizeOfCreateOptions, // |struct_size|. |
| MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. |
| 5, // |element_num_bytes|. |
| 104 // |capacity_num_bytes|. |
| }; |
| MojoCreateDataPipeOptions unused; |
| EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, |
| DataPipe::ValidateCreateOptions(&options, &unused)); |
| } |
| // |capacity_num_bytes| too big. |
| { |
| MojoCreateDataPipeOptions options = { |
| kSizeOfCreateOptions, // |struct_size|. |
| MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|. |
| 8, // |element_num_bytes|. |
| 0xffff0000 // |capacity_num_bytes|. |
| }; |
| MojoCreateDataPipeOptions unused; |
| EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, |
| DataPipe::ValidateCreateOptions(&options, &unused)); |
| } |
| } |
| |
| } // namespace |
| } // namespace system |
| } // namespace mojo |