| // 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 <memory> |
| #include <string> |
| #include <unordered_map> |
| #include <vector> |
| |
| #include "base/message_loop/message_loop.h" |
| #include "mojo/public/cpp/bindings/binding.h" |
| #include "mojo/public/cpp/bindings/lib/fixed_buffer.h" |
| #include "mojo/public/cpp/bindings/lib/serialization.h" |
| #include "mojo/public/interfaces/bindings/tests/test_data_view.mojom.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace mojo { |
| namespace test { |
| namespace data_view { |
| namespace { |
| |
| class DataViewTest : public testing::Test { |
| private: |
| base::MessageLoop message_loop_; |
| }; |
| |
| struct DataViewHolder { |
| std::unique_ptr<TestStructDataView> data_view; |
| mojo::Message message; |
| mojo::internal::SerializationContext context; |
| }; |
| |
| std::unique_ptr<DataViewHolder> SerializeTestStruct(TestStructPtr input) { |
| auto result = std::make_unique<DataViewHolder>(); |
| result->message = Message(0, 0, 0, 0, nullptr); |
| internal::TestStruct_Data::BufferWriter writer; |
| mojo::internal::Serialize<TestStructDataView>( |
| input, result->message.payload_buffer(), &writer, &result->context); |
| result->data_view = |
| std::make_unique<TestStructDataView>(writer.data(), &result->context); |
| return result; |
| } |
| |
| class TestInterfaceImpl : public TestInterface { |
| public: |
| explicit TestInterfaceImpl(TestInterfaceRequest request) |
| : binding_(this, std::move(request)) {} |
| ~TestInterfaceImpl() override {} |
| |
| // TestInterface implementation: |
| void Echo(int32_t value, const EchoCallback& callback) override { |
| callback.Run(value); |
| } |
| |
| private: |
| Binding<TestInterface> binding_; |
| }; |
| |
| } // namespace |
| |
| TEST_F(DataViewTest, String) { |
| TestStructPtr obj(TestStruct::New()); |
| obj->f_string = "hello"; |
| |
| auto data_view_holder = SerializeTestStruct(std::move(obj)); |
| auto& data_view = *data_view_holder->data_view; |
| |
| StringDataView string_data_view; |
| data_view.GetFStringDataView(&string_data_view); |
| |
| ASSERT_FALSE(string_data_view.is_null()); |
| EXPECT_EQ(std::string("hello"), |
| std::string(string_data_view.storage(), string_data_view.size())); |
| } |
| |
| TEST_F(DataViewTest, NestedStruct) { |
| TestStructPtr obj(TestStruct::New()); |
| obj->f_struct = NestedStruct::New(); |
| obj->f_struct->f_int32 = 42; |
| |
| auto data_view_holder = SerializeTestStruct(std::move(obj)); |
| auto& data_view = *data_view_holder->data_view; |
| |
| NestedStructDataView struct_data_view; |
| data_view.GetFStructDataView(&struct_data_view); |
| |
| ASSERT_FALSE(struct_data_view.is_null()); |
| EXPECT_EQ(42, struct_data_view.f_int32()); |
| } |
| |
| TEST_F(DataViewTest, NativeStruct) { |
| TestStructPtr obj(TestStruct::New()); |
| obj->f_native_struct = native::NativeStruct::New(); |
| obj->f_native_struct->data = std::vector<uint8_t>({3, 2, 1}); |
| |
| auto data_view_holder = SerializeTestStruct(std::move(obj)); |
| auto& data_view = *data_view_holder->data_view; |
| |
| native::NativeStructDataView struct_data_view; |
| data_view.GetFNativeStructDataView(&struct_data_view); |
| |
| ArrayDataView<uint8_t> data_data_view; |
| struct_data_view.GetDataDataView(&data_data_view); |
| |
| ASSERT_FALSE(data_data_view.is_null()); |
| ASSERT_EQ(3u, data_data_view.size()); |
| EXPECT_EQ(3, data_data_view[0]); |
| EXPECT_EQ(2, data_data_view[1]); |
| EXPECT_EQ(1, data_data_view[2]); |
| EXPECT_EQ(3, *data_data_view.data()); |
| } |
| |
| TEST_F(DataViewTest, BoolArray) { |
| TestStructPtr obj(TestStruct::New()); |
| obj->f_bool_array = {true, false}; |
| |
| auto data_view_holder = SerializeTestStruct(std::move(obj)); |
| auto& data_view = *data_view_holder->data_view; |
| |
| ArrayDataView<bool> array_data_view; |
| data_view.GetFBoolArrayDataView(&array_data_view); |
| |
| ASSERT_FALSE(array_data_view.is_null()); |
| ASSERT_EQ(2u, array_data_view.size()); |
| EXPECT_TRUE(array_data_view[0]); |
| EXPECT_FALSE(array_data_view[1]); |
| } |
| |
| TEST_F(DataViewTest, IntegerArray) { |
| TestStructPtr obj(TestStruct::New()); |
| obj->f_int32_array = {1024, 128}; |
| |
| auto data_view_holder = SerializeTestStruct(std::move(obj)); |
| auto& data_view = *data_view_holder->data_view; |
| |
| ArrayDataView<int32_t> array_data_view; |
| data_view.GetFInt32ArrayDataView(&array_data_view); |
| |
| ASSERT_FALSE(array_data_view.is_null()); |
| ASSERT_EQ(2u, array_data_view.size()); |
| EXPECT_EQ(1024, array_data_view[0]); |
| EXPECT_EQ(128, array_data_view[1]); |
| EXPECT_EQ(1024, *array_data_view.data()); |
| } |
| |
| TEST_F(DataViewTest, EnumArray) { |
| TestStructPtr obj(TestStruct::New()); |
| obj->f_enum_array = {TestEnum::VALUE_1, TestEnum::VALUE_0}; |
| |
| auto data_view_holder = SerializeTestStruct(std::move(obj)); |
| auto& data_view = *data_view_holder->data_view; |
| |
| ArrayDataView<TestEnum> array_data_view; |
| data_view.GetFEnumArrayDataView(&array_data_view); |
| |
| ASSERT_FALSE(array_data_view.is_null()); |
| ASSERT_EQ(2u, array_data_view.size()); |
| EXPECT_EQ(TestEnum::VALUE_1, array_data_view[0]); |
| EXPECT_EQ(TestEnum::VALUE_0, array_data_view[1]); |
| EXPECT_EQ(TestEnum::VALUE_0, *(array_data_view.data() + 1)); |
| |
| TestEnum output; |
| ASSERT_TRUE(array_data_view.Read(0, &output)); |
| EXPECT_EQ(TestEnum::VALUE_1, output); |
| } |
| |
| TEST_F(DataViewTest, InterfaceArray) { |
| TestInterfacePtrInfo ptr_info; |
| TestInterfaceImpl impl(MakeRequest(&ptr_info)); |
| |
| TestStructPtr obj(TestStruct::New()); |
| obj->f_interface_array.push_back(std::move(ptr_info)); |
| |
| auto data_view_holder = SerializeTestStruct(std::move(obj)); |
| auto& data_view = *data_view_holder->data_view; |
| |
| ArrayDataView<TestInterfacePtrDataView> array_data_view; |
| data_view.GetFInterfaceArrayDataView(&array_data_view); |
| |
| ASSERT_FALSE(array_data_view.is_null()); |
| ASSERT_EQ(1u, array_data_view.size()); |
| |
| TestInterfacePtr ptr2 = array_data_view.Take<TestInterfacePtr>(0); |
| ASSERT_TRUE(ptr2); |
| int32_t result = 0; |
| ASSERT_TRUE(ptr2->Echo(42, &result)); |
| EXPECT_EQ(42, result); |
| } |
| |
| TEST_F(DataViewTest, NestedArray) { |
| TestStructPtr obj(TestStruct::New()); |
| obj->f_nested_array = {{3, 4}, {2}}; |
| |
| auto data_view_holder = SerializeTestStruct(std::move(obj)); |
| auto& data_view = *data_view_holder->data_view; |
| |
| ArrayDataView<ArrayDataView<int32_t>> array_data_view; |
| data_view.GetFNestedArrayDataView(&array_data_view); |
| |
| ASSERT_FALSE(array_data_view.is_null()); |
| ASSERT_EQ(2u, array_data_view.size()); |
| |
| ArrayDataView<int32_t> nested_array_data_view; |
| array_data_view.GetDataView(0, &nested_array_data_view); |
| ASSERT_FALSE(nested_array_data_view.is_null()); |
| ASSERT_EQ(2u, nested_array_data_view.size()); |
| EXPECT_EQ(4, nested_array_data_view[1]); |
| |
| std::vector<int32_t> vec; |
| ASSERT_TRUE(array_data_view.Read(1, &vec)); |
| ASSERT_EQ(1u, vec.size()); |
| EXPECT_EQ(2, vec[0]); |
| } |
| |
| TEST_F(DataViewTest, StructArray) { |
| NestedStructPtr nested_struct(NestedStruct::New()); |
| nested_struct->f_int32 = 42; |
| |
| TestStructPtr obj(TestStruct::New()); |
| obj->f_struct_array.push_back(std::move(nested_struct)); |
| |
| auto data_view_holder = SerializeTestStruct(std::move(obj)); |
| auto& data_view = *data_view_holder->data_view; |
| |
| ArrayDataView<NestedStructDataView> array_data_view; |
| data_view.GetFStructArrayDataView(&array_data_view); |
| |
| ASSERT_FALSE(array_data_view.is_null()); |
| ASSERT_EQ(1u, array_data_view.size()); |
| |
| NestedStructDataView struct_data_view; |
| array_data_view.GetDataView(0, &struct_data_view); |
| ASSERT_FALSE(struct_data_view.is_null()); |
| EXPECT_EQ(42, struct_data_view.f_int32()); |
| |
| NestedStructPtr nested_struct2; |
| ASSERT_TRUE(array_data_view.Read(0, &nested_struct2)); |
| ASSERT_TRUE(nested_struct2); |
| EXPECT_EQ(42, nested_struct2->f_int32); |
| } |
| |
| TEST_F(DataViewTest, Map) { |
| TestStructPtr obj(TestStruct::New()); |
| obj->f_map["1"] = 1; |
| obj->f_map["2"] = 2; |
| |
| auto data_view_holder = SerializeTestStruct(std::move(obj)); |
| auto& data_view = *data_view_holder->data_view; |
| |
| MapDataView<StringDataView, int32_t> map_data_view; |
| data_view.GetFMapDataView(&map_data_view); |
| |
| ASSERT_FALSE(map_data_view.is_null()); |
| ASSERT_EQ(2u, map_data_view.size()); |
| |
| ASSERT_FALSE(map_data_view.keys().is_null()); |
| ASSERT_EQ(2u, map_data_view.keys().size()); |
| |
| ASSERT_FALSE(map_data_view.values().is_null()); |
| ASSERT_EQ(2u, map_data_view.values().size()); |
| |
| std::vector<std::string> keys; |
| ASSERT_TRUE(map_data_view.ReadKeys(&keys)); |
| std::vector<int32_t> values; |
| ASSERT_TRUE(map_data_view.ReadValues(&values)); |
| |
| std::unordered_map<std::string, int32_t> map; |
| for (size_t i = 0; i < 2; ++i) |
| map[keys[i]] = values[i]; |
| |
| EXPECT_EQ(1, map["1"]); |
| EXPECT_EQ(2, map["2"]); |
| } |
| |
| TEST_F(DataViewTest, UnionArray) { |
| TestUnionPtr union_ptr(TestUnion::New()); |
| union_ptr->set_f_int32(1024); |
| |
| TestStructPtr obj(TestStruct::New()); |
| obj->f_union_array.push_back(std::move(union_ptr)); |
| |
| auto data_view_holder = SerializeTestStruct(std::move(obj)); |
| auto& data_view = *data_view_holder->data_view; |
| |
| ArrayDataView<TestUnionDataView> array_data_view; |
| data_view.GetFUnionArrayDataView(&array_data_view); |
| ASSERT_FALSE(array_data_view.is_null()); |
| ASSERT_EQ(1u, array_data_view.size()); |
| |
| TestUnionDataView union_data_view; |
| array_data_view.GetDataView(0, &union_data_view); |
| ASSERT_FALSE(union_data_view.is_null()); |
| |
| TestUnionPtr union_ptr2; |
| ASSERT_TRUE(array_data_view.Read(0, &union_ptr2)); |
| ASSERT_TRUE(union_ptr2->is_f_int32()); |
| EXPECT_EQ(1024, union_ptr2->get_f_int32()); |
| } |
| |
| } // namespace data_view |
| } // namespace test |
| } // namespace mojo |