diff options
Diffstat (limited to 'mojo/public/cpp/bindings/tests/array_common_test.h')
-rw-r--r-- | mojo/public/cpp/bindings/tests/array_common_test.h | 392 |
1 files changed, 392 insertions, 0 deletions
diff --git a/mojo/public/cpp/bindings/tests/array_common_test.h b/mojo/public/cpp/bindings/tests/array_common_test.h new file mode 100644 index 0000000..19c0f6f --- /dev/null +++ b/mojo/public/cpp/bindings/tests/array_common_test.h @@ -0,0 +1,392 @@ +// Copyright 2016 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 <stddef.h> +#include <stdint.h> +#include <utility> + +#include "mojo/public/cpp/bindings/lib/array_internal.h" +#include "mojo/public/cpp/bindings/lib/fixed_buffer.h" +#include "mojo/public/cpp/bindings/lib/serialization.h" +#include "mojo/public/cpp/bindings/tests/container_test_util.h" +#include "mojo/public/interfaces/bindings/tests/test_structs.mojom.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo { +namespace test { + +// Common tests for both mojo::Array and mojo::WTFArray. +template <template <typename...> class ArrayType> +class ArrayCommonTest { + public: + // Tests null and empty arrays. + static void NullAndEmpty() { + ArrayType<char> array0; + EXPECT_TRUE(array0.empty()); + EXPECT_FALSE(array0.is_null()); + array0 = nullptr; + EXPECT_TRUE(array0.is_null()); + EXPECT_FALSE(array0.empty()); + + ArrayType<char> array1(nullptr); + EXPECT_TRUE(array1.is_null()); + EXPECT_FALSE(array1.empty()); + array1.SetToEmpty(); + EXPECT_TRUE(array1.empty()); + EXPECT_FALSE(array1.is_null()); + } + + // Tests that basic array operations work. + static void Basic() { + ArrayType<char> array(8); + for (size_t i = 0; i < array.size(); ++i) { + char val = static_cast<char>(i * 2); + array[i] = val; + EXPECT_EQ(val, array.at(i)); + } + } + + // Tests that basic ArrayType<bool> operations work. + static void Bool() { + ArrayType<bool> array(64); + for (size_t i = 0; i < array.size(); ++i) { + bool val = i % 3 == 0; + array[i] = val; + EXPECT_EQ(val, array.at(i)); + } + } + + // Tests that ArrayType<ScopedMessagePipeHandle> supports transferring + // handles. + static void Handle() { + MessagePipe pipe; + ArrayType<ScopedMessagePipeHandle> handles(2); + handles[0] = std::move(pipe.handle0); + handles[1].reset(pipe.handle1.release()); + + EXPECT_FALSE(pipe.handle0.is_valid()); + EXPECT_FALSE(pipe.handle1.is_valid()); + + ArrayType<ScopedMessagePipeHandle> handles2 = std::move(handles); + EXPECT_TRUE(handles2[0].is_valid()); + EXPECT_TRUE(handles2[1].is_valid()); + + ScopedMessagePipeHandle pipe_handle = std::move(handles2[0]); + EXPECT_TRUE(pipe_handle.is_valid()); + EXPECT_FALSE(handles2[0].is_valid()); + } + + // Tests that ArrayType<ScopedMessagePipeHandle> supports closing handles. + static void HandlesAreClosed() { + MessagePipe pipe; + MojoHandle pipe0_value = pipe.handle0.get().value(); + MojoHandle pipe1_value = pipe.handle0.get().value(); + + { + ArrayType<ScopedMessagePipeHandle> handles(2); + handles[0] = std::move(pipe.handle0); + handles[1].reset(pipe.handle0.release()); + } + + // We expect the pipes to have been closed. + EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(pipe0_value)); + EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(pipe1_value)); + } + + static void Clone() { + { + // Test POD. + ArrayType<int32_t> array(3); + for (size_t i = 0; i < array.size(); ++i) + array[i] = static_cast<int32_t>(i); + + ArrayType<int32_t> clone_array = array.Clone(); + EXPECT_EQ(array.size(), clone_array.size()); + for (size_t i = 0; i < array.size(); ++i) + EXPECT_EQ(array[i], clone_array[i]); + } + + { + // Test copyable object. + ArrayType<String> array(2); + array[0] = "hello"; + array[1] = "world"; + + ArrayType<String> clone_array = array.Clone(); + EXPECT_EQ(array.size(), clone_array.size()); + for (size_t i = 0; i < array.size(); ++i) + EXPECT_EQ(array[i], clone_array[i]); + } + + { + // Test struct. + ArrayType<RectPtr> array(2); + array[1] = Rect::New(); + array[1]->x = 1; + array[1]->y = 2; + array[1]->width = 3; + array[1]->height = 4; + + ArrayType<RectPtr> clone_array = array.Clone(); + EXPECT_EQ(array.size(), clone_array.size()); + EXPECT_TRUE(clone_array[0].is_null()); + EXPECT_EQ(array[1]->x, clone_array[1]->x); + EXPECT_EQ(array[1]->y, clone_array[1]->y); + EXPECT_EQ(array[1]->width, clone_array[1]->width); + EXPECT_EQ(array[1]->height, clone_array[1]->height); + } + + { + // Test array of array. + ArrayType<ArrayType<int8_t>> array(2); + array[0] = nullptr; + array[1] = ArrayType<int8_t>(2); + array[1][0] = 0; + array[1][1] = 1; + + ArrayType<ArrayType<int8_t>> clone_array = array.Clone(); + EXPECT_EQ(array.size(), clone_array.size()); + EXPECT_TRUE(clone_array[0].is_null()); + EXPECT_EQ(array[1].size(), clone_array[1].size()); + EXPECT_EQ(array[1][0], clone_array[1][0]); + EXPECT_EQ(array[1][1], clone_array[1][1]); + } + + { + // Test that array of handles still works although Clone() is not + // available. + ArrayType<ScopedMessagePipeHandle> array(10); + EXPECT_FALSE(array[0].is_valid()); + } + } + + static void Serialization_ArrayOfPOD() { + ArrayType<int32_t> array(4); + for (size_t i = 0; i < array.size(); ++i) + array[i] = static_cast<int32_t>(i); + + size_t size = GetSerializedSize_(array, nullptr); + EXPECT_EQ(8U + 4 * 4U, size); + + mojo::internal::FixedBufferForTesting buf(size); + mojo::internal::Array_Data<int32_t>* data; + mojo::internal::ArrayValidateParams validate_params(0, false, nullptr); + SerializeArray_(std::move(array), &buf, &data, &validate_params, nullptr); + + ArrayType<int32_t> array2; + Deserialize_(data, &array2, nullptr); + + EXPECT_EQ(4U, array2.size()); + for (size_t i = 0; i < array2.size(); ++i) + EXPECT_EQ(static_cast<int32_t>(i), array2[i]); + } + + static void Serialization_EmptyArrayOfPOD() { + ArrayType<int32_t> array; + size_t size = GetSerializedSize_(array, nullptr); + EXPECT_EQ(8U, size); + + mojo::internal::FixedBufferForTesting buf(size); + mojo::internal::Array_Data<int32_t>* data; + mojo::internal::ArrayValidateParams validate_params(0, false, nullptr); + SerializeArray_(std::move(array), &buf, &data, &validate_params, nullptr); + + ArrayType<int32_t> array2; + Deserialize_(data, &array2, nullptr); + EXPECT_EQ(0U, array2.size()); + } + + static void Serialization_ArrayOfArrayOfPOD() { + ArrayType<ArrayType<int32_t>> array(2); + for (size_t j = 0; j < array.size(); ++j) { + ArrayType<int32_t> inner(4); + for (size_t i = 0; i < inner.size(); ++i) + inner[i] = static_cast<int32_t>(i + (j * 10)); + array[j] = std::move(inner); + } + + size_t size = GetSerializedSize_(array, nullptr); + EXPECT_EQ(8U + 2 * 8U + 2 * (8U + 4 * 4U), size); + + mojo::internal::FixedBufferForTesting buf(size); + mojo::internal::Array_Data<mojo::internal::Array_Data<int32_t>*>* data; + mojo::internal::ArrayValidateParams validate_params( + 0, false, new mojo::internal::ArrayValidateParams(0, false, nullptr)); + SerializeArray_(std::move(array), &buf, &data, &validate_params, nullptr); + + ArrayType<ArrayType<int32_t>> array2; + Deserialize_(data, &array2, nullptr); + + EXPECT_EQ(2U, array2.size()); + for (size_t j = 0; j < array2.size(); ++j) { + const ArrayType<int32_t>& inner = array2[j]; + EXPECT_EQ(4U, inner.size()); + for (size_t i = 0; i < inner.size(); ++i) + EXPECT_EQ(static_cast<int32_t>(i + (j * 10)), inner[i]); + } + } + + static void Serialization_ArrayOfBool() { + ArrayType<bool> array(10); + for (size_t i = 0; i < array.size(); ++i) + array[i] = i % 2 ? true : false; + + size_t size = GetSerializedSize_(array, nullptr); + EXPECT_EQ(8U + 8U, size); + + mojo::internal::FixedBufferForTesting buf(size); + mojo::internal::Array_Data<bool>* data; + mojo::internal::ArrayValidateParams validate_params(0, false, nullptr); + SerializeArray_(std::move(array), &buf, &data, &validate_params, nullptr); + + ArrayType<bool> array2; + Deserialize_(data, &array2, nullptr); + + EXPECT_EQ(10U, array2.size()); + for (size_t i = 0; i < array2.size(); ++i) + EXPECT_EQ(i % 2 ? true : false, array2[i]); + } + + static void Serialization_ArrayOfString() { + ArrayType<String> array(10); + for (size_t i = 0; i < array.size(); ++i) { + char c = 'A' + static_cast<char>(i); + array[i] = String(&c, 1); + } + + size_t size = GetSerializedSize_(array, nullptr); + EXPECT_EQ(8U + // array header + 10 * 8U + // array payload (10 pointers) + 10 * (8U + // string header + 8U), // string length of 1 padded to 8 + size); + + mojo::internal::FixedBufferForTesting buf(size); + mojo::internal::Array_Data<mojo::internal::String_Data*>* data; + mojo::internal::ArrayValidateParams validate_params( + 0, false, new mojo::internal::ArrayValidateParams(0, false, nullptr)); + SerializeArray_(std::move(array), &buf, &data, &validate_params, nullptr); + + ArrayType<String> array2; + Deserialize_(data, &array2, nullptr); + + EXPECT_EQ(10U, array2.size()); + for (size_t i = 0; i < array2.size(); ++i) { + char c = 'A' + static_cast<char>(i); + EXPECT_EQ(String(&c, 1), array2[i]); + } + } + + static void Resize_Copyable() { + ASSERT_EQ(0u, CopyableType::num_instances()); + ArrayType<CopyableType> array(3); + std::vector<CopyableType*> value_ptrs; + value_ptrs.push_back(array[0].ptr()); + value_ptrs.push_back(array[1].ptr()); + + for (size_t i = 0; i < array.size(); i++) + array[i].ResetCopied(); + + array.resize(2); + ASSERT_EQ(2u, array.size()); + EXPECT_EQ(array.size(), CopyableType::num_instances()); + for (size_t i = 0; i < array.size(); i++) { + EXPECT_FALSE(array[i].copied()); + EXPECT_EQ(value_ptrs[i], array[i].ptr()); + } + + array.resize(3); + array[2].ResetCopied(); + ASSERT_EQ(3u, array.size()); + EXPECT_EQ(array.size(), CopyableType::num_instances()); + for (size_t i = 0; i < array.size(); i++) + EXPECT_FALSE(array[i].copied()); + value_ptrs.push_back(array[2].ptr()); + + size_t capacity = array.storage().capacity(); + array.resize(capacity); + ASSERT_EQ(capacity, array.size()); + EXPECT_EQ(array.size(), CopyableType::num_instances()); + for (size_t i = 0; i < 3; i++) + EXPECT_FALSE(array[i].copied()); + for (size_t i = 3; i < array.size(); i++) { + array[i].ResetCopied(); + value_ptrs.push_back(array[i].ptr()); + } + + array.resize(capacity + 2); + ASSERT_EQ(capacity + 2, array.size()); + EXPECT_EQ(array.size(), CopyableType::num_instances()); + for (size_t i = 0; i < capacity; i++) { + EXPECT_TRUE(array[i].copied()); + EXPECT_EQ(value_ptrs[i], array[i].ptr()); + } + array = nullptr; + EXPECT_EQ(0u, CopyableType::num_instances()); + EXPECT_FALSE(array); + array.resize(0); + EXPECT_EQ(0u, CopyableType::num_instances()); + EXPECT_TRUE(array); + } + + static void Resize_MoveOnly() { + ASSERT_EQ(0u, MoveOnlyType::num_instances()); + ArrayType<MoveOnlyType> array(3); + std::vector<MoveOnlyType*> value_ptrs; + value_ptrs.push_back(array[0].ptr()); + value_ptrs.push_back(array[1].ptr()); + + for (size_t i = 0; i < array.size(); i++) + EXPECT_FALSE(array[i].moved()); + + array.resize(2); + ASSERT_EQ(2u, array.size()); + EXPECT_EQ(array.size(), MoveOnlyType::num_instances()); + for (size_t i = 0; i < array.size(); i++) { + EXPECT_FALSE(array[i].moved()); + EXPECT_EQ(value_ptrs[i], array[i].ptr()); + } + + array.resize(3); + ASSERT_EQ(3u, array.size()); + EXPECT_EQ(array.size(), MoveOnlyType::num_instances()); + for (size_t i = 0; i < array.size(); i++) + EXPECT_FALSE(array[i].moved()); + value_ptrs.push_back(array[2].ptr()); + + size_t capacity = array.storage().capacity(); + array.resize(capacity); + ASSERT_EQ(capacity, array.size()); + EXPECT_EQ(array.size(), MoveOnlyType::num_instances()); + for (size_t i = 0; i < array.size(); i++) + EXPECT_FALSE(array[i].moved()); + for (size_t i = 3; i < array.size(); i++) + value_ptrs.push_back(array[i].ptr()); + + array.resize(capacity + 2); + ASSERT_EQ(capacity + 2, array.size()); + EXPECT_EQ(array.size(), MoveOnlyType::num_instances()); + for (size_t i = 0; i < capacity; i++) { + EXPECT_TRUE(array[i].moved()); + EXPECT_EQ(value_ptrs[i], array[i].ptr()); + } + for (size_t i = capacity; i < array.size(); i++) + EXPECT_FALSE(array[i].moved()); + + array = nullptr; + EXPECT_EQ(0u, MoveOnlyType::num_instances()); + EXPECT_FALSE(array); + array.resize(0); + EXPECT_EQ(0u, MoveOnlyType::num_instances()); + EXPECT_TRUE(array); + } +}; + +#define ARRAY_COMMON_TEST(ArrayType, test_name) \ + TEST_F(ArrayType##Test, test_name) { \ + ArrayCommonTest<ArrayType>::test_name(); \ + } + +} // namespace test +} // namespace mojo |