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:
LazySerializationTest()19 LazySerializationTest() {}
~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:
TestUnserializedStructImpl(test::TestUnserializedStructRequest request)30 explicit TestUnserializedStructImpl(
31 test::TestUnserializedStructRequest request)
32 : binding_(this, std::move(request)) {}
~TestUnserializedStructImpl()33 ~TestUnserializedStructImpl() override {}
34
35 // test::TestUnserializedStruct:
PassUnserializedStruct(const test::StructWithUnreachableTraitsImpl & s,const PassUnserializedStructCallback & callback)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:
ForceSerializeTesterImpl(test::ForceSerializeTesterRequest request)50 ForceSerializeTesterImpl(test::ForceSerializeTesterRequest request)
51 : binding_(this, std::move(request)) {}
52 ~ForceSerializeTesterImpl() override = default;
53
54 // test::ForceSerializeTester:
SendForceSerializedStruct(const test::StructForceSerializeImpl & s,const SendForceSerializedStructCallback & callback)55 void SendForceSerializedStruct(
56 const test::StructForceSerializeImpl& s,
57 const SendForceSerializedStructCallback& callback) override {
58 callback.Run(s);
59 }
60
SendNestedForceSerializedStruct(const test::StructNestedForceSerializeImpl & s,const SendNestedForceSerializedStructCallback & callback)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
TEST_F(LazySerializationTest,NeverSerialize)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
TEST_F(LazySerializationTest,ForceSerialize)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
TEST_F(LazySerializationTest,ForceSerializeNested)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