1 // Copyright 2020 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 "cast/sender/cast_app_availability_tracker.h"
6 
7 #include "gmock/gmock.h"
8 #include "gtest/gtest.h"
9 #include "platform/test/fake_clock.h"
10 
11 namespace openscreen {
12 namespace cast {
13 namespace {
14 
15 using ::testing::UnorderedElementsAreArray;
16 
17 MATCHER_P(CastMediaSourcesEqual, expected, "") {
18   if (expected.size() != arg.size())
19     return false;
20   return std::equal(
21       expected.begin(), expected.end(), arg.begin(),
__anonb1845e430202(const CastMediaSource& source1, const CastMediaSource& source2) 22       [](const CastMediaSource& source1, const CastMediaSource& source2) {
23         return source1.source_id() == source2.source_id();
24       });
25 }
26 
27 }  // namespace
28 
29 class CastAppAvailabilityTrackerTest : public ::testing::Test {
30  public:
CastAppAvailabilityTrackerTest()31   CastAppAvailabilityTrackerTest() : clock_(Clock::now()) {}
32   ~CastAppAvailabilityTrackerTest() override = default;
33 
Now() const34   Clock::time_point Now() const { return clock_.now(); }
35 
36  protected:
37   FakeClock clock_;
38   CastAppAvailabilityTracker tracker_;
39 };
40 
TEST_F(CastAppAvailabilityTrackerTest,RegisterSource)41 TEST_F(CastAppAvailabilityTrackerTest, RegisterSource) {
42   CastMediaSource source1("cast:AAA?clientId=1", {"AAA"});
43   CastMediaSource source2("cast:AAA?clientId=2", {"AAA"});
44 
45   std::vector<std::string> expected_app_ids = {"AAA"};
46   EXPECT_EQ(expected_app_ids, tracker_.RegisterSource(source1));
47 
48   EXPECT_EQ(std::vector<std::string>{}, tracker_.RegisterSource(source1));
49   EXPECT_EQ(std::vector<std::string>{}, tracker_.RegisterSource(source2));
50 
51   tracker_.UnregisterSource(source1);
52   tracker_.UnregisterSource(source2);
53 
54   EXPECT_EQ(expected_app_ids, tracker_.RegisterSource(source1));
55   EXPECT_EQ(expected_app_ids, tracker_.GetRegisteredApps());
56 }
57 
TEST_F(CastAppAvailabilityTrackerTest,RegisterSourceReturnsMultipleAppIds)58 TEST_F(CastAppAvailabilityTrackerTest, RegisterSourceReturnsMultipleAppIds) {
59   CastMediaSource source1("urn:x-org.chromium.media:source:tab:1",
60                           {"0F5096E8", "85CDB22F"});
61 
62   // Mirorring app ids.
63   std::vector<std::string> expected_app_ids = {"0F5096E8", "85CDB22F"};
64   EXPECT_THAT(tracker_.RegisterSource(source1),
65               UnorderedElementsAreArray(expected_app_ids));
66   EXPECT_THAT(tracker_.GetRegisteredApps(),
67               UnorderedElementsAreArray(expected_app_ids));
68 }
69 
TEST_F(CastAppAvailabilityTrackerTest,MultipleAppIdsAlreadyTrackingOne)70 TEST_F(CastAppAvailabilityTrackerTest, MultipleAppIdsAlreadyTrackingOne) {
71   // One of the mirroring app IDs.
72   CastMediaSource source1("cast:0F5096E8?clientId=123", {"0F5096E8"});
73 
74   std::vector<std::string> new_app_ids = {"0F5096E8"};
75   std::vector<std::string> registered_app_ids = {"0F5096E8"};
76   EXPECT_EQ(new_app_ids, tracker_.RegisterSource(source1));
77   EXPECT_EQ(registered_app_ids, tracker_.GetRegisteredApps());
78 
79   CastMediaSource source2("urn:x-org.chromium.media:source:tab:1",
80                           {"0F5096E8", "85CDB22F"});
81 
82   new_app_ids = {"85CDB22F"};
83   registered_app_ids = {"0F5096E8", "85CDB22F"};
84 
85   EXPECT_EQ(new_app_ids, tracker_.RegisterSource(source2));
86   EXPECT_THAT(tracker_.GetRegisteredApps(),
87               UnorderedElementsAreArray(registered_app_ids));
88 }
89 
TEST_F(CastAppAvailabilityTrackerTest,UpdateAppAvailability)90 TEST_F(CastAppAvailabilityTrackerTest, UpdateAppAvailability) {
91   CastMediaSource source1("cast:AAA?clientId=1", {"AAA"});
92   CastMediaSource source2("cast:AAA?clientId=2", {"AAA"});
93   CastMediaSource source3("cast:BBB?clientId=3", {"BBB"});
94 
95   tracker_.RegisterSource(source3);
96 
97   // |source3| not affected.
98   EXPECT_THAT(
99       tracker_.UpdateAppAvailability(
100           "deviceId1", "AAA", {AppAvailabilityResult::kAvailable, Now()}),
101       CastMediaSourcesEqual(std::vector<CastMediaSource>()));
102 
103   std::vector<std::string> devices_1 = {"deviceId1"};
104   std::vector<std::string> devices_1_2 = {"deviceId1", "deviceId2"};
105   std::vector<CastMediaSource> sources_1 = {source1};
106   std::vector<CastMediaSource> sources_1_2 = {source1, source2};
107 
108   // Tracker returns available devices even though sources aren't registered.
109   EXPECT_EQ(devices_1, tracker_.GetAvailableDevices(source1));
110   EXPECT_EQ(devices_1, tracker_.GetAvailableDevices(source2));
111   EXPECT_TRUE(tracker_.GetAvailableDevices(source3).empty());
112 
113   tracker_.RegisterSource(source1);
114   // Only |source1| is registered for this app.
115   EXPECT_THAT(
116       tracker_.UpdateAppAvailability(
117           "deviceId2", "AAA", {AppAvailabilityResult::kAvailable, Now()}),
118       CastMediaSourcesEqual(sources_1));
119   EXPECT_THAT(tracker_.GetAvailableDevices(source1),
120               UnorderedElementsAreArray(devices_1_2));
121   EXPECT_THAT(tracker_.GetAvailableDevices(source2),
122               UnorderedElementsAreArray(devices_1_2));
123   EXPECT_TRUE(tracker_.GetAvailableDevices(source3).empty());
124 
125   tracker_.RegisterSource(source2);
126   EXPECT_THAT(
127       tracker_.UpdateAppAvailability(
128           "deviceId2", "AAA", {AppAvailabilityResult::kUnavailable, Now()}),
129       CastMediaSourcesEqual(sources_1_2));
130   EXPECT_EQ(devices_1, tracker_.GetAvailableDevices(source1));
131   EXPECT_EQ(devices_1, tracker_.GetAvailableDevices(source2));
132   EXPECT_TRUE(tracker_.GetAvailableDevices(source3).empty());
133 }
134 
TEST_F(CastAppAvailabilityTrackerTest,RemoveResultsForDevice)135 TEST_F(CastAppAvailabilityTrackerTest, RemoveResultsForDevice) {
136   CastMediaSource source1("cast:AAA?clientId=1", {"AAA"});
137 
138   tracker_.UpdateAppAvailability("deviceId1", "AAA",
139                                  {AppAvailabilityResult::kAvailable, Now()});
140   EXPECT_EQ(AppAvailabilityResult::kAvailable,
141             tracker_.GetAvailability("deviceId1", "AAA").availability);
142 
143   std::vector<std::string> expected_device_ids = {"deviceId1"};
144   EXPECT_EQ(expected_device_ids, tracker_.GetAvailableDevices(source1));
145 
146   // Unrelated device ID.
147   tracker_.RemoveResultsForDevice("deviceId2");
148   EXPECT_EQ(AppAvailabilityResult::kAvailable,
149             tracker_.GetAvailability("deviceId1", "AAA").availability);
150   EXPECT_EQ(expected_device_ids, tracker_.GetAvailableDevices(source1));
151 
152   tracker_.RemoveResultsForDevice("deviceId1");
153   EXPECT_EQ(AppAvailabilityResult::kUnknown,
154             tracker_.GetAvailability("deviceId1", "AAA").availability);
155   EXPECT_EQ(std::vector<std::string>{}, tracker_.GetAvailableDevices(source1));
156 }
157 
158 }  // namespace cast
159 }  // namespace openscreen
160