1 // Copyright 2017 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/common/media_router/discovery/media_sink_service_base.h"
6 
7 #include "base/memory/ptr_util.h"
8 #include "base/test/mock_callback.h"
9 #include "base/timer/mock_timer.h"
10 #include "chrome/common/media_router/test/test_helper.h"
11 #include "testing/gmock/include/gmock/gmock.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 
14 using ::testing::_;
15 using ::testing::Return;
16 
17 namespace {
18 
CreateDialSinkExtraData(const std::string & model_name,const std::string & ip_address,const std::string & app_url)19 media_router::DialSinkExtraData CreateDialSinkExtraData(
20     const std::string& model_name,
21     const std::string& ip_address,
22     const std::string& app_url) {
23   media_router::DialSinkExtraData dial_extra_data;
24   EXPECT_TRUE(dial_extra_data.ip_address.AssignFromIPLiteral(ip_address));
25   dial_extra_data.model_name = model_name;
26   dial_extra_data.app_url = GURL(app_url);
27   return dial_extra_data;
28 }
29 
CreateDialMediaSinks()30 std::vector<media_router::MediaSinkInternal> CreateDialMediaSinks() {
31   media_router::MediaSink sink1("sink1", "sink_name_1",
32                                 media_router::SinkIconType::CAST);
33   media_router::DialSinkExtraData extra_data1 = CreateDialSinkExtraData(
34       "model_name1", "192.168.1.1", "https://example1.com");
35 
36   media_router::MediaSink sink2("sink2", "sink_name_2",
37                                 media_router::SinkIconType::CAST);
38   media_router::DialSinkExtraData extra_data2 = CreateDialSinkExtraData(
39       "model_name2", "192.168.1.2", "https://example2.com");
40 
41   std::vector<media_router::MediaSinkInternal> sinks;
42   sinks.push_back(media_router::MediaSinkInternal(sink1, extra_data1));
43   sinks.push_back(media_router::MediaSinkInternal(sink2, extra_data2));
44   return sinks;
45 }
46 
47 }  // namespace
48 
49 namespace media_router {
50 
51 class MediaSinkServiceBaseTest : public ::testing::Test {
52  public:
MediaSinkServiceBaseTest()53   MediaSinkServiceBaseTest()
54       : media_sink_service_(mock_sink_discovered_cb_.Get()) {}
~MediaSinkServiceBaseTest()55   ~MediaSinkServiceBaseTest() override {}
56 
PopulateSinks(const std::vector<MediaSinkInternal> & old_sinks,const std::vector<MediaSinkInternal> & new_sinks)57   void PopulateSinks(const std::vector<MediaSinkInternal>& old_sinks,
58                      const std::vector<MediaSinkInternal>& new_sinks) {
59     media_sink_service_.previous_sinks_.clear();
60     for (const auto& old_sink : old_sinks)
61       media_sink_service_.previous_sinks_.emplace(old_sink.sink().id(),
62                                                   old_sink);
63 
64     media_sink_service_.sinks_.clear();
65     for (const auto& new_sink : new_sinks)
66       media_sink_service_.sinks_.emplace(new_sink.sink().id(), new_sink);
67   }
68 
TestOnDiscoveryComplete(const std::vector<MediaSinkInternal> & old_sinks,const std::vector<MediaSinkInternal> & new_sinks)69   void TestOnDiscoveryComplete(
70       const std::vector<MediaSinkInternal>& old_sinks,
71       const std::vector<MediaSinkInternal>& new_sinks) {
72     PopulateSinks(old_sinks, new_sinks);
73     EXPECT_CALL(mock_sink_discovered_cb_, Run(new_sinks));
74     media_sink_service_.OnDiscoveryComplete();
75   }
76 
77  protected:
78   base::MockCallback<OnSinksDiscoveredCallback> mock_sink_discovered_cb_;
79   TestMediaSinkService media_sink_service_;
80 
81   DISALLOW_COPY_AND_ASSIGN(MediaSinkServiceBaseTest);
82 };
83 
TEST_F(MediaSinkServiceBaseTest,TestOnDiscoveryComplete_SameSink)84 TEST_F(MediaSinkServiceBaseTest, TestOnDiscoveryComplete_SameSink) {
85   std::vector<MediaSinkInternal> old_sinks;
86   std::vector<MediaSinkInternal> new_sinks = CreateDialMediaSinks();
87   TestOnDiscoveryComplete(old_sinks, new_sinks);
88 
89   // Same sink
90   EXPECT_CALL(mock_sink_discovered_cb_, Run(new_sinks)).Times(0);
91   media_sink_service_.OnDiscoveryComplete();
92 }
93 
TEST_F(MediaSinkServiceBaseTest,TestOnDiscoveryComplete_SameSinkDifferentOrders)94 TEST_F(MediaSinkServiceBaseTest,
95        TestOnDiscoveryComplete_SameSinkDifferentOrders) {
96   std::vector<MediaSinkInternal> old_sinks = CreateDialMediaSinks();
97   std::vector<MediaSinkInternal> new_sinks = CreateDialMediaSinks();
98   std::reverse(new_sinks.begin(), new_sinks.end());
99 
100   PopulateSinks(old_sinks, new_sinks);
101   EXPECT_CALL(mock_sink_discovered_cb_, Run(new_sinks)).Times(0);
102   media_sink_service_.OnDiscoveryComplete();
103 }
104 
TEST_F(MediaSinkServiceBaseTest,TestOnDiscoveryComplete_OneNewSink)105 TEST_F(MediaSinkServiceBaseTest, TestOnDiscoveryComplete_OneNewSink) {
106   std::vector<MediaSinkInternal> old_sinks = CreateDialMediaSinks();
107   std::vector<MediaSinkInternal> new_sinks = CreateDialMediaSinks();
108   MediaSink sink3("sink3", "sink_name_3", SinkIconType::CAST);
109   DialSinkExtraData extra_data3 = CreateDialSinkExtraData(
110       "model_name3", "192.168.1.3", "https://example3.com");
111   new_sinks.push_back(MediaSinkInternal(sink3, extra_data3));
112   TestOnDiscoveryComplete(old_sinks, new_sinks);
113 }
114 
TEST_F(MediaSinkServiceBaseTest,TestOnDiscoveryComplete_RemovedOneSink)115 TEST_F(MediaSinkServiceBaseTest, TestOnDiscoveryComplete_RemovedOneSink) {
116   std::vector<MediaSinkInternal> old_sinks = CreateDialMediaSinks();
117   std::vector<MediaSinkInternal> new_sinks = CreateDialMediaSinks();
118   new_sinks.erase(new_sinks.begin());
119   TestOnDiscoveryComplete(old_sinks, new_sinks);
120 }
121 
TEST_F(MediaSinkServiceBaseTest,TestOnDiscoveryComplete_UpdatedOneSink)122 TEST_F(MediaSinkServiceBaseTest, TestOnDiscoveryComplete_UpdatedOneSink) {
123   std::vector<MediaSinkInternal> old_sinks = CreateDialMediaSinks();
124   std::vector<MediaSinkInternal> new_sinks = CreateDialMediaSinks();
125   new_sinks[0].sink().set_name("sink_name_4");
126   TestOnDiscoveryComplete(old_sinks, new_sinks);
127 }
128 
TEST_F(MediaSinkServiceBaseTest,TestOnDiscoveryComplete_Mixed)129 TEST_F(MediaSinkServiceBaseTest, TestOnDiscoveryComplete_Mixed) {
130   std::vector<MediaSinkInternal> old_sinks = CreateDialMediaSinks();
131 
132   MediaSink sink1("sink1", "sink_name_1", SinkIconType::CAST);
133   DialSinkExtraData extra_data2 = CreateDialSinkExtraData(
134       "model_name2", "192.168.1.2", "https://example2.com");
135 
136   MediaSink sink3("sink3", "sink_name_3", SinkIconType::CAST);
137   DialSinkExtraData extra_data3 = CreateDialSinkExtraData(
138       "model_name3", "192.168.1.3", "https://example3.com");
139 
140   std::vector<MediaSinkInternal> new_sinks;
141   new_sinks.push_back(MediaSinkInternal(sink1, extra_data2));
142   new_sinks.push_back(MediaSinkInternal(sink3, extra_data3));
143 
144   TestOnDiscoveryComplete(old_sinks, new_sinks);
145 }
146 
147 }  // namespace media_router
148