OLD | NEW |
| (Empty) |
1 // Copyright 2015 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 "blimp/net/blimp_message_output_buffer.h" | |
6 | |
7 #include "base/callback_helpers.h" | |
8 #include "base/logging.h" | |
9 #include "base/memory/ptr_util.h" | |
10 #include "base/message_loop/message_loop.h" | |
11 #include "blimp/common/proto/blimp_message.pb.h" | |
12 #include "blimp/net/test_common.h" | |
13 #include "net/base/net_errors.h" | |
14 #include "net/base/test_completion_callback.h" | |
15 #include "testing/gmock/include/gmock/gmock.h" | |
16 #include "testing/gtest/include/gtest/gtest.h" | |
17 | |
18 using testing::_; | |
19 using testing::InvokeArgument; | |
20 using testing::Ref; | |
21 using testing::Return; | |
22 using testing::SaveArg; | |
23 | |
24 namespace blimp { | |
25 namespace { | |
26 | |
27 class BlimpMessageOutputBufferTest : public testing::Test { | |
28 public: | |
29 BlimpMessageOutputBufferTest() {} | |
30 | |
31 void SetUp() override { | |
32 input_msg_.mutable_input(); | |
33 input_msg_.set_message_id(1); | |
34 compositor_msg_.mutable_compositor(); | |
35 compositor_msg_.set_message_id(2); | |
36 | |
37 // Buffer should only have space for two unacknowledged messages | |
38 // (with message IDs). | |
39 ASSERT_EQ(input_msg_.ByteSize(), compositor_msg_.ByteSize()); | |
40 buffer_.reset(new BlimpMessageOutputBuffer(2 * input_msg_.GetCachedSize())); | |
41 } | |
42 | |
43 protected: | |
44 void AddOutputExpectation(const BlimpMessage& msg) { | |
45 EXPECT_CALL(output_processor_, MockableProcessMessage(EqualsProto(msg), _)) | |
46 .WillOnce(SaveArg<1>(&captured_cb_)) | |
47 .RetiresOnSaturation(); | |
48 } | |
49 | |
50 BlimpMessage WithMessageId(const BlimpMessage& message, int64_t message_id) { | |
51 BlimpMessage output = message; | |
52 output.set_message_id(message_id); | |
53 return output; | |
54 } | |
55 | |
56 BlimpMessage input_msg_; | |
57 BlimpMessage compositor_msg_; | |
58 | |
59 base::MessageLoop message_loop_; | |
60 net::CompletionCallback captured_cb_; | |
61 MockBlimpMessageProcessor output_processor_; | |
62 std::unique_ptr<BlimpMessageOutputBuffer> buffer_; | |
63 testing::InSequence s; | |
64 }; | |
65 | |
66 // Verify batched writes and acknowledgements. | |
67 TEST_F(BlimpMessageOutputBufferTest, SeparatelyBufferWriteAck) { | |
68 net::TestCompletionCallback complete_cb_1; | |
69 net::TestCompletionCallback complete_cb_2; | |
70 | |
71 AddOutputExpectation(input_msg_); | |
72 AddOutputExpectation(compositor_msg_); | |
73 | |
74 // Accumulate two messages. | |
75 buffer_->ProcessMessage(base::WrapUnique(new BlimpMessage(input_msg_)), | |
76 complete_cb_1.callback()); | |
77 buffer_->ProcessMessage(base::WrapUnique(new BlimpMessage(compositor_msg_)), | |
78 complete_cb_2.callback()); | |
79 ASSERT_EQ(2, buffer_->GetBufferByteSizeForTest()); | |
80 | |
81 // Write two messages. | |
82 ASSERT_TRUE(captured_cb_.is_null()); | |
83 buffer_->SetOutputProcessor(&output_processor_); | |
84 ASSERT_FALSE(captured_cb_.is_null()); | |
85 base::ResetAndReturn(&captured_cb_).Run(net::OK); | |
86 ASSERT_EQ(2, buffer_->GetBufferByteSizeForTest()); | |
87 ASSERT_EQ(1, buffer_->GetUnacknowledgedMessageCountForTest()); | |
88 base::ResetAndReturn(&captured_cb_).Run(net::OK); | |
89 ASSERT_EQ(2, buffer_->GetBufferByteSizeForTest()); | |
90 ASSERT_EQ(2, buffer_->GetUnacknowledgedMessageCountForTest()); | |
91 | |
92 // Both messages are acknowledged by separate checkpoints. | |
93 buffer_->OnMessageCheckpoint(1); | |
94 ASSERT_EQ(1, buffer_->GetBufferByteSizeForTest()); | |
95 ASSERT_EQ(1, buffer_->GetUnacknowledgedMessageCountForTest()); | |
96 EXPECT_EQ(net::OK, complete_cb_1.WaitForResult()); | |
97 buffer_->OnMessageCheckpoint(2); | |
98 ASSERT_EQ(0, buffer_->GetBufferByteSizeForTest()); | |
99 ASSERT_EQ(0, buffer_->GetUnacknowledgedMessageCountForTest()); | |
100 EXPECT_EQ(net::OK, complete_cb_2.WaitForResult()); | |
101 } | |
102 | |
103 // Verify buffer writes from an empty state. | |
104 TEST_F(BlimpMessageOutputBufferTest, WritesFromEmptyBuffer) { | |
105 net::TestCompletionCallback complete_cb_1; | |
106 net::TestCompletionCallback complete_cb_2; | |
107 | |
108 AddOutputExpectation(input_msg_); | |
109 AddOutputExpectation(compositor_msg_); | |
110 | |
111 ASSERT_TRUE(captured_cb_.is_null()); | |
112 buffer_->SetOutputProcessor(&output_processor_); | |
113 | |
114 // Message #0 is buffered, sent, acknowledged. | |
115 buffer_->ProcessMessage(base::WrapUnique(new BlimpMessage(input_msg_)), | |
116 complete_cb_1.callback()); | |
117 ASSERT_EQ(1, buffer_->GetBufferByteSizeForTest()); | |
118 ASSERT_FALSE(captured_cb_.is_null()); | |
119 base::ResetAndReturn(&captured_cb_).Run(net::OK); | |
120 ASSERT_EQ(1, buffer_->GetBufferByteSizeForTest()); | |
121 ASSERT_EQ(1, buffer_->GetUnacknowledgedMessageCountForTest()); | |
122 buffer_->OnMessageCheckpoint(1); | |
123 ASSERT_EQ(0, buffer_->GetBufferByteSizeForTest()); | |
124 ASSERT_EQ(0, buffer_->GetUnacknowledgedMessageCountForTest()); | |
125 | |
126 buffer_->ProcessMessage(base::WrapUnique(new BlimpMessage(compositor_msg_)), | |
127 complete_cb_2.callback()); | |
128 ASSERT_EQ(1, buffer_->GetBufferByteSizeForTest()); | |
129 ASSERT_FALSE(captured_cb_.is_null()); | |
130 base::ResetAndReturn(&captured_cb_).Run(net::OK); | |
131 ASSERT_EQ(1, buffer_->GetBufferByteSizeForTest()); | |
132 ASSERT_EQ(1, buffer_->GetUnacknowledgedMessageCountForTest()); | |
133 buffer_->OnMessageCheckpoint(2); | |
134 ASSERT_EQ(0, buffer_->GetBufferByteSizeForTest()); | |
135 ASSERT_EQ(0, buffer_->GetUnacknowledgedMessageCountForTest()); | |
136 } | |
137 | |
138 // Verify that a single checkpoint can be used to acknowledge two writes. | |
139 TEST_F(BlimpMessageOutputBufferTest, SharedCheckpoint) { | |
140 net::TestCompletionCallback complete_cb_1; | |
141 net::TestCompletionCallback complete_cb_2; | |
142 | |
143 AddOutputExpectation(input_msg_); | |
144 AddOutputExpectation(compositor_msg_); | |
145 | |
146 // Message #1 is written but unacknowledged. | |
147 buffer_->ProcessMessage(base::WrapUnique(new BlimpMessage(input_msg_)), | |
148 complete_cb_1.callback()); | |
149 ASSERT_EQ(1, buffer_->GetBufferByteSizeForTest()); | |
150 ASSERT_TRUE(captured_cb_.is_null()); | |
151 buffer_->SetOutputProcessor(&output_processor_); | |
152 ASSERT_FALSE(captured_cb_.is_null()); | |
153 base::ResetAndReturn(&captured_cb_).Run(net::OK); | |
154 ASSERT_EQ(1, buffer_->GetBufferByteSizeForTest()); | |
155 ASSERT_EQ(1, buffer_->GetUnacknowledgedMessageCountForTest()); | |
156 | |
157 // Message #2 is written but unacknowledged. | |
158 buffer_->ProcessMessage(base::WrapUnique(new BlimpMessage(compositor_msg_)), | |
159 complete_cb_2.callback()); | |
160 ASSERT_EQ(2, buffer_->GetBufferByteSizeForTest()); | |
161 ASSERT_FALSE(captured_cb_.is_null()); | |
162 base::ResetAndReturn(&captured_cb_).Run(net::OK); | |
163 ASSERT_TRUE(captured_cb_.is_null()); | |
164 ASSERT_EQ(2, buffer_->GetBufferByteSizeForTest()); | |
165 ASSERT_EQ(2, buffer_->GetUnacknowledgedMessageCountForTest()); | |
166 | |
167 // Both messages are acknowledged in one checkpoint. | |
168 buffer_->OnMessageCheckpoint(2); | |
169 ASSERT_EQ(0, buffer_->GetBufferByteSizeForTest()); | |
170 ASSERT_EQ(0, buffer_->GetUnacknowledgedMessageCountForTest()); | |
171 EXPECT_EQ(net::OK, complete_cb_1.WaitForResult()); | |
172 EXPECT_EQ(net::OK, complete_cb_2.WaitForResult()); | |
173 } | |
174 | |
175 // Verify that messages that fail to write are kept in a pending write state. | |
176 TEST_F(BlimpMessageOutputBufferTest, WriteError) { | |
177 net::TestCompletionCallback complete_cb_1; | |
178 net::TestCompletionCallback complete_cb_2; | |
179 | |
180 AddOutputExpectation(input_msg_); | |
181 AddOutputExpectation(input_msg_); | |
182 | |
183 // Accumulate two messages. | |
184 buffer_->ProcessMessage(base::WrapUnique(new BlimpMessage(input_msg_)), | |
185 complete_cb_1.callback()); | |
186 ASSERT_EQ(1, buffer_->GetBufferByteSizeForTest()); | |
187 | |
188 // First write attempt, which fails. | |
189 ASSERT_TRUE(captured_cb_.is_null()); | |
190 buffer_->SetOutputProcessor(&output_processor_); | |
191 ASSERT_FALSE(captured_cb_.is_null()); | |
192 base::ResetAndReturn(&captured_cb_).Run(net::ERR_FAILED); | |
193 ASSERT_EQ(1, buffer_->GetBufferByteSizeForTest()); | |
194 ASSERT_EQ(0, buffer_->GetUnacknowledgedMessageCountForTest()); | |
195 | |
196 // Simulate disconnect. | |
197 buffer_->SetOutputProcessor(nullptr); | |
198 | |
199 // Reconnect. Should immediately try to write the contents of the buffer. | |
200 buffer_->SetOutputProcessor(&output_processor_); | |
201 ASSERT_FALSE(captured_cb_.is_null()); | |
202 base::ResetAndReturn(&captured_cb_).Run(net::OK); | |
203 ASSERT_EQ(1, buffer_->GetBufferByteSizeForTest()); | |
204 ASSERT_EQ(1, buffer_->GetUnacknowledgedMessageCountForTest()); | |
205 buffer_->OnMessageCheckpoint(1); | |
206 ASSERT_EQ(0, buffer_->GetBufferByteSizeForTest()); | |
207 ASSERT_EQ(0, buffer_->GetUnacknowledgedMessageCountForTest()); | |
208 EXPECT_EQ(net::OK, complete_cb_1.WaitForResult()); | |
209 } | |
210 | |
211 // Verify that unacknowledged messages can be moved back to a pending write | |
212 // state (recovery after a lost connection.) | |
213 TEST_F(BlimpMessageOutputBufferTest, MessageRetransmit) { | |
214 net::TestCompletionCallback complete_cb_1; | |
215 net::TestCompletionCallback complete_cb_2; | |
216 | |
217 AddOutputExpectation(input_msg_); | |
218 AddOutputExpectation(compositor_msg_); | |
219 AddOutputExpectation(compositor_msg_); // Retransmitted message. | |
220 | |
221 // Accumulate two messages. | |
222 buffer_->ProcessMessage(base::WrapUnique(new BlimpMessage(input_msg_)), | |
223 complete_cb_1.callback()); | |
224 buffer_->ProcessMessage(base::WrapUnique(new BlimpMessage(compositor_msg_)), | |
225 complete_cb_2.callback()); | |
226 ASSERT_EQ(2, buffer_->GetBufferByteSizeForTest()); | |
227 | |
228 // Write two messages. | |
229 ASSERT_TRUE(captured_cb_.is_null()); | |
230 buffer_->SetOutputProcessor(&output_processor_); | |
231 ASSERT_FALSE(captured_cb_.is_null()); | |
232 base::ResetAndReturn(&captured_cb_).Run(net::OK); | |
233 ASSERT_EQ(2, buffer_->GetBufferByteSizeForTest()); | |
234 ASSERT_EQ(1, buffer_->GetUnacknowledgedMessageCountForTest()); | |
235 base::ResetAndReturn(&captured_cb_).Run(net::OK); | |
236 ASSERT_EQ(2, buffer_->GetBufferByteSizeForTest()); | |
237 ASSERT_EQ(2, buffer_->GetUnacknowledgedMessageCountForTest()); | |
238 | |
239 // Simulate disconnect & reconnect. | |
240 buffer_->SetOutputProcessor(nullptr); | |
241 buffer_->SetOutputProcessor(&output_processor_); | |
242 | |
243 // Remote end indicates that it only received message #0. | |
244 // Message #1 should be moved from an unacknowledged state to a pending write | |
245 // state. | |
246 ASSERT_TRUE(captured_cb_.is_null()); | |
247 buffer_->OnMessageCheckpoint(1); | |
248 buffer_->RetransmitBufferedMessages(); | |
249 ASSERT_FALSE(captured_cb_.is_null()); | |
250 ASSERT_EQ(1, buffer_->GetBufferByteSizeForTest()); | |
251 ASSERT_EQ(0, buffer_->GetUnacknowledgedMessageCountForTest()); | |
252 base::ResetAndReturn(&captured_cb_).Run(net::OK); | |
253 ASSERT_EQ(1, buffer_->GetUnacknowledgedMessageCountForTest()); | |
254 | |
255 // Remote end acknowledges #1, buffer should be empty. | |
256 buffer_->OnMessageCheckpoint(2); | |
257 ASSERT_EQ(0, buffer_->GetBufferByteSizeForTest()); | |
258 ASSERT_EQ(0, buffer_->GetUnacknowledgedMessageCountForTest()); | |
259 EXPECT_EQ(net::OK, complete_cb_2.WaitForResult()); | |
260 } | |
261 | |
262 } // namespace | |
263 } // namespace blimp | |
OLD | NEW |