| Index: mojo/public/cpp/bindings/tests/union_unittest.cc
|
| diff --git a/mojo/public/cpp/bindings/tests/union_unittest.cc b/mojo/public/cpp/bindings/tests/union_unittest.cc
|
| index aba7faa6fbeaf07ebe18f86cfe548c9bf9a98efe..ef9bac17f7319cba284ca8d3f5af89d862405bbd 100644
|
| --- a/mojo/public/cpp/bindings/tests/union_unittest.cc
|
| +++ b/mojo/public/cpp/bindings/tests/union_unittest.cc
|
| @@ -2,10 +2,14 @@
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| +#include "mojo/public/cpp/bindings/array.h"
|
| +#include "mojo/public/cpp/bindings/lib/array_internal.h"
|
| +#include "mojo/public/cpp/bindings/lib/array_serialization.h"
|
| #include "mojo/public/cpp/bindings/lib/bounds_checker.h"
|
| #include "mojo/public/cpp/bindings/lib/fixed_buffer.h"
|
| #include "mojo/public/cpp/bindings/string.h"
|
| #include "mojo/public/cpp/environment/environment.h"
|
| +#include "mojo/public/interfaces/bindings/tests/test_structs.mojom.h"
|
| #include "mojo/public/interfaces/bindings/tests/test_unions.mojom.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
|
|
| @@ -104,12 +108,12 @@ TEST(UnionTest, SerializationPod) {
|
| PodUnionPtr pod1(PodUnion::New());
|
| pod1->set_f_int8(10);
|
|
|
| - size_t size = GetSerializedSize_(pod1);
|
| + size_t size = GetSerializedSize_(pod1, false);
|
| EXPECT_EQ(16U, size);
|
|
|
| mojo::internal::FixedBuffer buf(size);
|
| - internal::PodUnion_Data* data;
|
| - Serialize_(pod1.Pass(), &buf, &data);
|
| + internal::PodUnion_Data* data = nullptr;
|
| + SerializeUnion_(pod1.Pass(), &buf, &data, false);
|
|
|
| PodUnionPtr pod2;
|
| Deserialize_(data, &pod2);
|
| @@ -119,27 +123,68 @@ TEST(UnionTest, SerializationPod) {
|
| EXPECT_EQ(pod2->which(), PodUnion::Tag::F_INT8);
|
| }
|
|
|
| -TEST(UnionTest, ValidationJustWorksPod) {
|
| +TEST(UnionTest, PodValidation) {
|
| PodUnionPtr pod(PodUnion::New());
|
| pod->set_f_int8(10);
|
|
|
| - size_t size = GetSerializedSize_(pod);
|
| + size_t size = GetSerializedSize_(pod, false);
|
| EXPECT_EQ(16U, size);
|
|
|
| mojo::internal::FixedBuffer buf(size);
|
| - internal::PodUnion_Data* data;
|
| - Serialize_(pod.Pass(), &buf, &data);
|
| + internal::PodUnion_Data* data = nullptr;
|
| + SerializeUnion_(pod.Pass(), &buf, &data, false);
|
| void* raw_buf = buf.Leak();
|
| mojo::internal::BoundsChecker bounds_checker(data,
|
| static_cast<uint32_t>(size), 0);
|
| - EXPECT_TRUE(internal::PodUnion_Data::Validate(raw_buf, &bounds_checker));
|
| + EXPECT_TRUE(
|
| + internal::PodUnion_Data::Validate(raw_buf, &bounds_checker, false));
|
| free(raw_buf);
|
| }
|
|
|
| +TEST(UnionTest, SerializeNotNull) {
|
| + PodUnionPtr pod(PodUnion::New());
|
| + pod->set_f_int8(0);
|
| + size_t size = GetSerializedSize_(pod, false);
|
| + mojo::internal::FixedBuffer buf(size);
|
| + internal::PodUnion_Data* data = nullptr;
|
| + SerializeUnion_(pod.Pass(), &buf, &data, false);
|
| + EXPECT_FALSE(data->is_null());
|
| +}
|
| +
|
| +TEST(UnionTest, SerializeIsNullInlined) {
|
| + PodUnionPtr pod;
|
| + size_t size = GetSerializedSize_(pod, false);
|
| + EXPECT_EQ(16U, size);
|
| + mojo::internal::FixedBuffer buf(size);
|
| + internal::PodUnion_Data* data = internal::PodUnion_Data::New(&buf);
|
| +
|
| + // Check that dirty output buffers are handled correctly by serialization.
|
| + data->size = 16U;
|
| + data->tag = PodUnion::Tag::F_UINT16;
|
| + data->data.f_f_int16 = 20;
|
| +
|
| + SerializeUnion_(pod.Pass(), &buf, &data, true);
|
| + EXPECT_TRUE(data->is_null());
|
| +
|
| + PodUnionPtr pod2;
|
| + Deserialize_(data, &pod2);
|
| + EXPECT_TRUE(pod2.is_null());
|
| +}
|
| +
|
| +TEST(UnionTest, SerializeIsNullNotInlined) {
|
| + PodUnionPtr pod;
|
| + size_t size = GetSerializedSize_(pod, false);
|
| + EXPECT_EQ(16U, size);
|
| + mojo::internal::FixedBuffer buf(size);
|
| + internal::PodUnion_Data* data = nullptr;
|
| + SerializeUnion_(pod.Pass(), &buf, &data, false);
|
| + EXPECT_EQ(nullptr, data);
|
| +}
|
| +
|
| TEST(UnionTest, NullValidation) {
|
| void* buf = nullptr;
|
| mojo::internal::BoundsChecker bounds_checker(buf, 0, 0);
|
| - EXPECT_TRUE(internal::PodUnion_Data::Validate(buf, &bounds_checker));
|
| + EXPECT_TRUE(internal::PodUnion_Data::Validate(buf, &bounds_checker, false));
|
| }
|
|
|
| TEST(UnionTest, OutOfAlignmentValidation) {
|
| @@ -154,7 +199,7 @@ TEST(UnionTest, OutOfAlignmentValidation) {
|
| reinterpret_cast<internal::PodUnion_Data*>(buf);
|
| mojo::internal::BoundsChecker bounds_checker(data,
|
| static_cast<uint32_t>(size), 0);
|
| - EXPECT_FALSE(internal::PodUnion_Data::Validate(buf, &bounds_checker));
|
| + EXPECT_FALSE(internal::PodUnion_Data::Validate(buf, &bounds_checker, false));
|
| free(raw_buf);
|
| }
|
|
|
| @@ -166,7 +211,8 @@ TEST(UnionTest, OOBValidation) {
|
| mojo::internal::BoundsChecker bounds_checker(data,
|
| static_cast<uint32_t>(size), 0);
|
| void* raw_buf = buf.Leak();
|
| - EXPECT_FALSE(internal::PodUnion_Data::Validate(raw_buf, &bounds_checker));
|
| + EXPECT_FALSE(
|
| + internal::PodUnion_Data::Validate(raw_buf, &bounds_checker, false));
|
| free(raw_buf);
|
| }
|
|
|
| @@ -179,7 +225,8 @@ TEST(UnionTest, UnknownTagValidation) {
|
| mojo::internal::BoundsChecker bounds_checker(data,
|
| static_cast<uint32_t>(size), 0);
|
| void* raw_buf = buf.Leak();
|
| - EXPECT_FALSE(internal::PodUnion_Data::Validate(raw_buf, &bounds_checker));
|
| + EXPECT_FALSE(
|
| + internal::PodUnion_Data::Validate(raw_buf, &bounds_checker, false));
|
| free(raw_buf);
|
| }
|
|
|
| @@ -222,10 +269,10 @@ TEST(UnionTest, StringSerialization) {
|
| String hello("hello world");
|
| pod1->set_f_string(hello);
|
|
|
| - size_t size = GetSerializedSize_(pod1);
|
| + size_t size = GetSerializedSize_(pod1, false);
|
| mojo::internal::FixedBuffer buf(size);
|
| - internal::ObjectUnion_Data* data;
|
| - Serialize_(pod1.Pass(), &buf, &data);
|
| + internal::ObjectUnion_Data* data = nullptr;
|
| + SerializeUnion_(pod1.Pass(), &buf, &data, false);
|
|
|
| ObjectUnionPtr pod2;
|
| Deserialize_(data, &pod2);
|
| @@ -234,7 +281,7 @@ TEST(UnionTest, StringSerialization) {
|
| EXPECT_EQ(pod2->which(), ObjectUnion::Tag::F_STRING);
|
| }
|
|
|
| -TEST(UnionTest, StringValidationNull) {
|
| +TEST(UnionTest, NullStringValidation) {
|
| Environment environment;
|
| size_t size = sizeof(internal::ObjectUnion_Data);
|
| mojo::internal::FixedBuffer buf(size);
|
| @@ -244,11 +291,12 @@ TEST(UnionTest, StringValidationNull) {
|
| mojo::internal::BoundsChecker bounds_checker(data,
|
| static_cast<uint32_t>(size), 0);
|
| void* raw_buf = buf.Leak();
|
| - EXPECT_FALSE(internal::ObjectUnion_Data::Validate(raw_buf, &bounds_checker));
|
| + EXPECT_FALSE(
|
| + internal::ObjectUnion_Data::Validate(raw_buf, &bounds_checker, false));
|
| free(raw_buf);
|
| }
|
|
|
| -TEST(UnionTest, StringValidationPointerOverflow) {
|
| +TEST(UnionTest, StringPointerOverflowValidation) {
|
| Environment environment;
|
| size_t size = sizeof(internal::ObjectUnion_Data);
|
| mojo::internal::FixedBuffer buf(size);
|
| @@ -258,11 +306,12 @@ TEST(UnionTest, StringValidationPointerOverflow) {
|
| mojo::internal::BoundsChecker bounds_checker(data,
|
| static_cast<uint32_t>(size), 0);
|
| void* raw_buf = buf.Leak();
|
| - EXPECT_FALSE(internal::ObjectUnion_Data::Validate(raw_buf, &bounds_checker));
|
| + EXPECT_FALSE(
|
| + internal::ObjectUnion_Data::Validate(raw_buf, &bounds_checker, false));
|
| free(raw_buf);
|
| }
|
|
|
| -TEST(UnionTest, StringValidationValidateString) {
|
| +TEST(UnionTest, StringValidateOOB) {
|
| Environment environment;
|
| size_t size = 32;
|
| mojo::internal::FixedBuffer buf(size);
|
| @@ -277,8 +326,203 @@ TEST(UnionTest, StringValidationValidateString) {
|
| array_header->num_elements = 20;
|
| mojo::internal::BoundsChecker bounds_checker(data, 32, 0);
|
| void* raw_buf = buf.Leak();
|
| - EXPECT_FALSE(internal::ObjectUnion_Data::Validate(raw_buf, &bounds_checker));
|
| + EXPECT_FALSE(
|
| + internal::ObjectUnion_Data::Validate(raw_buf, &bounds_checker, false));
|
| + free(raw_buf);
|
| +}
|
| +
|
| +// TODO(azani): Move back in array_unittest.cc when possible.
|
| +// Array tests
|
| +TEST(UnionTest, PodUnionInArray) {
|
| + SmallStructPtr small_struct(SmallStruct::New());
|
| + small_struct->pod_union_array = Array<PodUnionPtr>(2);
|
| + small_struct->pod_union_array[0] = PodUnion::New();
|
| + small_struct->pod_union_array[1] = PodUnion::New();
|
| +
|
| + small_struct->pod_union_array[0]->set_f_int8(10);
|
| + small_struct->pod_union_array[1]->set_f_int16(12);
|
| +
|
| + EXPECT_EQ(10, small_struct->pod_union_array[0]->get_f_int8());
|
| + EXPECT_EQ(12, small_struct->pod_union_array[1]->get_f_int16());
|
| +}
|
| +
|
| +TEST(UnionTest, PodUnionInArraySerialization) {
|
| + Environment environment;
|
| + Array<PodUnionPtr> array(2);
|
| + array[0] = PodUnion::New();
|
| + array[1] = PodUnion::New();
|
| +
|
| + array[0]->set_f_int8(10);
|
| + array[1]->set_f_int16(12);
|
| + EXPECT_EQ(2U, array.size());
|
| +
|
| + size_t size = GetSerializedSize_(array);
|
| + EXPECT_EQ(40U, size);
|
| +
|
| + mojo::internal::FixedBuffer buf(size);
|
| + mojo::internal::Array_Data<internal::PodUnion_Data>* data;
|
| + SerializeArray_<mojo::internal::ArrayValidateParams<
|
| + 0, false, mojo::internal::NoValidateParams>>(array.Pass(), &buf, &data);
|
| +
|
| + Array<PodUnionPtr> array2;
|
| + Deserialize_(data, &array2);
|
| +
|
| + EXPECT_EQ(2U, array2.size());
|
| +
|
| + EXPECT_EQ(10, array2[0]->get_f_int8());
|
| + EXPECT_EQ(12, array2[1]->get_f_int16());
|
| +}
|
| +
|
| +TEST(UnionTest, PodUnionInArraySerializationWithNull) {
|
| + Environment environment;
|
| + Array<PodUnionPtr> array(2);
|
| + array[0] = PodUnion::New();
|
| +
|
| + array[0]->set_f_int8(10);
|
| + EXPECT_EQ(2U, array.size());
|
| +
|
| + size_t size = GetSerializedSize_(array);
|
| + EXPECT_EQ(40U, size);
|
| +
|
| + mojo::internal::FixedBuffer buf(size);
|
| + mojo::internal::Array_Data<internal::PodUnion_Data>* data;
|
| + SerializeArray_<mojo::internal::ArrayValidateParams<
|
| + 0, true, mojo::internal::NoValidateParams>>(array.Pass(), &buf, &data);
|
| +
|
| + Array<PodUnionPtr> array2;
|
| + Deserialize_(data, &array2);
|
| +
|
| + EXPECT_EQ(2U, array2.size());
|
| +
|
| + EXPECT_EQ(10, array2[0]->get_f_int8());
|
| + EXPECT_TRUE(array2[1].is_null());
|
| +}
|
| +
|
| +// TODO(azani): Move back in struct_unittest.cc when possible.
|
| +// Struct tests
|
| +TEST(UnionTest, Clone_Union) {
|
| + Environment environment;
|
| + SmallStructPtr small_struct(SmallStruct::New());
|
| + small_struct->pod_union = PodUnion::New();
|
| + small_struct->pod_union->set_f_int8(10);
|
| +
|
| + SmallStructPtr clone = small_struct.Clone();
|
| + EXPECT_EQ(10, clone->pod_union->get_f_int8());
|
| +}
|
| +
|
| +// Serialization test of a struct with a union of plain old data.
|
| +TEST(UnionTest, Serialization_UnionOfPods) {
|
| + Environment environment;
|
| + SmallStructPtr small_struct(SmallStruct::New());
|
| + small_struct->pod_union = PodUnion::New();
|
| + small_struct->pod_union->set_f_int32(10);
|
| +
|
| + size_t size = GetSerializedSize_(small_struct);
|
| +
|
| + mojo::internal::FixedBuffer buf(size);
|
| + internal::SmallStruct_Data* data = nullptr;
|
| + Serialize_(small_struct.Pass(), &buf, &data);
|
| +
|
| + SmallStructPtr deserialized;
|
| + Deserialize_(data, &deserialized);
|
| +
|
| + EXPECT_EQ(10, deserialized->pod_union->get_f_int32());
|
| +}
|
| +
|
| +// Serialization test of a struct with a union of structs.
|
| +TEST(UnionTest, Serialization_UnionOfObjects) {
|
| + Environment environment;
|
| + SmallObjStructPtr obj_struct(SmallObjStruct::New());
|
| + obj_struct->obj_union = ObjectUnion::New();
|
| + String hello("hello world");
|
| + obj_struct->obj_union->set_f_string(hello);
|
| +
|
| + size_t size = GetSerializedSize_(obj_struct);
|
| +
|
| + mojo::internal::FixedBuffer buf(size);
|
| + internal::SmallObjStruct_Data* data = nullptr;
|
| + Serialize_(obj_struct.Pass(), &buf, &data);
|
| +
|
| + SmallObjStructPtr deserialized;
|
| + Deserialize_(data, &deserialized);
|
| +
|
| + EXPECT_EQ(hello, deserialized->obj_union->get_f_string());
|
| +}
|
| +
|
| +// Validation test of a struct with a union.
|
| +TEST(UnionTest, Validation_UnionsInStruct) {
|
| + Environment environment;
|
| + SmallStructPtr small_struct(SmallStruct::New());
|
| + small_struct->pod_union = PodUnion::New();
|
| + small_struct->pod_union->set_f_int32(10);
|
| +
|
| + size_t size = GetSerializedSize_(small_struct);
|
| +
|
| + mojo::internal::FixedBuffer buf(size);
|
| + internal::SmallStruct_Data* data = nullptr;
|
| + Serialize_(small_struct.Pass(), &buf, &data);
|
| +
|
| + void* raw_buf = buf.Leak();
|
| + mojo::internal::BoundsChecker bounds_checker(data, size, 0);
|
| + EXPECT_TRUE(internal::SmallStruct_Data::Validate(raw_buf, &bounds_checker));
|
| + free(raw_buf);
|
| +}
|
| +
|
| +// Validation test of a struct union fails due to unknown union tag.
|
| +TEST(UnionTest, Validation_PodUnionInStruct_Failure) {
|
| + Environment environment;
|
| + SmallStructPtr small_struct(SmallStruct::New());
|
| + small_struct->pod_union = PodUnion::New();
|
| + small_struct->pod_union->set_f_int32(10);
|
| +
|
| + size_t size = GetSerializedSize_(small_struct);
|
| +
|
| + mojo::internal::FixedBuffer buf(size);
|
| + internal::SmallStruct_Data* data = nullptr;
|
| + Serialize_(small_struct.Pass(), &buf, &data);
|
| + data->pod_union.tag = static_cast<internal::PodUnion_Data::PodUnion_Tag>(100);
|
| +
|
| + void* raw_buf = buf.Leak();
|
| + mojo::internal::BoundsChecker bounds_checker(data, size, 0);
|
| + EXPECT_FALSE(internal::SmallStruct_Data::Validate(raw_buf, &bounds_checker));
|
| free(raw_buf);
|
| }
|
| +
|
| +// Validation fails due to non-nullable null union in struct.
|
| +TEST(UnionTest, Validation_NullUnion_Failure) {
|
| + Environment environment;
|
| + SmallStructNonNullableUnionPtr small_struct(
|
| + SmallStructNonNullableUnion::New());
|
| +
|
| + size_t size = GetSerializedSize_(small_struct);
|
| +
|
| + mojo::internal::FixedBuffer buf(size);
|
| + internal::SmallStructNonNullableUnion_Data* data =
|
| + internal::SmallStructNonNullableUnion_Data::New(&buf);
|
| +
|
| + void* raw_buf = buf.Leak();
|
| + mojo::internal::BoundsChecker bounds_checker(data, size, 0);
|
| + EXPECT_FALSE(internal::SmallStructNonNullableUnion_Data::Validate(
|
| + raw_buf, &bounds_checker));
|
| + free(raw_buf);
|
| +}
|
| +
|
| +// Validation passes with nullable null union.
|
| +TEST(UnionTest, Validation_NullableUnion) {
|
| + Environment environment;
|
| + SmallStructPtr small_struct(SmallStruct::New());
|
| +
|
| + size_t size = GetSerializedSize_(small_struct);
|
| +
|
| + mojo::internal::FixedBuffer buf(size);
|
| + internal::SmallStruct_Data* data = nullptr;
|
| + Serialize_(small_struct.Pass(), &buf, &data);
|
| +
|
| + void* raw_buf = buf.Leak();
|
| + mojo::internal::BoundsChecker bounds_checker(data, size, 0);
|
| + EXPECT_TRUE(internal::SmallStruct_Data::Validate(raw_buf, &bounds_checker));
|
| + free(raw_buf);
|
| +}
|
| +
|
| } // namespace test
|
| } // namespace mojo
|
|
|