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

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

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

Powered by Google App Engine
This is Rietveld 408576698