Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(222)

Side by Side Diff: mojo/public/cpp/bindings/tests/connector_unittest.cc

Issue 814543006: Move //mojo/{public, edk} underneath //third_party (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2013 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 <stdlib.h>
6 #include <string.h>
7
8 #include "mojo/public/cpp/bindings/lib/connector.h"
9 #include "mojo/public/cpp/bindings/lib/message_builder.h"
10 #include "mojo/public/cpp/bindings/lib/message_queue.h"
11 #include "mojo/public/cpp/environment/environment.h"
12 #include "mojo/public/cpp/system/macros.h"
13 #include "mojo/public/cpp/utility/run_loop.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 namespace mojo {
17 namespace test {
18 namespace {
19
20 class MessageAccumulator : public MessageReceiver {
21 public:
22 MessageAccumulator() {}
23
24 bool Accept(Message* message) override {
25 queue_.Push(message);
26 return true;
27 }
28
29 bool IsEmpty() const { return queue_.IsEmpty(); }
30
31 void Pop(Message* message) { queue_.Pop(message); }
32
33 private:
34 internal::MessageQueue queue_;
35 };
36
37 class ConnectorDeletingMessageAccumulator : public MessageAccumulator {
38 public:
39 ConnectorDeletingMessageAccumulator(internal::Connector** connector)
40 : connector_(connector) {}
41
42 bool Accept(Message* message) override {
43 delete *connector_;
44 *connector_ = 0;
45 return MessageAccumulator::Accept(message);
46 }
47
48 private:
49 internal::Connector** connector_;
50 };
51
52 class ReentrantMessageAccumulator : public MessageAccumulator {
53 public:
54 ReentrantMessageAccumulator(internal::Connector* connector)
55 : connector_(connector), number_of_calls_(0) {}
56
57 bool Accept(Message* message) override {
58 if (!MessageAccumulator::Accept(message))
59 return false;
60 number_of_calls_++;
61 if (number_of_calls_ == 1) {
62 return connector_->WaitForIncomingMessage();
63 }
64 return true;
65 }
66
67 int number_of_calls() { return number_of_calls_; }
68
69 private:
70 internal::Connector* connector_;
71 int number_of_calls_;
72 };
73
74 class ConnectorTest : public testing::Test {
75 public:
76 ConnectorTest() {}
77
78 void SetUp() override {
79 CreateMessagePipe(nullptr, &handle0_, &handle1_);
80 }
81
82 void TearDown() override {}
83
84 void AllocMessage(const char* text, Message* message) {
85 size_t payload_size = strlen(text) + 1; // Plus null terminator.
86 internal::MessageBuilder builder(1, payload_size);
87 memcpy(builder.buffer()->Allocate(payload_size), text, payload_size);
88 builder.Finish(message);
89 }
90
91 void PumpMessages() { loop_.RunUntilIdle(); }
92
93 protected:
94 ScopedMessagePipeHandle handle0_;
95 ScopedMessagePipeHandle handle1_;
96
97 private:
98 Environment env_;
99 RunLoop loop_;
100 };
101
102 TEST_F(ConnectorTest, Basic) {
103 internal::Connector connector0(handle0_.Pass());
104 internal::Connector connector1(handle1_.Pass());
105
106 const char kText[] = "hello world";
107
108 Message message;
109 AllocMessage(kText, &message);
110
111 connector0.Accept(&message);
112
113 MessageAccumulator accumulator;
114 connector1.set_incoming_receiver(&accumulator);
115
116 PumpMessages();
117
118 ASSERT_FALSE(accumulator.IsEmpty());
119
120 Message message_received;
121 accumulator.Pop(&message_received);
122
123 EXPECT_EQ(
124 std::string(kText),
125 std::string(reinterpret_cast<const char*>(message_received.payload())));
126 }
127
128 TEST_F(ConnectorTest, Basic_Synchronous) {
129 internal::Connector connector0(handle0_.Pass());
130 internal::Connector connector1(handle1_.Pass());
131
132 const char kText[] = "hello world";
133
134 Message message;
135 AllocMessage(kText, &message);
136
137 connector0.Accept(&message);
138
139 MessageAccumulator accumulator;
140 connector1.set_incoming_receiver(&accumulator);
141
142 connector1.WaitForIncomingMessage();
143
144 ASSERT_FALSE(accumulator.IsEmpty());
145
146 Message message_received;
147 accumulator.Pop(&message_received);
148
149 EXPECT_EQ(
150 std::string(kText),
151 std::string(reinterpret_cast<const char*>(message_received.payload())));
152 }
153
154 TEST_F(ConnectorTest, Basic_EarlyIncomingReceiver) {
155 internal::Connector connector0(handle0_.Pass());
156 internal::Connector connector1(handle1_.Pass());
157
158 MessageAccumulator accumulator;
159 connector1.set_incoming_receiver(&accumulator);
160
161 const char kText[] = "hello world";
162
163 Message message;
164 AllocMessage(kText, &message);
165
166 connector0.Accept(&message);
167
168 PumpMessages();
169
170 ASSERT_FALSE(accumulator.IsEmpty());
171
172 Message message_received;
173 accumulator.Pop(&message_received);
174
175 EXPECT_EQ(
176 std::string(kText),
177 std::string(reinterpret_cast<const char*>(message_received.payload())));
178 }
179
180 TEST_F(ConnectorTest, Basic_TwoMessages) {
181 internal::Connector connector0(handle0_.Pass());
182 internal::Connector connector1(handle1_.Pass());
183
184 const char* kText[] = {"hello", "world"};
185
186 for (size_t i = 0; i < MOJO_ARRAYSIZE(kText); ++i) {
187 Message message;
188 AllocMessage(kText[i], &message);
189
190 connector0.Accept(&message);
191 }
192
193 MessageAccumulator accumulator;
194 connector1.set_incoming_receiver(&accumulator);
195
196 PumpMessages();
197
198 for (size_t i = 0; i < MOJO_ARRAYSIZE(kText); ++i) {
199 ASSERT_FALSE(accumulator.IsEmpty());
200
201 Message message_received;
202 accumulator.Pop(&message_received);
203
204 EXPECT_EQ(
205 std::string(kText[i]),
206 std::string(reinterpret_cast<const char*>(message_received.payload())));
207 }
208 }
209
210 TEST_F(ConnectorTest, Basic_TwoMessages_Synchronous) {
211 internal::Connector connector0(handle0_.Pass());
212 internal::Connector connector1(handle1_.Pass());
213
214 const char* kText[] = {"hello", "world"};
215
216 for (size_t i = 0; i < MOJO_ARRAYSIZE(kText); ++i) {
217 Message message;
218 AllocMessage(kText[i], &message);
219
220 connector0.Accept(&message);
221 }
222
223 MessageAccumulator accumulator;
224 connector1.set_incoming_receiver(&accumulator);
225
226 connector1.WaitForIncomingMessage();
227
228 ASSERT_FALSE(accumulator.IsEmpty());
229
230 Message message_received;
231 accumulator.Pop(&message_received);
232
233 EXPECT_EQ(
234 std::string(kText[0]),
235 std::string(reinterpret_cast<const char*>(message_received.payload())));
236
237 ASSERT_TRUE(accumulator.IsEmpty());
238 }
239
240 TEST_F(ConnectorTest, WriteToClosedPipe) {
241 internal::Connector connector0(handle0_.Pass());
242
243 const char kText[] = "hello world";
244
245 Message message;
246 AllocMessage(kText, &message);
247
248 // Close the other end of the pipe.
249 handle1_.reset();
250
251 // Not observed yet because we haven't spun the RunLoop yet.
252 EXPECT_FALSE(connector0.encountered_error());
253
254 // Write failures are not reported.
255 bool ok = connector0.Accept(&message);
256 EXPECT_TRUE(ok);
257
258 // Still not observed.
259 EXPECT_FALSE(connector0.encountered_error());
260
261 // Spin the RunLoop, and then we should start observing the closed pipe.
262 PumpMessages();
263
264 EXPECT_TRUE(connector0.encountered_error());
265 }
266
267 TEST_F(ConnectorTest, MessageWithHandles) {
268 internal::Connector connector0(handle0_.Pass());
269 internal::Connector connector1(handle1_.Pass());
270
271 const char kText[] = "hello world";
272
273 Message message1;
274 AllocMessage(kText, &message1);
275
276 MessagePipe pipe;
277 message1.mutable_handles()->push_back(pipe.handle0.release());
278
279 connector0.Accept(&message1);
280
281 // The message should have been transferred, releasing the handles.
282 EXPECT_TRUE(message1.handles()->empty());
283
284 MessageAccumulator accumulator;
285 connector1.set_incoming_receiver(&accumulator);
286
287 PumpMessages();
288
289 ASSERT_FALSE(accumulator.IsEmpty());
290
291 Message message_received;
292 accumulator.Pop(&message_received);
293
294 EXPECT_EQ(
295 std::string(kText),
296 std::string(reinterpret_cast<const char*>(message_received.payload())));
297 ASSERT_EQ(1U, message_received.handles()->size());
298
299 // Now send a message to the transferred handle and confirm it's sent through
300 // to the orginal pipe.
301 // TODO(vtl): Do we need a better way of "downcasting" the handle types?
302 ScopedMessagePipeHandle smph;
303 smph.reset(MessagePipeHandle(message_received.handles()->front().value()));
304 message_received.mutable_handles()->front() = Handle();
305 // |smph| now owns this handle.
306
307 internal::Connector connector_received(smph.Pass());
308 internal::Connector connector_original(pipe.handle1.Pass());
309
310 Message message2;
311 AllocMessage(kText, &message2);
312
313 connector_received.Accept(&message2);
314 connector_original.set_incoming_receiver(&accumulator);
315 PumpMessages();
316
317 ASSERT_FALSE(accumulator.IsEmpty());
318
319 accumulator.Pop(&message_received);
320
321 EXPECT_EQ(
322 std::string(kText),
323 std::string(reinterpret_cast<const char*>(message_received.payload())));
324 }
325
326 TEST_F(ConnectorTest, WaitForIncomingMessageWithError) {
327 internal::Connector connector0(handle0_.Pass());
328 // Close the other end of the pipe.
329 handle1_.reset();
330 ASSERT_FALSE(connector0.WaitForIncomingMessage());
331 }
332
333 TEST_F(ConnectorTest, WaitForIncomingMessageWithDeletion) {
334 internal::Connector connector0(handle0_.Pass());
335 internal::Connector* connector1 = new internal::Connector(handle1_.Pass());
336
337 const char kText[] = "hello world";
338
339 Message message;
340 AllocMessage(kText, &message);
341
342 connector0.Accept(&message);
343
344 ConnectorDeletingMessageAccumulator accumulator(&connector1);
345 connector1->set_incoming_receiver(&accumulator);
346
347 connector1->WaitForIncomingMessage();
348
349 ASSERT_FALSE(connector1);
350 ASSERT_FALSE(accumulator.IsEmpty());
351
352 Message message_received;
353 accumulator.Pop(&message_received);
354
355 EXPECT_EQ(
356 std::string(kText),
357 std::string(reinterpret_cast<const char*>(message_received.payload())));
358 }
359
360 TEST_F(ConnectorTest, WaitForIncomingMessageWithReentrancy) {
361 internal::Connector connector0(handle0_.Pass());
362 internal::Connector connector1(handle1_.Pass());
363
364 const char* kText[] = {"hello", "world"};
365
366 for (size_t i = 0; i < MOJO_ARRAYSIZE(kText); ++i) {
367 Message message;
368 AllocMessage(kText[i], &message);
369
370 connector0.Accept(&message);
371 }
372
373 ReentrantMessageAccumulator accumulator(&connector1);
374 connector1.set_incoming_receiver(&accumulator);
375
376 PumpMessages();
377
378 for (size_t i = 0; i < MOJO_ARRAYSIZE(kText); ++i) {
379 ASSERT_FALSE(accumulator.IsEmpty());
380
381 Message message_received;
382 accumulator.Pop(&message_received);
383
384 EXPECT_EQ(
385 std::string(kText[i]),
386 std::string(reinterpret_cast<const char*>(message_received.payload())));
387 }
388
389 ASSERT_EQ(2, accumulator.number_of_calls());
390 }
391
392 } // namespace
393 } // namespace test
394 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/public/cpp/bindings/tests/buffer_unittest.cc ('k') | mojo/public/cpp/bindings/tests/container_test_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698