blob: 6aa2ce786d0134a44f07204ea74052510695fb73 [file] [log] [blame]
// 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