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.
6 #include "base/containers/hash_tables.h"
7 #include "base/json/json_writer.h"
8 #include "base/strings/stringprintf.h"
9 #include "chrome/browser/media/router/media_sinks_observer.h"
10 #include "chrome/browser/media/router/media_source_helper.h"
11 #include "chrome/browser/media/router/mock_media_router.h"
12 #include "chrome/browser/ui/webui/media_router/query_result_manager.h"
13 #include "testing/gmock/include/gmock/gmock.h"
14 #include "testing/gtest/include/gtest/gtest.h"
16 using testing::ContainerEq
;
18 using testing::IsEmpty
;
21 using testing::Return
;
24 namespace media_router
{
28 class MockObserver
: public QueryResultManager::Observer
{
30 MOCK_METHOD1(OnResultsUpdated
, void(
31 const std::vector
<MediaSinkWithCastModes
>& sinks
));
36 class QueryResultManagerTest
: public ::testing::Test
{
38 QueryResultManagerTest()
39 : mock_router_(), query_result_manager_(&mock_router_
) {
42 void DiscoverSinks(MediaCastMode cast_mode
, const MediaSource
& source
) {
43 EXPECT_CALL(mock_router_
, RegisterMediaSinksObserver(_
)).Times(1);
44 EXPECT_CALL(mock_observer_
, OnResultsUpdated(_
)).Times(1);
45 query_result_manager_
.StartSinksQuery(cast_mode
, source
);
48 MockMediaRouter mock_router_
;
49 QueryResultManager query_result_manager_
;
50 MockObserver mock_observer_
;
53 DISALLOW_COPY_AND_ASSIGN(QueryResultManagerTest
);
56 MATCHER_P(VectorEquals
, expected
, "") {
57 if (expected
.size() != arg
.size()) {
60 for (int i
= 0; i
< static_cast<int>(expected
.size()); i
++) {
61 if (!expected
[i
].Equals(arg
[i
])) {
68 TEST_F(QueryResultManagerTest
, Observers
) {
71 query_result_manager_
.AddObserver(&ob1
);
72 query_result_manager_
.AddObserver(&ob2
);
74 EXPECT_CALL(ob1
, OnResultsUpdated(_
)).Times(1);
75 EXPECT_CALL(ob2
, OnResultsUpdated(_
)).Times(1);
76 query_result_manager_
.NotifyOnResultsUpdated();
78 query_result_manager_
.RemoveObserver(&ob2
);
79 EXPECT_CALL(ob1
, OnResultsUpdated(_
)).Times(1);
80 query_result_manager_
.NotifyOnResultsUpdated();
82 query_result_manager_
.RemoveObserver(&ob1
);
83 query_result_manager_
.NotifyOnResultsUpdated();
86 TEST_F(QueryResultManagerTest
, StartStopSinksQuery
) {
87 CastModeSet cast_modes
;
89 query_result_manager_
.GetSupportedCastModes(&cast_modes
);
90 EXPECT_TRUE(cast_modes
.empty());
91 MediaSource actual_source
=
92 query_result_manager_
.GetSourceForCastMode(MediaCastMode::DEFAULT
);
93 EXPECT_TRUE(actual_source
.Empty());
95 MediaSource
source(MediaSourceForPresentationUrl("http://fooUrl"));
96 EXPECT_CALL(mock_router_
, RegisterMediaSinksObserver(_
)).Times(1);
97 query_result_manager_
.StartSinksQuery(MediaCastMode::DEFAULT
, source
);
99 query_result_manager_
.GetSupportedCastModes(&cast_modes
);
100 EXPECT_EQ(1u, cast_modes
.size());
101 EXPECT_TRUE(ContainsKey(cast_modes
, MediaCastMode::DEFAULT
));
102 actual_source
= query_result_manager_
.GetSourceForCastMode(
103 MediaCastMode::DEFAULT
);
104 EXPECT_TRUE(source
.Equals(actual_source
));
106 // Register a different source for the same cast mode.
107 MediaSource
another_source(MediaSourceForPresentationUrl("http://barUrl"));
108 EXPECT_CALL(mock_router_
, UnregisterMediaSinksObserver(_
)).Times(1);
109 EXPECT_CALL(mock_router_
, RegisterMediaSinksObserver(_
)).Times(1);
110 query_result_manager_
.StartSinksQuery(
111 MediaCastMode::DEFAULT
, another_source
);
113 query_result_manager_
.GetSupportedCastModes(&cast_modes
);
114 EXPECT_EQ(1u, cast_modes
.size());
115 EXPECT_TRUE(ContainsKey(cast_modes
, MediaCastMode::DEFAULT
));
116 actual_source
= query_result_manager_
.GetSourceForCastMode(
117 MediaCastMode::DEFAULT
);
118 EXPECT_TRUE(another_source
.Equals(actual_source
));
120 EXPECT_CALL(mock_router_
, UnregisterMediaSinksObserver(_
)).Times(1);
121 query_result_manager_
.StopSinksQuery(MediaCastMode::DEFAULT
);
123 query_result_manager_
.GetSupportedCastModes(&cast_modes
);
124 EXPECT_TRUE(cast_modes
.empty());
125 actual_source
= query_result_manager_
.GetSourceForCastMode(
126 MediaCastMode::DEFAULT
);
127 EXPECT_TRUE(actual_source
.Empty());
130 TEST_F(QueryResultManagerTest
, MultipleQueries
) {
131 MediaSink
sink1("sinkId1", "Sink 1", MediaSink::IconType::CAST
);
132 MediaSink
sink2("sinkId2", "Sink 2", MediaSink::IconType::CAST
);
133 MediaSink
sink3("sinkId3", "Sink 3", MediaSink::IconType::CAST
);
134 MediaSink
sink4("sinkId4", "Sink 4", MediaSink::IconType::CAST
);
135 MediaSink
sink5("sinkId5", "Sink 5", MediaSink::IconType::CAST
);
137 query_result_manager_
.AddObserver(&mock_observer_
);
138 DiscoverSinks(MediaCastMode::DEFAULT
,
139 MediaSourceForPresentationUrl("http://barUrl"));
140 DiscoverSinks(MediaCastMode::TAB_MIRROR
, MediaSourceForTab(123));
142 // Scenario (results in this order):
143 // Action: DEFAULT -> [1, 2, 3]
145 // Sinks: [1 -> {DEFAULT}, 2 -> {DEFAULT}, 3 -> {DEFAULT}]
146 std::vector
<MediaSinkWithCastModes
> expected_sinks
;
147 expected_sinks
.push_back(MediaSinkWithCastModes(sink1
));
148 expected_sinks
.back().cast_modes
.insert(MediaCastMode::DEFAULT
);
149 expected_sinks
.push_back(MediaSinkWithCastModes(sink2
));
150 expected_sinks
.back().cast_modes
.insert(MediaCastMode::DEFAULT
);
151 expected_sinks
.push_back(MediaSinkWithCastModes(sink3
));
152 expected_sinks
.back().cast_modes
.insert(MediaCastMode::DEFAULT
);
154 const auto& sinks_observers
= query_result_manager_
.sinks_observers_
;
155 auto sinks_observer_it
= sinks_observers
.find(MediaCastMode::DEFAULT
);
156 ASSERT_TRUE(sinks_observer_it
!= sinks_observers
.end());
157 ASSERT_TRUE(sinks_observer_it
->second
.get());
159 std::vector
<MediaSink
> sinks_query_result
;
160 sinks_query_result
.push_back(sink1
);
161 sinks_query_result
.push_back(sink2
);
162 sinks_query_result
.push_back(sink3
);
163 EXPECT_CALL(mock_observer_
,
164 OnResultsUpdated(VectorEquals(expected_sinks
))).Times(1);
165 sinks_observer_it
->second
->OnSinksReceived(sinks_query_result
);
167 // Action: TAB_MIRROR -> [2, 3, 4]
169 // Sinks: [1 -> {DEFAULT}, 2 -> {DEFAULT, TAB_MIRROR},
170 // 3 -> {DEFAULT, TAB_MIRROR}, 4 -> {TAB_MIRROR}]
171 expected_sinks
.clear();
172 expected_sinks
.push_back(MediaSinkWithCastModes(sink1
));
173 expected_sinks
.back().cast_modes
.insert(MediaCastMode::DEFAULT
);
174 expected_sinks
.push_back(MediaSinkWithCastModes(sink2
));
175 expected_sinks
.back().cast_modes
.insert(MediaCastMode::DEFAULT
);
176 expected_sinks
.back().cast_modes
.insert(MediaCastMode::TAB_MIRROR
);
177 expected_sinks
.push_back(MediaSinkWithCastModes(sink3
));
178 expected_sinks
.back().cast_modes
.insert(MediaCastMode::DEFAULT
);
179 expected_sinks
.back().cast_modes
.insert(MediaCastMode::TAB_MIRROR
);
180 expected_sinks
.push_back(MediaSinkWithCastModes(sink4
));
181 expected_sinks
.back().cast_modes
.insert(MediaCastMode::TAB_MIRROR
);
183 sinks_query_result
.clear();
184 sinks_query_result
.push_back(sink2
);
185 sinks_query_result
.push_back(sink3
);
186 sinks_query_result
.push_back(sink4
);
188 sinks_observer_it
= sinks_observers
.find(MediaCastMode::TAB_MIRROR
);
189 ASSERT_TRUE(sinks_observer_it
!= sinks_observers
.end());
190 ASSERT_TRUE(sinks_observer_it
->second
.get());
191 EXPECT_CALL(mock_observer_
,
192 OnResultsUpdated(VectorEquals(expected_sinks
))).Times(1);
193 sinks_observer_it
->second
->OnSinksReceived(sinks_query_result
);
195 // Action: Update default presentation URL
197 // Sinks: [2 -> {TAB_MIRROR}, 3 -> {TAB_MIRROR}, 4 -> {TAB_MIRROR}]
198 expected_sinks
.clear();
199 expected_sinks
.push_back(MediaSinkWithCastModes(sink2
));
200 expected_sinks
.back().cast_modes
.insert(MediaCastMode::TAB_MIRROR
);
201 expected_sinks
.push_back(MediaSinkWithCastModes(sink3
));
202 expected_sinks
.back().cast_modes
.insert(MediaCastMode::TAB_MIRROR
);
203 expected_sinks
.push_back(MediaSinkWithCastModes(sink4
));
204 expected_sinks
.back().cast_modes
.insert(MediaCastMode::TAB_MIRROR
);
206 EXPECT_CALL(mock_router_
, UnregisterMediaSinksObserver(_
)).Times(1);
207 EXPECT_CALL(mock_router_
, RegisterMediaSinksObserver(_
)).Times(1);
208 EXPECT_CALL(mock_observer_
,
209 OnResultsUpdated(VectorEquals(expected_sinks
))).Times(1);
210 query_result_manager_
.StartSinksQuery(
211 MediaCastMode::DEFAULT
,
212 MediaSourceForPresentationUrl("http://bazurl.com"));
214 // Action: Remove TAB_MIRROR observer
217 expected_sinks
.clear();
218 EXPECT_CALL(mock_observer_
,
219 OnResultsUpdated(VectorEquals(expected_sinks
))).Times(1);
220 EXPECT_CALL(mock_router_
, UnregisterMediaSinksObserver(_
)).Times(1);
221 query_result_manager_
.StopSinksQuery(MediaCastMode::TAB_MIRROR
);
223 // Remaining observers: DEFAULT observer, which will be removed on destruction
224 EXPECT_CALL(mock_router_
, UnregisterMediaSinksObserver(_
)).Times(1);
227 } // namespace media_router