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 "chromeos/services/multidevice_setup/eligible_host_devices_provider_impl.h"
6 
7 #include <memory>
8 
9 #include "base/containers/flat_set.h"
10 #include "base/macros.h"
11 #include "base/stl_util.h"
12 #include "base/test/scoped_feature_list.h"
13 #include "chromeos/components/multidevice/remote_device_test_util.h"
14 #include "chromeos/components/multidevice/software_feature.h"
15 #include "chromeos/components/multidevice/software_feature_state.h"
16 #include "chromeos/constants/chromeos_features.h"
17 #include "chromeos/services/device_sync/proto/cryptauth_api.pb.h"
18 #include "chromeos/services/device_sync/public/cpp/fake_device_sync_client.h"
19 #include "chromeos/services/device_sync/public/mojom/device_sync.mojom.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 
22 namespace chromeos {
23 
24 namespace multidevice_setup {
25 
26 namespace {
27 
28 const size_t kNumTestDevices = 5;
29 
30 }  // namespace
31 
32 class MultiDeviceSetupEligibleHostDevicesProviderImplTest
33     : public testing::TestWithParam<bool> {
34  protected:
MultiDeviceSetupEligibleHostDevicesProviderImplTest()35   MultiDeviceSetupEligibleHostDevicesProviderImplTest()
36       : test_devices_(
37             multidevice::CreateRemoteDeviceRefListForTest(kNumTestDevices)) {}
38   ~MultiDeviceSetupEligibleHostDevicesProviderImplTest() override = default;
39 
40   // testing::Test:
SetUp()41   void SetUp() override {
42     use_get_devices_activity_status_ = GetParam();
43     scoped_feature_list_.InitWithFeatureState(
44         chromeos::features::kCryptAuthV2DeviceActivityStatus,
45         use_get_devices_activity_status_);
46 
47     fake_device_sync_client_ =
48         std::make_unique<device_sync::FakeDeviceSyncClient>();
49     fake_device_sync_client_->set_synced_devices(test_devices_);
50 
51     provider_ = EligibleHostDevicesProviderImpl::Factory::Create(
52         fake_device_sync_client_.get());
53   }
54 
fake_device_sync_client()55   device_sync::FakeDeviceSyncClient* fake_device_sync_client() {
56     return fake_device_sync_client_.get();
57   }
58 
test_devices()59   multidevice::RemoteDeviceRefList& test_devices() { return test_devices_; }
60 
provider()61   EligibleHostDevicesProvider* provider() { return provider_.get(); }
62 
SetBitsOnTestDevices()63   void SetBitsOnTestDevices() {
64     // Devices 0, 1, and 2 are supported.
65     GetMutableRemoteDevice(test_devices()[0])
66         ->software_features[multidevice::SoftwareFeature::kBetterTogetherHost] =
67         multidevice::SoftwareFeatureState::kSupported;
68     GetMutableRemoteDevice(test_devices()[1])
69         ->software_features[multidevice::SoftwareFeature::kBetterTogetherHost] =
70         multidevice::SoftwareFeatureState::kSupported;
71     GetMutableRemoteDevice(test_devices()[2])
72         ->software_features[multidevice::SoftwareFeature::kBetterTogetherHost] =
73         multidevice::SoftwareFeatureState::kSupported;
74 
75     // Device 3 is enabled.
76     GetMutableRemoteDevice(test_devices()[3])
77         ->software_features[multidevice::SoftwareFeature::kBetterTogetherHost] =
78         multidevice::SoftwareFeatureState::kEnabled;
79 
80     // Device 4 is not supported.
81     GetMutableRemoteDevice(test_devices()[4])
82         ->software_features[multidevice::SoftwareFeature::kBetterTogetherHost] =
83         multidevice::SoftwareFeatureState::kNotSupported;
84   }
85 
use_get_devices_activity_status()86   bool use_get_devices_activity_status() {
87     return use_get_devices_activity_status_;
88   }
89 
90  private:
91   multidevice::RemoteDeviceRefList test_devices_;
92 
93   std::unique_ptr<device_sync::FakeDeviceSyncClient> fake_device_sync_client_;
94 
95   std::unique_ptr<EligibleHostDevicesProvider> provider_;
96 
97   bool use_get_devices_activity_status_;
98 
99   base::test::ScopedFeatureList scoped_feature_list_;
100 
101   DISALLOW_COPY_AND_ASSIGN(MultiDeviceSetupEligibleHostDevicesProviderImplTest);
102 };
103 
TEST_P(MultiDeviceSetupEligibleHostDevicesProviderImplTest,Empty)104 TEST_P(MultiDeviceSetupEligibleHostDevicesProviderImplTest, Empty) {
105   EXPECT_TRUE(provider()->GetEligibleHostDevices().empty());
106 }
107 
TEST_P(MultiDeviceSetupEligibleHostDevicesProviderImplTest,NoEligibleDevices)108 TEST_P(MultiDeviceSetupEligibleHostDevicesProviderImplTest, NoEligibleDevices) {
109   GetMutableRemoteDevice(test_devices()[0])
110       ->software_features[multidevice::SoftwareFeature::kBetterTogetherHost] =
111       multidevice::SoftwareFeatureState::kNotSupported;
112   GetMutableRemoteDevice(test_devices()[1])
113       ->software_features[multidevice::SoftwareFeature::kBetterTogetherHost] =
114       multidevice::SoftwareFeatureState::kNotSupported;
115 
116   multidevice::RemoteDeviceRefList devices{test_devices()[0],
117                                            test_devices()[1]};
118   fake_device_sync_client()->set_synced_devices(devices);
119   fake_device_sync_client()->NotifyNewDevicesSynced();
120 
121   EXPECT_TRUE(provider()->GetEligibleHostDevices().empty());
122 }
123 
TEST_P(MultiDeviceSetupEligibleHostDevicesProviderImplTest,SupportedAndEnabled)124 TEST_P(MultiDeviceSetupEligibleHostDevicesProviderImplTest,
125        SupportedAndEnabled) {
126   SetBitsOnTestDevices();
127 
128   GetMutableRemoteDevice(test_devices()[0])->last_update_time_millis = 1999;
129   GetMutableRemoteDevice(test_devices()[1])->last_update_time_millis = 25;
130   GetMutableRemoteDevice(test_devices()[2])->last_update_time_millis = 2525;
131   GetMutableRemoteDevice(test_devices()[3])->last_update_time_millis = 500;
132   GetMutableRemoteDevice(test_devices()[4])->last_update_time_millis = 1000;
133 
134   multidevice::RemoteDeviceRefList devices{test_devices()[0], test_devices()[1],
135                                            test_devices()[2], test_devices()[3],
136                                            test_devices()[4]};
137   fake_device_sync_client()->set_synced_devices(devices);
138   fake_device_sync_client()->NotifyNewDevicesSynced();
139 
140   multidevice::RemoteDeviceRefList eligible_devices =
141       provider()->GetEligibleHostDevices();
142   EXPECT_EQ(4u, eligible_devices.size());
143   EXPECT_EQ(test_devices()[2], eligible_devices[0]);
144   EXPECT_EQ(test_devices()[0], eligible_devices[1]);
145   EXPECT_EQ(test_devices()[3], eligible_devices[2]);
146   EXPECT_EQ(test_devices()[1], eligible_devices[3]);
147 }
148 
TEST_P(MultiDeviceSetupEligibleHostDevicesProviderImplTest,GetDevicesActivityStatus)149 TEST_P(MultiDeviceSetupEligibleHostDevicesProviderImplTest,
150        GetDevicesActivityStatus) {
151   SetBitsOnTestDevices();
152 
153   GetMutableRemoteDevice(test_devices()[0])->last_update_time_millis = 1;
154   GetMutableRemoteDevice(test_devices()[1])->last_update_time_millis = 25;
155   GetMutableRemoteDevice(test_devices()[2])->last_update_time_millis = 10;
156   GetMutableRemoteDevice(test_devices()[3])->last_update_time_millis = 100;
157   GetMutableRemoteDevice(test_devices()[4])->last_update_time_millis = 10000;
158 
159   multidevice::RemoteDeviceRefList devices{test_devices()[0], test_devices()[1],
160                                            test_devices()[2], test_devices()[3],
161                                            test_devices()[4]};
162   fake_device_sync_client()->set_synced_devices(devices);
163   fake_device_sync_client()->NotifyNewDevicesSynced();
164 
165   std::vector<device_sync::mojom::DeviceActivityStatusPtr>
166       device_activity_statuses;
167   device_activity_statuses.emplace_back(
168       device_sync::mojom::DeviceActivityStatus::New(
169           test_devices()[0].instance_id(), base::Time::FromTimeT(50),
170           cryptauthv2::ConnectivityStatus::ONLINE));
171   device_activity_statuses.emplace_back(
172       device_sync::mojom::DeviceActivityStatus::New(
173           test_devices()[1].instance_id(), base::Time::FromTimeT(100),
174           cryptauthv2::ConnectivityStatus::OFFLINE));
175   device_activity_statuses.emplace_back(
176       device_sync::mojom::DeviceActivityStatus::New(
177           test_devices()[2].instance_id(), base::Time::FromTimeT(200),
178           cryptauthv2::ConnectivityStatus::ONLINE));
179   device_activity_statuses.emplace_back(
180       device_sync::mojom::DeviceActivityStatus::New(
181           test_devices()[3].instance_id(), base::Time::FromTimeT(50),
182           cryptauthv2::ConnectivityStatus::ONLINE));
183   if (use_get_devices_activity_status()) {
184     fake_device_sync_client()->InvokePendingGetDevicesActivityStatusCallback(
185         device_sync::mojom::NetworkRequestResult::kSuccess,
186         std::move(device_activity_statuses));
187   }
188 
189   multidevice::DeviceWithConnectivityStatusList eligible_active_devices =
190       provider()->GetEligibleActiveHostDevices();
191   EXPECT_EQ(4u, eligible_active_devices.size());
192 
193   if (use_get_devices_activity_status()) {
194     EXPECT_EQ(test_devices()[2], eligible_active_devices[0].remote_device);
195     EXPECT_EQ(test_devices()[3], eligible_active_devices[1].remote_device);
196     EXPECT_EQ(test_devices()[0], eligible_active_devices[2].remote_device);
197     EXPECT_EQ(test_devices()[1], eligible_active_devices[3].remote_device);
198     EXPECT_EQ(cryptauthv2::ConnectivityStatus::ONLINE,
199               eligible_active_devices[0].connectivity_status);
200     EXPECT_EQ(cryptauthv2::ConnectivityStatus::ONLINE,
201               eligible_active_devices[1].connectivity_status);
202     EXPECT_EQ(cryptauthv2::ConnectivityStatus::ONLINE,
203               eligible_active_devices[2].connectivity_status);
204     EXPECT_EQ(cryptauthv2::ConnectivityStatus::OFFLINE,
205               eligible_active_devices[3].connectivity_status);
206   } else {
207     multidevice::RemoteDeviceRefList eligible_devices =
208         provider()->GetEligibleHostDevices();
209     EXPECT_EQ(4u, eligible_devices.size());
210     EXPECT_EQ(test_devices()[3], eligible_devices[0]);
211     EXPECT_EQ(test_devices()[1], eligible_devices[1]);
212     EXPECT_EQ(test_devices()[2], eligible_devices[2]);
213     EXPECT_EQ(test_devices()[0], eligible_devices[3]);
214 
215     for (size_t i = 0; i < 4; i++) {
216       EXPECT_EQ(eligible_devices[i], eligible_active_devices[i].remote_device);
217     }
218     for (size_t i = 0; i < 4; i++) {
219       EXPECT_EQ(cryptauthv2::ConnectivityStatus::UNKNOWN_CONNECTIVITY,
220                 eligible_active_devices[i].connectivity_status);
221     }
222   }
223 }
224 
TEST_P(MultiDeviceSetupEligibleHostDevicesProviderImplTest,GetDevicesActivityStatusFailedRequest)225 TEST_P(MultiDeviceSetupEligibleHostDevicesProviderImplTest,
226        GetDevicesActivityStatusFailedRequest) {
227   if (!use_get_devices_activity_status()) {
228     return;
229   }
230 
231   SetBitsOnTestDevices();
232   GetMutableRemoteDevice(test_devices()[0])->last_update_time_millis = 5;
233   GetMutableRemoteDevice(test_devices()[1])->last_update_time_millis = 4;
234   GetMutableRemoteDevice(test_devices()[2])->last_update_time_millis = 3;
235   GetMutableRemoteDevice(test_devices()[3])->last_update_time_millis = 2;
236   GetMutableRemoteDevice(test_devices()[4])->last_update_time_millis = 1;
237 
238   multidevice::RemoteDeviceRefList devices{test_devices()[0], test_devices()[1],
239                                            test_devices()[2], test_devices()[3],
240                                            test_devices()[4]};
241   fake_device_sync_client()->set_synced_devices(devices);
242   fake_device_sync_client()->NotifyNewDevicesSynced();
243   fake_device_sync_client()->InvokePendingGetDevicesActivityStatusCallback(
244       device_sync::mojom::NetworkRequestResult::kInternalServerError,
245       base::nullopt);
246 
247   multidevice::DeviceWithConnectivityStatusList eligible_active_devices =
248       provider()->GetEligibleActiveHostDevices();
249   multidevice::RemoteDeviceRefList eligible_devices =
250       provider()->GetEligibleHostDevices();
251   EXPECT_EQ(test_devices()[0], eligible_active_devices[0].remote_device);
252   EXPECT_EQ(test_devices()[1], eligible_active_devices[1].remote_device);
253   EXPECT_EQ(test_devices()[2], eligible_active_devices[2].remote_device);
254   EXPECT_EQ(test_devices()[3], eligible_active_devices[3].remote_device);
255   EXPECT_EQ(test_devices()[0], eligible_devices[0]);
256   EXPECT_EQ(test_devices()[1], eligible_devices[1]);
257   EXPECT_EQ(test_devices()[2], eligible_devices[2]);
258   EXPECT_EQ(test_devices()[3], eligible_devices[3]);
259 }
260 
261 INSTANTIATE_TEST_SUITE_P(All,
262                          MultiDeviceSetupEligibleHostDevicesProviderImplTest,
263                          testing::Bool());
264 
265 }  // namespace multidevice_setup
266 
267 }  // namespace chromeos
268