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

Side by Side Diff: chrome/browser/media/cast_remoting_connector_unittest.cc

Issue 2138013003: media::mojom::Remoter and CastRemotingConnector/Sender (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: CastRemotingConnector unit tests, and misc. Created 4 years, 3 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 2016 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 "chrome/browser/media/cast_remoting_connector.h"
6
7 #include <utility>
8 #include <vector>
9
10 #include "base/callback.h"
11 #include "base/memory/weak_ptr.h"
12 #include "base/run_loop.h"
13 #include "chrome/browser/media/router/media_route.h"
14 #include "chrome/browser/media/router/media_routes_observer.h"
15 #include "chrome/browser/media/router/media_source.h"
16 #include "chrome/browser/media/router/mock_media_router.h"
17 #include "chrome/browser/media/router/route_message.h"
18 #include "chrome/browser/media/router/route_message_observer.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "content/public/test/test_browser_thread_bundle.h"
21 #include "media/mojo/interfaces/remoting.mojom.h"
22 #include "mojo/public/cpp/bindings/binding.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25
26 using content::BrowserThread;
27
28 using media::mojom::RemoterPtr;
29 using media::mojom::RemoterRequest;
30 using media::mojom::RemotingSourcePtr;
31 using media::mojom::RemotingSourceRequest;
32 using media::mojom::RemotingStartFailReason;
33 using media::mojom::RemotingStopReason;
34
35 using media_router::MediaRoutesObserver;
36 using media_router::MediaRoute;
37 using media_router::MediaSource;
38 using media_router::RouteMessage;
39 using media_router::RouteMessageObserver;
40
41 using ::testing::_;
42 using ::testing::AtLeast;
43
44 namespace {
45
46 constexpr char kRemotingMediaSource[] =
47 "urn:x-org.chromium.media:source:tab_content_remoting:123";
48 constexpr char kRemotingMediaSink[] = "wiggles";
49 constexpr char kRemotingMediaRoute[] =
50 "urn:x-org.chromium:media:route:garbly_gook_ssi7m4oa8oma7rasd/cast-wiggles";
51
52 // Implements basic functionality of a subset of the MediaRouter for use by the
53 // unit tests in this module. Note that MockMediaRouter will complain at runtime
54 // if any methods were called that should not have been called.
55 class FakeMediaRouter : public media_router::MockMediaRouter {
56 public:
57 FakeMediaRouter()
58 : routes_observer_(nullptr), message_observer_(nullptr), weak_factory_(thi s) {}
59 ~FakeMediaRouter() final {}
60
61 //
62 // These methods are called by test code to create/destroy a media route and
63 // pass messages in both directions.
64 //
65
66 void OnRemotingRouteExists(bool exists) {
67 routes_.clear();
68 if (exists) {
69 routes_.push_back(MediaRoute(
70 kRemotingMediaRoute, MediaSource(routes_observer_->source_id()),
71 kRemotingMediaSink, "Cast Media Remoting", false, "", false));
72 } else {
73 // Cancel delivery of all messages in both directions.
74 inbound_messages_.clear();
75 for (const auto& entry : outbound_messages_) {
76 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
77 base::Bind(entry.second, false));
78 }
79 outbound_messages_.clear();
80 }
81 BrowserThread::PostTask(
82 BrowserThread::UI, FROM_HERE,
83 base::Bind(&FakeMediaRouter::DoUpdateRoutes,
84 weak_factory_.GetWeakPtr()));
85 }
86
87 void OnMessageFromProvider(const std::string& message) {
88 inbound_messages_.push_back(RouteMessage());
89 inbound_messages_.back().type = RouteMessage::TEXT;
90 inbound_messages_.back().text = message;
91 BrowserThread::PostTask(
92 BrowserThread::UI, FROM_HERE,
93 base::Bind(&FakeMediaRouter::DoDeliverInboundMessages,
94 weak_factory_.GetWeakPtr()));
95 }
96
97 void OnBinaryMessageFromProvider(const std::vector<uint8_t>& message) {
98 inbound_messages_.push_back(RouteMessage());
99 inbound_messages_.back().type = RouteMessage::BINARY;
100 inbound_messages_.back().binary = std::vector<uint8_t>(message);
101 BrowserThread::PostTask(
102 BrowserThread::UI, FROM_HERE,
103 base::Bind(&FakeMediaRouter::DoDeliverInboundMessages,
104 weak_factory_.GetWeakPtr()));
105 }
106
107 void TakeMessagesSentToProvider(RouteMessage::Type type,
108 std::vector<RouteMessage>* messages) {
109 decltype(outbound_messages_) untaken_messages;
110 for (const auto& entry : outbound_messages_) {
111 if (entry.first.type == type) {
112 messages->push_back(entry.first);
113 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
114 base::Bind(entry.second, true));
115 } else {
116 untaken_messages.push_back(entry);
117 }
118 }
119 outbound_messages_.swap(untaken_messages);
120 }
121
122 protected:
123 void RegisterMediaRoutesObserver(MediaRoutesObserver* observer) final {
124 CHECK(!routes_observer_);
125 routes_observer_ = observer;
126 CHECK(routes_observer_);
127 BrowserThread::PostTask(
128 BrowserThread::UI, FROM_HERE,
129 base::Bind(&FakeMediaRouter::DoUpdateRoutes,
130 weak_factory_.GetWeakPtr()));
131 }
132
133 void UnregisterMediaRoutesObserver(MediaRoutesObserver* observer) final {
134 CHECK_EQ(routes_observer_, observer);
135 routes_observer_ = nullptr;
136 }
137
138 void RegisterRouteMessageObserver(RouteMessageObserver* observer) final {
139 CHECK(!message_observer_);
140 message_observer_ = observer;
141 CHECK(message_observer_);
142 }
143
144 void UnregisterRouteMessageObserver(RouteMessageObserver* observer) final {
145 CHECK_EQ(message_observer_, observer);
146 message_observer_ = nullptr;
147 }
148
149 void SendRouteMessage(const MediaRoute::Id& route_id,
150 const std::string& text,
151 const SendRouteMessageCallback& callback) final {
152 EXPECT_EQ(message_observer_->route_id(), route_id);
153 ASSERT_FALSE(callback.is_null());
154 RouteMessage message;
155 message.type = RouteMessage::TEXT;
156 message.text = text;
157 outbound_messages_.push_back(std::make_pair(message, callback));
158 }
159
160 void SendRouteBinaryMessage(
161 const MediaRoute::Id& route_id,
162 std::unique_ptr<std::vector<uint8_t>> data,
163 const SendRouteMessageCallback& callback) final {
164 EXPECT_EQ(message_observer_->route_id(), route_id);
165 ASSERT_TRUE(!!data);
166 ASSERT_FALSE(callback.is_null());
167 RouteMessage message;
168 message.type = RouteMessage::BINARY;
169 message.binary = std::move(*data);
170 outbound_messages_.push_back(std::make_pair(message, callback));
171 }
172
173 private:
174 // Asynchronous callback to notify the MediaRoutesObserver of a change in
175 // routes.
176 void DoUpdateRoutes() {
177 if (routes_observer_)
178 routes_observer_->OnRoutesUpdated(routes_, std::vector<MediaRoute::Id>());
179 }
180
181 // Asynchronous callback to deliver messages to the RouteMessageObserver.
182 void DoDeliverInboundMessages() {
183 if (message_observer_)
184 message_observer_->OnMessagesReceived(inbound_messages_);
185 inbound_messages_.clear();
186 }
187
188 MediaRoutesObserver* routes_observer_;
189 RouteMessageObserver* message_observer_;
190
191 std::vector<MediaRoute> routes_;
192 // Messages from Cast Provider to the connector.
193 std::vector<RouteMessage> inbound_messages_;
194 // Messages from the connector to the Cast Provider.
195 using OutboundMessageAndCallback =
196 std::pair<RouteMessage, SendRouteMessageCallback>;
197 std::vector<OutboundMessageAndCallback> outbound_messages_;
198
199 base::WeakPtrFactory<FakeMediaRouter> weak_factory_;
200 };
201
202 class MockRemotingSource : public media::mojom::RemotingSource {
203 public:
204 MockRemotingSource() : binding_(this) {}
205 ~MockRemotingSource() override {}
206
207 void Bind(RemotingSourceRequest request) {
208 binding_.Bind(std::move(request));
209 }
210
211 MOCK_METHOD0(OnSinkAvailable, void());
212 MOCK_METHOD0(OnSinkGone, void());
213 MOCK_METHOD0(OnStarted, void());
214 MOCK_METHOD1(OnStartFailed, void(RemotingStartFailReason));
215 MOCK_METHOD1(OnMessageFromSink, void(const std::vector<uint8_t>&));
216 MOCK_METHOD1(OnStopped, void(RemotingStopReason));
217
218 private:
219 mojo::Binding<media::mojom::RemotingSource> binding_;
220 };
221
222 } // namespace
223
224 class CastRemotingConnectorTest : public ::testing::Test {
225 public:
226 CastRemotingConnectorTest()
227 : remoting_source_(kRemotingMediaSource),
228 connector_(&media_router_, remoting_source_.id()) {}
229
230 void TearDown() final {
231 // Allow any pending Mojo operations to complete before destruction. For
232 // example, when one end of a Mojo message pipe is closed, a task is posted
233 // to later destroy objects that were owned by the message pipe.
234 RunUntilIdle();
235 }
236
237 protected:
238 RemoterPtr CreateRemoter(MockRemotingSource* source) {
239 RemotingSourcePtr source_ptr;
240 source->Bind(mojo::GetProxy(&source_ptr));
241 RemoterPtr remoter_ptr;
242 connector_.CreateBridge(std::move(source_ptr),
243 mojo::GetProxy(&remoter_ptr));
244 return remoter_ptr;
245 }
246
247 void ProviderDiscoversSink() {
248 media_router_.OnRemotingRouteExists(true);
249 }
250
251 void ProviderLosesSink() {
252 media_router_.OnRemotingRouteExists(false);
253 }
254
255 void ConnectorSentMessageToProvider(const std::string& expected_message) {
256 std::vector<RouteMessage> messages;
257 media_router_.TakeMessagesSentToProvider(RouteMessage::TEXT, &messages);
258 bool did_see_expected_message = false;
259 for (const RouteMessage& message : messages) {
260 if (message.text && expected_message == *message.text) {
261 did_see_expected_message = true;
262 } else {
263 ADD_FAILURE()
264 << "Unexpected message: " << message.ToHumanReadableString();
265 }
266 }
267 EXPECT_TRUE(did_see_expected_message);
268 }
269
270 void ConnectorSentMessageToSink(
271 const std::vector<uint8_t>& expected_message) {
272 std::vector<RouteMessage> messages;
273 media_router_.TakeMessagesSentToProvider(RouteMessage::BINARY, &messages);
274 bool did_see_expected_message = false;
275 for (const RouteMessage& message : messages) {
276 if (message.binary && expected_message == *message.binary) {
277 did_see_expected_message = true;
278 } else {
279 ADD_FAILURE()
280 << "Unexpected message: " << message.ToHumanReadableString();
281 }
282 }
283 EXPECT_TRUE(did_see_expected_message);
284 }
285
286 void ConnectorSentNoMessagesToProvider() {
287 std::vector<RouteMessage> messages;
288 media_router_.TakeMessagesSentToProvider(RouteMessage::TEXT, &messages);
289 EXPECT_TRUE(messages.empty());
290 }
291
292 void ConnectorSentNoMessagesToSink() {
293 std::vector<RouteMessage> messages;
294 media_router_.TakeMessagesSentToProvider(RouteMessage::BINARY, &messages);
295 EXPECT_TRUE(messages.empty());
296 }
297
298 void ProviderPassesMessageFromSink(
299 const std::vector<uint8_t>& message) {
300 media_router_.OnBinaryMessageFromProvider(message);
301 }
302
303 void ProviderSaysToRemotingConnector(const std::string& message) {
304 media_router_.OnMessageFromProvider(message);
305 }
306
307 void MediaRouterTerminatesRoute() {
308 media_router_.OnRemotingRouteExists(false);
309 }
310
311 static void RunUntilIdle() {
312 base::RunLoop().RunUntilIdle();
313 }
314
315 private:
316 content::TestBrowserThreadBundle browser_thread_bundle_;
317 FakeMediaRouter media_router_;
318 const MediaSource remoting_source_;
319 CastRemotingConnector connector_;
320 };
321
322 TEST_F(CastRemotingConnectorTest, NeverNotifiesThatSinkIsAvailable) {
323 MockRemotingSource source;
324 RemoterPtr remoter = CreateRemoter(&source);
325
326 EXPECT_CALL(source, OnSinkAvailable()).Times(0);
327 EXPECT_CALL(source, OnSinkGone()).Times(AtLeast(0));
328 RunUntilIdle();
329 }
330
331 TEST_F(CastRemotingConnectorTest, NotifiesWhenSinkIsAvailableAndThenGone) {
332 MockRemotingSource source;
333 RemoterPtr remoter = CreateRemoter(&source);
334
335 EXPECT_CALL(source, OnSinkAvailable()).Times(1);
336 ProviderDiscoversSink();
337 RunUntilIdle();
338
339 EXPECT_CALL(source, OnSinkGone()).Times(AtLeast(1));
340 ProviderLosesSink();
341 RunUntilIdle();
342 }
343
344 TEST_F(CastRemotingConnectorTest,
345 NotifiesMultipleSourcesWhenSinkIsAvailableAndThenGone) {
346 MockRemotingSource source1;
347 RemoterPtr remoter1 = CreateRemoter(&source1);
348 MockRemotingSource source2;
349 RemoterPtr remoter2 = CreateRemoter(&source2);
350
351 EXPECT_CALL(source1, OnSinkAvailable()).Times(1);
352 EXPECT_CALL(source2, OnSinkAvailable()).Times(1);
353 ProviderDiscoversSink();
354 RunUntilIdle();
355
356 EXPECT_CALL(source1, OnSinkGone()).Times(AtLeast(1));
357 EXPECT_CALL(source2, OnSinkGone()).Times(AtLeast(1));
358 ProviderLosesSink();
359 RunUntilIdle();
360 }
361
362 namespace {
363
364 // The possible ways a remoting session may be terminated in the "full
365 // run-through" tests.
366 enum HowItEnds {
367 SOURCE_TERMINATES, // The render process decides to end remoting.
368 MOJO_PIPE_CLOSES, // A Mojo message pipe closes unexpectedly.
369 ROUTE_TERMINATES, // The Media Router UI was used to terminate the route.
370 EXTERNAL_FAILURE, // The sink is cut-off, perhaps due to a network outage.
371 };
372
373 } // namespace
374
375 class CastRemotingConnectorFullSessionTest
376 : public CastRemotingConnectorTest,
377 public ::testing::WithParamInterface<HowItEnds> {
378 public:
379 HowItEnds how_it_ends() const { return GetParam(); }
380 };
381
382 // Performs a full run-through of starting and stopping remoting, with
383 // communications between source and sink established at the correct times, and
384 // tests that end-to-end behavior is correct depending on what caused the
385 // remoting session to end.
386 TEST_P(CastRemotingConnectorFullSessionTest, GoesThroughAllTheMotions) {
387 std::unique_ptr<MockRemotingSource> source(new MockRemotingSource());
388 RemoterPtr remoter = CreateRemoter(source.get());
389 std::unique_ptr<MockRemotingSource> other_source(new MockRemotingSource());
390 RemoterPtr other_remoter = CreateRemoter(other_source.get());
391
392 // Throughout this test |other_source| should not participate in the
393 // remoting session, and so these method calls should never occur:
394 EXPECT_CALL(*other_source, OnStarted()).Times(0);
395 EXPECT_CALL(*other_source, OnStopped(_)).Times(0);
396 EXPECT_CALL(*other_source, OnMessageFromSink(_)).Times(0);
397
398 // Both sinks should be notified when the Cast Provider tells the connector
399 // a remoting sink is available.
400 EXPECT_CALL(*source, OnSinkAvailable()).Times(1).RetiresOnSaturation();
401 EXPECT_CALL(*other_source, OnSinkAvailable()).Times(1).RetiresOnSaturation();
402 ProviderDiscoversSink();
403 RunUntilIdle();
404
405 // When |source| starts a remoting session, |other_source| is notified the
406 // sink is gone, the Cast Provider is notified that remoting has started,
407 // and |source| is notified that its request was successful.
408 EXPECT_CALL(*source, OnStarted()).Times(1).RetiresOnSaturation();
409 EXPECT_CALL(*other_source, OnSinkGone()).Times(1).RetiresOnSaturation();
410 remoter->Start();
411 RunUntilIdle();
412 ConnectorSentMessageToProvider("START_CAST_REMOTING:session=1");
413
414 // The |source| should now be able to send binary messages to the sink.
415 // |other_source| should not!
416 const std::vector<uint8_t> message_to_sink = { 3, 1, 4, 1, 5, 9 };
417 remoter->SendMessageToSink(message_to_sink);
418 const std::vector<uint8_t> ignored_message_to_sink = { 1, 2, 3 };
419 other_remoter->SendMessageToSink(ignored_message_to_sink);
420 RunUntilIdle();
421 ConnectorSentMessageToSink(message_to_sink);
422
423 // The sink should also be able to send binary messages to the |source|.
424 const std::vector<uint8_t> message_to_source = { 2, 7, 1, 8, 2, 8 };
425 EXPECT_CALL(*source, OnMessageFromSink(message_to_source)).Times(1)
426 .RetiresOnSaturation();
427 ProviderPassesMessageFromSink(message_to_source);
428 RunUntilIdle();
429
430 // The |other_source| should not be allowed to start a remoting session.
431 EXPECT_CALL(*other_source,
432 OnStartFailed(RemotingStartFailReason::CANNOT_START_MULTIPLE))
433 .Times(1).RetiresOnSaturation();
434 other_remoter->Start();
435 RunUntilIdle();
436 ConnectorSentNoMessagesToProvider();
437
438 // What happens from here depends on how this remoting session will end...
439 switch (how_it_ends()) {
440 case SOURCE_TERMINATES: {
441 // When the |source| stops the remoting session, the Cast Provider is
442 // notified the session has stopped, and the |source| receives both an
443 // OnStopped() and an OnSinkGone() notification.
444 const RemotingStopReason reason = RemotingStopReason::LOCAL_PLAYBACK;
445 EXPECT_CALL(*source, OnSinkGone()).Times(1).RetiresOnSaturation();
446 EXPECT_CALL(*source, OnStopped(reason)).Times(1).RetiresOnSaturation();
447 remoter->Stop(reason);
448 RunUntilIdle();
449 ConnectorSentMessageToProvider("STOP_CAST_REMOTING:session=1");
450
451 // Since remoting is stopped, any further messaging in either direction
452 // must be dropped.
453 const std::vector<uint8_t> message_to_sink = { 1, 6, 1, 8, 0, 3 };
454 const std::vector<uint8_t> message_to_source = { 6, 2, 8, 3, 1, 8 };
455 EXPECT_CALL(*source, OnMessageFromSink(_)).Times(0);
456 remoter->SendMessageToSink(message_to_sink);
457 ProviderPassesMessageFromSink(message_to_source);
458 RunUntilIdle();
459 ConnectorSentNoMessagesToSink();
460
461 // When the sink is ready, the Cast Provider sends a notification to the
462 // connector. The connector will notify both sources that a sink is once
463 // again available.
464 EXPECT_CALL(*source, OnSinkAvailable()).Times(1).RetiresOnSaturation();
465 EXPECT_CALL(*other_source, OnSinkAvailable()).Times(1)
466 .RetiresOnSaturation();
467 ProviderSaysToRemotingConnector("STOPPED_CAST_REMOTING:session=1");
468 RunUntilIdle();
469
470 // When the sink is no longer available, the Cast Provider notifies the
471 // connector, and both sources are then notified the sink is gone.
472 EXPECT_CALL(*source, OnSinkGone()).Times(AtLeast(1));
473 EXPECT_CALL(*other_source, OnSinkGone()).Times(AtLeast(1));
474 ProviderLosesSink();
475 RunUntilIdle();
476
477 break;
478 }
479
480 case MOJO_PIPE_CLOSES:
481 // When the Mojo pipes for |other_source| close, this should not affect
482 // the current remoting session.
483 other_source.reset();
484 other_remoter.reset();
485 RunUntilIdle();
486 ConnectorSentNoMessagesToProvider();
487
488 // Now, when the Mojo pipes for |source| close, the Cast Provider will be
489 // notified that the session has stopped.
490 source.reset();
491 remoter.reset();
492 RunUntilIdle();
493 ConnectorSentMessageToProvider("STOP_CAST_REMOTING:session=1");
494
495 // The Cast Provider will detect when the sink is ready for the next
496 // remoting session, and then notify the connector. However, there are no
497 // sources to propagate this notification to.
498 ProviderSaysToRemotingConnector("STOPPED_CAST_REMOTING:session=1");
499 RunUntilIdle();
500
501 break;
502
503 case ROUTE_TERMINATES:
504 // When the Media Router terminates the route (e.g., because a user
505 // terminated the route from the UI), the source and sink are immediately
506 // cut off from one another.
507 EXPECT_CALL(*source, OnSinkGone()).Times(AtLeast(1));
508 EXPECT_CALL(*source, OnStopped(RemotingStopReason::ROUTE_TERMINATED))
509 .Times(1).RetiresOnSaturation();
510 EXPECT_CALL(*other_source, OnSinkGone()).Times(AtLeast(0));
511 MediaRouterTerminatesRoute();
512 RunUntilIdle();
513 ConnectorSentNoMessagesToProvider();
514
515 // Furthermore, the connector and Cast Provider are also cut off from one
516 // another and should not be able to exchange messages anymore. Therefore,
517 // the connector will never try to notify the sources that the sink is
518 // available again.
519 EXPECT_CALL(*source, OnSinkAvailable()).Times(0);
520 EXPECT_CALL(*other_source, OnSinkAvailable()).Times(0);
521 ProviderSaysToRemotingConnector("STOPPED_CAST_REMOTING:session=1");
522 RunUntilIdle();
523
524 break;
525
526 case EXTERNAL_FAILURE: {
527 // When the Cast Provider is cut-off from the sink, it sends a fail
528 // notification to the connector. The connector, in turn, force-stops the
529 // remoting session and notifies the |source|.
530 EXPECT_CALL(*source, OnSinkGone()).Times(1).RetiresOnSaturation();
531 EXPECT_CALL(*source, OnStopped(RemotingStopReason::UNEXPECTED_FAILURE))
532 .Times(1).RetiresOnSaturation();
533 ProviderSaysToRemotingConnector("FAILED_CAST_REMOTING:session=1");
534 RunUntilIdle();
535
536 // Since remoting is stopped, any further messaging in either direction
537 // must be dropped.
538 const std::vector<uint8_t> message_to_sink = { 1, 6, 1, 8, 0, 3 };
539 const std::vector<uint8_t> message_to_source = { 6, 2, 8, 3, 1, 8 };
540 EXPECT_CALL(*source, OnMessageFromSink(_)).Times(0);
541 remoter->SendMessageToSink(message_to_sink);
542 ProviderPassesMessageFromSink(message_to_source);
543 RunUntilIdle();
544 ConnectorSentNoMessagesToSink();
545
546 // Later, if whatever caused the external failure has resolved, the Cast
547 // Provider will notify the connector that the sink is available one
548 // again.
549 EXPECT_CALL(*source, OnSinkAvailable()).Times(1).RetiresOnSaturation();
550 EXPECT_CALL(*other_source, OnSinkAvailable()).Times(1)
551 .RetiresOnSaturation();
552 ProviderSaysToRemotingConnector("STOPPED_CAST_REMOTING:session=1");
553 RunUntilIdle();
554
555 // When the sink is no longer available, the Cast Provider notifies the
556 // connector, and both sources are then notified the sink is gone.
557 EXPECT_CALL(*source, OnSinkGone()).Times(AtLeast(1));
558 EXPECT_CALL(*other_source, OnSinkGone()).Times(AtLeast(1));
559 ProviderLosesSink();
560 RunUntilIdle();
561
562 break;
563 }
564 };
565 }
566
567 INSTANTIATE_TEST_CASE_P(, CastRemotingConnectorFullSessionTest,
568 ::testing::Values(SOURCE_TERMINATES,
569 MOJO_PIPE_CLOSES,
570 ROUTE_TERMINATES,
571 EXTERNAL_FAILURE));
OLDNEW
« no previous file with comments | « chrome/browser/media/cast_remoting_connector.cc ('k') | chrome/browser/media/cast_remoting_sender.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698