1 // Copyright 2018 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/router/providers/cast/cast_app_availability_tracker.h"
6
7 #include "base/test/simple_test_tick_clock.h"
8 #include "components/cast_channel/cast_message_util.h"
9 #include "components/media_router/common/providers/cast/cast_media_source.h"
10 #include "testing/gmock/include/gmock/gmock.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12
13 using cast_channel::GetAppAvailabilityResult;
14
15 namespace media_router {
16
17 namespace {
18
19 MATCHER_P(CastMediaSourcesEqual, expected, "") {
20 if (expected.size() != arg.size())
21 return false;
22 return std::equal(
23 expected.begin(), expected.end(), arg.begin(),
__anonfc3cb5ae0202(const CastMediaSource& source1, const CastMediaSource& source2) 24 [](const CastMediaSource& source1, const CastMediaSource& source2) {
25 return source1.source_id() == source2.source_id();
26 });
27 }
28
29 } // namespace
30
31 class CastAppAvailabilityTrackerTest : public testing::Test {
32 public:
CastAppAvailabilityTrackerTest()33 CastAppAvailabilityTrackerTest() {}
34 ~CastAppAvailabilityTrackerTest() override = default;
35
Now() const36 base::TimeTicks Now() const { return clock_.NowTicks(); }
37
38 protected:
39 base::SimpleTestTickClock clock_;
40 CastAppAvailabilityTracker tracker_;
41
42 private:
43 DISALLOW_COPY_AND_ASSIGN(CastAppAvailabilityTrackerTest);
44 };
45
TEST_F(CastAppAvailabilityTrackerTest,RegisterSource)46 TEST_F(CastAppAvailabilityTrackerTest, RegisterSource) {
47 auto source1 = CastMediaSource::FromMediaSourceId("cast:AAAAAAAA?clientId=1");
48 ASSERT_TRUE(source1);
49 auto source2 = CastMediaSource::FromMediaSourceId("cast:AAAAAAAA?clientId=2");
50 ASSERT_TRUE(source2);
51
52 base::flat_set<std::string> expected_app_ids = {"AAAAAAAA"};
53 EXPECT_EQ(expected_app_ids, tracker_.RegisterSource(*source1));
54
55 expected_app_ids.clear();
56 EXPECT_EQ(expected_app_ids, tracker_.RegisterSource(*source1));
57 EXPECT_EQ(expected_app_ids, tracker_.RegisterSource(*source2));
58
59 tracker_.UnregisterSource(*source1);
60 tracker_.UnregisterSource(*source2);
61
62 expected_app_ids = {"AAAAAAAA"};
63 EXPECT_EQ(expected_app_ids, tracker_.RegisterSource(*source1));
64 EXPECT_EQ(expected_app_ids, tracker_.GetRegisteredApps());
65 }
66
TEST_F(CastAppAvailabilityTrackerTest,RegisterSourceReturnsMultipleAppIds)67 TEST_F(CastAppAvailabilityTrackerTest, RegisterSourceReturnsMultipleAppIds) {
68 auto source1 = CastMediaSource::FromMediaSourceId(
69 "urn:x-org.chromium.media:source:tab:1");
70 ASSERT_TRUE(source1);
71
72 // Mirorring app ids.
73 base::flat_set<std::string> expected_app_ids = {"0F5096E8", "85CDB22F"};
74 EXPECT_EQ(expected_app_ids, tracker_.RegisterSource(*source1));
75 EXPECT_EQ(expected_app_ids, tracker_.GetRegisteredApps());
76 }
77
TEST_F(CastAppAvailabilityTrackerTest,MultipleAppIdsAlreadyTrackingOne)78 TEST_F(CastAppAvailabilityTrackerTest, MultipleAppIdsAlreadyTrackingOne) {
79 // One of the mirroring app IDs.
80 auto source1 =
81 CastMediaSource::FromMediaSourceId("cast:0F5096E8?clientId=123");
82 ASSERT_TRUE(source1);
83
84 base::flat_set<std::string> new_app_ids = {"0F5096E8"};
85 base::flat_set<std::string> registered_app_ids = {"0F5096E8"};
86 EXPECT_EQ(new_app_ids, tracker_.RegisterSource(*source1));
87 EXPECT_EQ(registered_app_ids, tracker_.GetRegisteredApps());
88
89 auto source2 = CastMediaSource::FromMediaSourceId(
90 "urn:x-org.chromium.media:source:tab:1");
91 ASSERT_TRUE(source2);
92
93 new_app_ids = {"85CDB22F"};
94 registered_app_ids = {"0F5096E8", "85CDB22F"};
95
96 EXPECT_EQ(new_app_ids, tracker_.RegisterSource(*source2));
97 EXPECT_EQ(registered_app_ids, tracker_.GetRegisteredApps());
98 }
99
TEST_F(CastAppAvailabilityTrackerTest,UpdateAppAvailability)100 TEST_F(CastAppAvailabilityTrackerTest, UpdateAppAvailability) {
101 auto source1 = CastMediaSource::FromMediaSourceId("cast:AAAAAAAA?clientId=1");
102 ASSERT_TRUE(source1);
103 auto source2 = CastMediaSource::FromMediaSourceId("cast:AAAAAAAA?clientId=2");
104 ASSERT_TRUE(source2);
105 auto source3 = CastMediaSource::FromMediaSourceId("cast:BBBBBBBB?clientId=3");
106 ASSERT_TRUE(source3);
107
108 tracker_.RegisterSource(*source3);
109
110 // |source3| not affected.
111 EXPECT_THAT(
112 tracker_.UpdateAppAvailability(
113 "sinkId1", "AAAAAAAA", {GetAppAvailabilityResult::kAvailable, Now()}),
114 CastMediaSourcesEqual(std::vector<CastMediaSource>()));
115
116 base::flat_set<MediaSink::Id> sinks_1 = {"sinkId1"};
117 base::flat_set<MediaSink::Id> sinks_1_2 = {"sinkId1", "sinkId2"};
118 std::vector<CastMediaSource> sources_1 = {*source1};
119 std::vector<CastMediaSource> sources_1_2 = {*source1, *source2};
120
121 // Tracker returns available sinks even though sources aren't registered.
122 EXPECT_EQ(sinks_1, tracker_.GetAvailableSinks(*source1));
123 EXPECT_EQ(sinks_1, tracker_.GetAvailableSinks(*source2));
124 EXPECT_TRUE(tracker_.GetAvailableSinks(*source3).empty());
125
126 tracker_.RegisterSource(*source1);
127 // Only |source1| is registered for this app.
128 EXPECT_THAT(
129 tracker_.UpdateAppAvailability(
130 "sinkId2", "AAAAAAAA", {GetAppAvailabilityResult::kAvailable, Now()}),
131 CastMediaSourcesEqual(sources_1));
132 EXPECT_EQ(sinks_1_2, tracker_.GetAvailableSinks(*source1));
133 EXPECT_EQ(sinks_1_2, tracker_.GetAvailableSinks(*source2));
134 EXPECT_TRUE(tracker_.GetAvailableSinks(*source3).empty());
135
136 tracker_.RegisterSource(*source2);
137 EXPECT_THAT(tracker_.UpdateAppAvailability(
138 "sinkId2", "AAAAAAAA",
139 {GetAppAvailabilityResult::kUnavailable, Now()}),
140 CastMediaSourcesEqual(sources_1_2));
141 EXPECT_EQ(sinks_1, tracker_.GetAvailableSinks(*source1));
142 EXPECT_EQ(sinks_1, tracker_.GetAvailableSinks(*source2));
143 EXPECT_TRUE(tracker_.GetAvailableSinks(*source3).empty());
144 }
145
TEST_F(CastAppAvailabilityTrackerTest,RemoveResultsForSink)146 TEST_F(CastAppAvailabilityTrackerTest, RemoveResultsForSink) {
147 auto source1 = CastMediaSource::FromMediaSourceId("cast:AAAAAAAA?clientId=1");
148 ASSERT_TRUE(source1);
149
150 tracker_.UpdateAppAvailability("sinkId1", "AAAAAAAA",
151 {GetAppAvailabilityResult::kAvailable, Now()});
152 EXPECT_EQ(GetAppAvailabilityResult::kAvailable,
153 tracker_.GetAvailability("sinkId1", "AAAAAAAA").first);
154
155 base::flat_set<MediaSink::Id> expected_sink_ids = {"sinkId1"};
156 EXPECT_EQ(expected_sink_ids, tracker_.GetAvailableSinks(*source1));
157
158 // Unrelated sink ID.
159 tracker_.RemoveResultsForSink("sinkId2");
160 EXPECT_EQ(GetAppAvailabilityResult::kAvailable,
161 tracker_.GetAvailability("sinkId1", "AAAAAAAA").first);
162 EXPECT_EQ(expected_sink_ids, tracker_.GetAvailableSinks(*source1));
163
164 expected_sink_ids.clear();
165 tracker_.RemoveResultsForSink("sinkId1");
166 EXPECT_EQ(GetAppAvailabilityResult::kUnknown,
167 tracker_.GetAvailability("sinkId1", "AAAAAAAA").first);
168 EXPECT_EQ(expected_sink_ids, tracker_.GetAvailableSinks(*source1));
169 }
170
171 } // namespace media_router
172