1 // Copyright 2017 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/macros.h" 6 #include "base/run_loop.h" 7 #include "base/test/bind_test_util.h" 8 #include "base/test/scoped_task_environment.h" 9 #include "mojo/public/cpp/bindings/binding.h" 10 #include "mojo/public/cpp/bindings/tests/bindings_test_base.h" 11 #include "mojo/public/interfaces/bindings/tests/struct_with_traits.mojom.h" 12 #include "testing/gtest/include/gtest/gtest.h" 13 14 namespace mojo { 15 namespace { 16 17 class LazySerializationTest : public testing::Test { 18 public: 19 LazySerializationTest() {} 20 ~LazySerializationTest() override {} 21 22 private: 23 base::test::ScopedTaskEnvironment task_environment_; 24 25 DISALLOW_COPY_AND_ASSIGN(LazySerializationTest); 26 }; 27 28 class TestUnserializedStructImpl : public test::TestUnserializedStruct { 29 public: 30 explicit TestUnserializedStructImpl( 31 test::TestUnserializedStructRequest request) 32 : binding_(this, std::move(request)) {} 33 ~TestUnserializedStructImpl() override {} 34 35 // test::TestUnserializedStruct: 36 void PassUnserializedStruct( 37 const test::StructWithUnreachableTraitsImpl& s, 38 const PassUnserializedStructCallback& callback) override { 39 callback.Run(s); 40 } 41 42 private: 43 mojo::Binding<test::TestUnserializedStruct> binding_; 44 45 DISALLOW_COPY_AND_ASSIGN(TestUnserializedStructImpl); 46 }; 47 48 class ForceSerializeTesterImpl : public test::ForceSerializeTester { 49 public: 50 ForceSerializeTesterImpl(test::ForceSerializeTesterRequest request) 51 : binding_(this, std::move(request)) {} 52 ~ForceSerializeTesterImpl() override = default; 53 54 // test::ForceSerializeTester: 55 void SendForceSerializedStruct( 56 const test::StructForceSerializeImpl& s, 57 const SendForceSerializedStructCallback& callback) override { 58 callback.Run(s); 59 } 60 61 void SendNestedForceSerializedStruct( 62 const test::StructNestedForceSerializeImpl& s, 63 const SendNestedForceSerializedStructCallback& callback) override { 64 callback.Run(s); 65 } 66 67 private: 68 Binding<test::ForceSerializeTester> binding_; 69 70 DISALLOW_COPY_AND_ASSIGN(ForceSerializeTesterImpl); 71 }; 72 73 TEST_F(LazySerializationTest, NeverSerialize) { 74 // Basic sanity check to ensure that no messages are serialized by default in 75 // environments where lazy serialization is supported, on an interface which 76 // supports lazy serialization, and where both ends of the interface are in 77 // the same process. 78 79 test::TestUnserializedStructPtr ptr; 80 TestUnserializedStructImpl impl(MakeRequest(&ptr)); 81 82 const int32_t kTestMagicNumber = 42; 83 84 test::StructWithUnreachableTraitsImpl data; 85 EXPECT_EQ(0, data.magic_number); 86 data.magic_number = kTestMagicNumber; 87 88 // Send our data over the pipe and wait for it to come back. The value should 89 // be preserved. We know the data was never serialized because the 90 // StructTraits for this type will DCHECK if executed in any capacity. 91 int received_number = 0; 92 base::RunLoop loop; 93 ptr->PassUnserializedStruct( 94 data, base::Bind( 95 [](base::RunLoop* loop, int* received_number, 96 const test::StructWithUnreachableTraitsImpl& passed) { 97 *received_number = passed.magic_number; 98 loop->Quit(); 99 }, 100 &loop, &received_number)); 101 loop.Run(); 102 EXPECT_EQ(kTestMagicNumber, received_number); 103 } 104 105 TEST_F(LazySerializationTest, ForceSerialize) { 106 // Verifies that the [force_serialize] attribute works as intended: i.e., even 107 // with lazy serialization enabled, messages which carry a force-serialized 108 // type will always serialize at call time. 109 110 test::ForceSerializeTesterPtr tester; 111 ForceSerializeTesterImpl impl(mojo::MakeRequest(&tester)); 112 113 constexpr int32_t kTestValue = 42; 114 115 base::RunLoop loop; 116 test::StructForceSerializeImpl in; 117 in.set_value(kTestValue); 118 EXPECT_FALSE(in.was_serialized()); 119 EXPECT_FALSE(in.was_deserialized()); 120 tester->SendForceSerializedStruct( 121 in, base::BindLambdaForTesting( 122 [&](const test::StructForceSerializeImpl& passed) { 123 EXPECT_EQ(kTestValue, passed.value()); 124 EXPECT_TRUE(passed.was_deserialized()); 125 EXPECT_FALSE(passed.was_serialized()); 126 loop.Quit(); 127 })); 128 EXPECT_TRUE(in.was_serialized()); 129 EXPECT_FALSE(in.was_deserialized()); 130 loop.Run(); 131 EXPECT_TRUE(in.was_serialized()); 132 EXPECT_FALSE(in.was_deserialized()); 133 } 134 135 TEST_F(LazySerializationTest, ForceSerializeNested) { 136 // Verifies that the [force_serialize] attribute works as intended in a nested 137 // context, i.e. when a force-serialized type is contained within a 138 // non-force-serialized type, 139 140 test::ForceSerializeTesterPtr tester; 141 ForceSerializeTesterImpl impl(mojo::MakeRequest(&tester)); 142 143 constexpr int32_t kTestValue = 42; 144 145 base::RunLoop loop; 146 test::StructNestedForceSerializeImpl in; 147 in.force().set_value(kTestValue); 148 EXPECT_FALSE(in.was_serialized()); 149 EXPECT_FALSE(in.was_deserialized()); 150 tester->SendNestedForceSerializedStruct( 151 in, base::BindLambdaForTesting( 152 [&](const test::StructNestedForceSerializeImpl& passed) { 153 EXPECT_EQ(kTestValue, passed.force().value()); 154 EXPECT_TRUE(passed.was_deserialized()); 155 EXPECT_FALSE(passed.was_serialized()); 156 loop.Quit(); 157 })); 158 EXPECT_TRUE(in.was_serialized()); 159 EXPECT_FALSE(in.was_deserialized()); 160 loop.Run(); 161 EXPECT_TRUE(in.was_serialized()); 162 EXPECT_FALSE(in.was_deserialized()); 163 } 164 165 } // namespace 166 } // namespace mojo 167