| // Copyright 2017 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chromeos/services/device_sync/software_feature_manager_impl.h" |
| |
| #include "base/bind.h" |
| #include "base/macros.h" |
| #include "chromeos/components/multidevice/remote_device_ref.h" |
| #include "chromeos/components/multidevice/remote_device_test_util.h" |
| #include "chromeos/components/multidevice/software_feature.h" |
| #include "chromeos/services/device_sync/fake_cryptauth_feature_status_setter.h" |
| #include "chromeos/services/device_sync/feature_status_change.h" |
| #include "chromeos/services/device_sync/mock_cryptauth_client.h" |
| #include "chromeos/services/device_sync/proto/enum_util.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| using testing::_; |
| using testing::Invoke; |
| |
| namespace chromeos { |
| |
| namespace device_sync { |
| |
| namespace { |
| |
| enum class Result { |
| kSuccess, |
| kErrorSettingSoftwareFeature, |
| kErrorSettingFeatureStatus, |
| kErrorFindingEligible |
| }; |
| |
| // Arbitrarily choose different error types which match to Result types. |
| const NetworkRequestError kErrorSettingSoftwareFeatureNetworkRequestError = |
| NetworkRequestError::kOffline; |
| const NetworkRequestError kErrorSettingFeatureStatusNetworkRequestError = |
| NetworkRequestError::kBadRequest; |
| const NetworkRequestError kErrorFindingEligibleNetworkRequestError = |
| NetworkRequestError::kEndpointNotFound; |
| |
| const char kBetterTogetherHostCallbackBluetoothAddress[] = |
| "BETTER_TOGETHER_HOST"; |
| const char kBetterTogetherClientCallbackBluetoothAddress[] = |
| "BETTER_TOGETHER_CLIENT"; |
| |
| const char kInstanceId0[] = "instanceId0"; |
| const char kInstanceId1[] = "instanceId1"; |
| const char kInstanceId2[] = "instanceId2"; |
| |
| std::vector<cryptauth::ExternalDeviceInfo> |
| CreateExternalDeviceInfosForRemoteDevices( |
| const multidevice::RemoteDeviceRefList remote_devices) { |
| std::vector<cryptauth::ExternalDeviceInfo> device_infos; |
| for (const auto& remote_device : remote_devices) { |
| // Add an cryptauth::ExternalDeviceInfo with the same public key as the |
| // multidevice::RemoteDevice. |
| cryptauth::ExternalDeviceInfo info; |
| info.set_public_key(remote_device.public_key()); |
| device_infos.push_back(info); |
| } |
| return device_infos; |
| } |
| |
| } // namespace |
| |
| class DeviceSyncSoftwareFeatureManagerImplTest |
| : public testing::Test, |
| public MockCryptAuthClientFactory::Observer, |
| public FakeCryptAuthFeatureStatusSetter::Delegate { |
| public: |
| DeviceSyncSoftwareFeatureManagerImplTest() |
| : all_test_external_device_infos_( |
| CreateExternalDeviceInfosForRemoteDevices( |
| multidevice::CreateRemoteDeviceRefListForTest(5))), |
| test_eligible_external_devices_infos_( |
| {all_test_external_device_infos_[0], |
| all_test_external_device_infos_[1], |
| all_test_external_device_infos_[2]}), |
| test_ineligible_external_devices_infos_( |
| {all_test_external_device_infos_[3], |
| all_test_external_device_infos_[4]}) {} |
| |
| void SetUp() override { |
| mock_cryptauth_client_factory_ = |
| std::make_unique<MockCryptAuthClientFactory>( |
| MockCryptAuthClientFactory::MockType::MAKE_NICE_MOCKS); |
| mock_cryptauth_client_factory_->AddObserver(this); |
| |
| fake_cryptauth_feature_status_setter_ = |
| std::make_unique<FakeCryptAuthFeatureStatusSetter>(); |
| fake_cryptauth_feature_status_setter_->set_delegate(this); |
| |
| software_feature_manager_ = SoftwareFeatureManagerImpl::Factory::Create( |
| mock_cryptauth_client_factory_.get(), |
| fake_cryptauth_feature_status_setter_.get()); |
| } |
| |
| void TearDown() override { |
| mock_cryptauth_client_factory_->RemoveObserver(this); |
| fake_cryptauth_feature_status_setter_->set_delegate(nullptr); |
| } |
| |
| void OnCryptAuthClientCreated(MockCryptAuthClient* client) override { |
| ON_CALL(*client, ToggleEasyUnlock(_, _, _)) |
| .WillByDefault(Invoke( |
| this, |
| &DeviceSyncSoftwareFeatureManagerImplTest::MockToggleEasyUnlock)); |
| ON_CALL(*client, FindEligibleUnlockDevices(_, _, _)) |
| .WillByDefault(Invoke(this, &DeviceSyncSoftwareFeatureManagerImplTest:: |
| MockFindEligibleUnlockDevices)); |
| } |
| |
| // Mock CryptAuthClient::ToggleEasyUnlock() implementation. |
| void MockToggleEasyUnlock(const cryptauth::ToggleEasyUnlockRequest& request, |
| CryptAuthClient::ToggleEasyUnlockCallback callback, |
| CryptAuthClient::ErrorCallback error_callback) { |
| last_toggle_request_ = request; |
| toggle_easy_unlock_callback_ = std::move(callback); |
| error_callback_ = std::move(error_callback); |
| error_code_ = kErrorSettingSoftwareFeatureNetworkRequestError; |
| } |
| |
| // Mock CryptAuthClient::FindEligibleUnlockDevices() implementation. |
| void MockFindEligibleUnlockDevices( |
| const cryptauth::FindEligibleUnlockDevicesRequest& request, |
| CryptAuthClient::FindEligibleUnlockDevicesCallback callback, |
| CryptAuthClient::ErrorCallback error_callback) { |
| last_find_request_ = request; |
| find_eligible_unlock_devices_callback_ = std::move(callback); |
| error_callback_ = std::move(error_callback); |
| error_code_ = kErrorFindingEligibleNetworkRequestError; |
| } |
| |
| // FakeCryptAuthFeatureStatusSetter::Delegate: |
| void OnSetFeatureStatusCalled() override { |
| error_code_ = kErrorSettingFeatureStatusNetworkRequestError; |
| } |
| |
| cryptauth::FindEligibleUnlockDevicesResponse |
| CreateFindEligibleUnlockDevicesResponse() { |
| cryptauth::FindEligibleUnlockDevicesResponse |
| find_eligible_unlock_devices_response; |
| for (const auto& device_info : test_eligible_external_devices_infos_) { |
| find_eligible_unlock_devices_response.add_eligible_devices()->CopyFrom( |
| device_info); |
| } |
| for (const auto& device_info : test_ineligible_external_devices_infos_) { |
| find_eligible_unlock_devices_response.add_ineligible_devices() |
| ->mutable_device() |
| ->CopyFrom(device_info); |
| } |
| return find_eligible_unlock_devices_response; |
| } |
| |
| void VerifyDeviceEligibility() { |
| // Ensure that resulting devices are not empty. Otherwise, following for |
| // loop checks will succeed on empty resulting devices. |
| EXPECT_TRUE(result_eligible_devices_.size() > 0); |
| EXPECT_TRUE(result_ineligible_devices_.size() > 0); |
| for (const auto& device_info : result_eligible_devices_) { |
| EXPECT_TRUE( |
| std::find_if( |
| test_eligible_external_devices_infos_.begin(), |
| test_eligible_external_devices_infos_.end(), |
| [&device_info](const cryptauth::ExternalDeviceInfo& device) { |
| return device.public_key() == device_info.public_key(); |
| }) != test_eligible_external_devices_infos_.end()); |
| } |
| for (const auto& ineligible_device : result_ineligible_devices_) { |
| EXPECT_TRUE( |
| std::find_if(test_ineligible_external_devices_infos_.begin(), |
| test_ineligible_external_devices_infos_.end(), |
| [&ineligible_device]( |
| const cryptauth::ExternalDeviceInfo& device) { |
| return device.public_key() == |
| ineligible_device.device().public_key(); |
| }) != test_ineligible_external_devices_infos_.end()); |
| } |
| result_eligible_devices_.clear(); |
| result_ineligible_devices_.clear(); |
| } |
| |
| void SetSoftwareFeatureState(multidevice::SoftwareFeature feature, |
| const cryptauth::ExternalDeviceInfo& device_info, |
| bool enabled, |
| bool is_exclusive = false) { |
| software_feature_manager_->SetSoftwareFeatureState( |
| device_info.public_key(), feature, enabled, |
| base::BindOnce(&DeviceSyncSoftwareFeatureManagerImplTest:: |
| OnSoftwareFeatureStateSet, |
| base::Unretained(this)), |
| base::BindOnce(&DeviceSyncSoftwareFeatureManagerImplTest::OnError, |
| base::Unretained(this)), |
| is_exclusive); |
| } |
| |
| void SetFeatureStatus(const std::string& device_id, |
| multidevice::SoftwareFeature feature, |
| FeatureStatusChange status_change) { |
| software_feature_manager_->SetFeatureStatus( |
| device_id, feature, status_change, |
| base::BindOnce( |
| &DeviceSyncSoftwareFeatureManagerImplTest::OnFeatureStatusSet, |
| base::Unretained(this)), |
| base::BindOnce(&DeviceSyncSoftwareFeatureManagerImplTest::OnError, |
| base::Unretained(this))); |
| } |
| |
| void FindEligibleDevices(multidevice::SoftwareFeature feature) { |
| software_feature_manager_->FindEligibleDevices( |
| feature, |
| base::BindOnce( |
| &DeviceSyncSoftwareFeatureManagerImplTest::OnEligibleDevicesFound, |
| base::Unretained(this)), |
| base::BindOnce(&DeviceSyncSoftwareFeatureManagerImplTest::OnError, |
| base::Unretained(this))); |
| } |
| |
| void VerifyLastSetFeatureStatusRequest( |
| const std::string& expected_device_id, |
| multidevice::SoftwareFeature expected_feature, |
| FeatureStatusChange expected_status_change) { |
| ASSERT_EQ(1u, fake_cryptauth_feature_status_setter_->requests().size()); |
| EXPECT_EQ( |
| expected_device_id, |
| fake_cryptauth_feature_status_setter_->requests().back().device_id); |
| EXPECT_EQ(expected_feature, |
| fake_cryptauth_feature_status_setter_->requests().back().feature); |
| EXPECT_EQ( |
| expected_status_change, |
| fake_cryptauth_feature_status_setter_->requests().back().status_change); |
| } |
| |
| void OnSoftwareFeatureStateSet() { result_ = Result::kSuccess; } |
| |
| void OnFeatureStatusSet() { result_ = Result::kSuccess; } |
| |
| void OnEligibleDevicesFound( |
| const std::vector<cryptauth::ExternalDeviceInfo>& eligible_devices, |
| const std::vector<cryptauth::IneligibleDevice>& ineligible_devices) { |
| result_ = Result::kSuccess; |
| result_eligible_devices_ = eligible_devices; |
| result_ineligible_devices_ = ineligible_devices; |
| } |
| |
| void OnError(NetworkRequestError error) { |
| if (error == kErrorSettingSoftwareFeatureNetworkRequestError) |
| result_ = Result::kErrorSettingSoftwareFeature; |
| else if (error == kErrorSettingFeatureStatusNetworkRequestError) |
| result_ = Result::kErrorSettingFeatureStatus; |
| else if (error == kErrorFindingEligibleNetworkRequestError) |
| result_ = Result::kErrorFindingEligible; |
| else |
| NOTREACHED(); |
| } |
| |
| void InvokeSetSoftwareFeatureCallback() { |
| CryptAuthClient::ToggleEasyUnlockCallback success_callback = |
| std::move(toggle_easy_unlock_callback_); |
| ASSERT_TRUE(!success_callback.is_null()); |
| std::move(success_callback).Run(cryptauth::ToggleEasyUnlockResponse()); |
| } |
| |
| void InvokeSetFeatureStatusCallback() { |
| ASSERT_EQ(1u, fake_cryptauth_feature_status_setter_->requests().size()); |
| |
| base::OnceClosure success_callback = |
| std::move(fake_cryptauth_feature_status_setter_->requests() |
| .back() |
| .success_callback); |
| ASSERT_FALSE(success_callback.is_null()); |
| fake_cryptauth_feature_status_setter_->requests().pop_back(); |
| |
| std::move(success_callback).Run(); |
| } |
| |
| void InvokeFindEligibleDevicesCallback( |
| const cryptauth::FindEligibleUnlockDevicesResponse& |
| retrieved_devices_response) { |
| CryptAuthClient::FindEligibleUnlockDevicesCallback success_callback = |
| std::move(find_eligible_unlock_devices_callback_); |
| ASSERT_TRUE(!success_callback.is_null()); |
| std::move(success_callback).Run(retrieved_devices_response); |
| } |
| |
| void InvokeErrorCallback() { |
| CryptAuthClient::ErrorCallback error_callback = std::move(error_callback_); |
| ASSERT_TRUE(!error_callback.is_null()); |
| std::move(error_callback).Run(*error_code_); |
| } |
| |
| void InvokeSetFeatureStatusErrorCallback() { |
| ASSERT_EQ(1u, fake_cryptauth_feature_status_setter_->requests().size()); |
| |
| base::OnceCallback<void(NetworkRequestError)> error_callback = |
| std::move(fake_cryptauth_feature_status_setter_->requests() |
| .back() |
| .error_callback); |
| ASSERT_FALSE(error_callback.is_null()); |
| fake_cryptauth_feature_status_setter_->requests().pop_back(); |
| |
| std::move(error_callback).Run(*error_code_); |
| } |
| |
| Result GetResultAndReset() { |
| EXPECT_TRUE(result_); |
| Result result = *result_; |
| result_.reset(); |
| return result; |
| } |
| |
| const std::vector<cryptauth::ExternalDeviceInfo> |
| all_test_external_device_infos_; |
| const std::vector<cryptauth::ExternalDeviceInfo> |
| test_eligible_external_devices_infos_; |
| const std::vector<cryptauth::ExternalDeviceInfo> |
| test_ineligible_external_devices_infos_; |
| |
| std::unique_ptr<FakeCryptAuthFeatureStatusSetter> |
| fake_cryptauth_feature_status_setter_; |
| std::unique_ptr<MockCryptAuthClientFactory> mock_cryptauth_client_factory_; |
| std::unique_ptr<SoftwareFeatureManager> software_feature_manager_; |
| |
| CryptAuthClient::ErrorCallback error_callback_; |
| |
| // Set when a CryptAuthClient function returns. If empty, no callback has been |
| // invoked. |
| base::Optional<Result> result_; |
| |
| // The code passed to the error callback; varies depending on what |
| // CryptAuthClient function is invoked. |
| base::Optional<NetworkRequestError> error_code_; |
| |
| // For SetSoftwareFeatureState() tests. |
| cryptauth::ToggleEasyUnlockRequest last_toggle_request_; |
| CryptAuthClient::ToggleEasyUnlockCallback toggle_easy_unlock_callback_; |
| |
| // For FindEligibleDevices() tests. |
| cryptauth::FindEligibleUnlockDevicesRequest last_find_request_; |
| CryptAuthClient::FindEligibleUnlockDevicesCallback |
| find_eligible_unlock_devices_callback_; |
| std::vector<cryptauth::ExternalDeviceInfo> result_eligible_devices_; |
| std::vector<cryptauth::IneligibleDevice> result_ineligible_devices_; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(DeviceSyncSoftwareFeatureManagerImplTest); |
| }; |
| |
| TEST_F(DeviceSyncSoftwareFeatureManagerImplTest, |
| TestOrderUponMultipleRequests) { |
| SetSoftwareFeatureState(multidevice::SoftwareFeature::kBetterTogetherHost, |
| test_eligible_external_devices_infos_[0], |
| true /* enable */); |
| SetFeatureStatus(kInstanceId0, |
| multidevice::SoftwareFeature::kBetterTogetherHost, |
| FeatureStatusChange::kEnableExclusively); |
| FindEligibleDevices(multidevice::SoftwareFeature::kBetterTogetherHost); |
| SetSoftwareFeatureState(multidevice::SoftwareFeature::kBetterTogetherClient, |
| test_eligible_external_devices_infos_[1], |
| false /* enable */); |
| SetFeatureStatus(kInstanceId1, |
| multidevice::SoftwareFeature::kBetterTogetherClient, |
| FeatureStatusChange::kEnableNonExclusively); |
| FindEligibleDevices(multidevice::SoftwareFeature::kBetterTogetherClient); |
| |
| EXPECT_EQ(SoftwareFeatureEnumToString( |
| cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST), |
| last_toggle_request_.feature()); |
| EXPECT_EQ(true, last_toggle_request_.enable()); |
| EXPECT_EQ(false, last_toggle_request_.is_exclusive()); |
| InvokeSetSoftwareFeatureCallback(); |
| EXPECT_EQ(Result::kSuccess, GetResultAndReset()); |
| |
| VerifyLastSetFeatureStatusRequest( |
| kInstanceId0, multidevice::SoftwareFeature::kBetterTogetherHost, |
| FeatureStatusChange::kEnableExclusively); |
| InvokeSetFeatureStatusCallback(); |
| EXPECT_EQ(Result::kSuccess, GetResultAndReset()); |
| |
| EXPECT_EQ(SoftwareFeatureEnumToString( |
| cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST), |
| last_find_request_.feature()); |
| EXPECT_EQ(kBetterTogetherHostCallbackBluetoothAddress, |
| last_find_request_.callback_bluetooth_address()); |
| InvokeFindEligibleDevicesCallback(CreateFindEligibleUnlockDevicesResponse()); |
| EXPECT_EQ(Result::kSuccess, GetResultAndReset()); |
| VerifyDeviceEligibility(); |
| |
| EXPECT_EQ(SoftwareFeatureEnumToString( |
| cryptauth::SoftwareFeature::BETTER_TOGETHER_CLIENT), |
| last_toggle_request_.feature()); |
| EXPECT_EQ(false, last_toggle_request_.enable()); |
| EXPECT_EQ(false, last_toggle_request_.is_exclusive()); |
| InvokeSetSoftwareFeatureCallback(); |
| EXPECT_EQ(Result::kSuccess, GetResultAndReset()); |
| |
| VerifyLastSetFeatureStatusRequest( |
| kInstanceId1, multidevice::SoftwareFeature::kBetterTogetherClient, |
| FeatureStatusChange::kEnableNonExclusively); |
| InvokeSetFeatureStatusCallback(); |
| EXPECT_EQ(Result::kSuccess, GetResultAndReset()); |
| |
| EXPECT_EQ(SoftwareFeatureEnumToString( |
| cryptauth::SoftwareFeature::BETTER_TOGETHER_CLIENT), |
| last_find_request_.feature()); |
| EXPECT_EQ(kBetterTogetherClientCallbackBluetoothAddress, |
| last_find_request_.callback_bluetooth_address()); |
| InvokeFindEligibleDevicesCallback(CreateFindEligibleUnlockDevicesResponse()); |
| EXPECT_EQ(Result::kSuccess, GetResultAndReset()); |
| VerifyDeviceEligibility(); |
| } |
| |
| TEST_F(DeviceSyncSoftwareFeatureManagerImplTest, |
| TestMultipleSetUnlocksRequests) { |
| SetSoftwareFeatureState(multidevice::SoftwareFeature::kBetterTogetherHost, |
| test_eligible_external_devices_infos_[0], |
| true /* enable */); |
| SetSoftwareFeatureState(multidevice::SoftwareFeature::kBetterTogetherClient, |
| test_eligible_external_devices_infos_[1], |
| false /* enable */); |
| SetSoftwareFeatureState(multidevice::SoftwareFeature::kBetterTogetherHost, |
| test_eligible_external_devices_infos_[2], |
| true /* enable */); |
| |
| EXPECT_EQ(SoftwareFeatureEnumToString( |
| cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST), |
| last_toggle_request_.feature()); |
| EXPECT_EQ(true, last_toggle_request_.enable()); |
| EXPECT_EQ(false, last_toggle_request_.is_exclusive()); |
| InvokeErrorCallback(); |
| EXPECT_EQ(Result::kErrorSettingSoftwareFeature, GetResultAndReset()); |
| |
| EXPECT_EQ(SoftwareFeatureEnumToString( |
| cryptauth::SoftwareFeature::BETTER_TOGETHER_CLIENT), |
| last_toggle_request_.feature()); |
| EXPECT_EQ(false, last_toggle_request_.enable()); |
| EXPECT_EQ(false, last_toggle_request_.is_exclusive()); |
| InvokeSetSoftwareFeatureCallback(); |
| EXPECT_EQ(Result::kSuccess, GetResultAndReset()); |
| |
| EXPECT_EQ(SoftwareFeatureEnumToString( |
| cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST), |
| last_toggle_request_.feature()); |
| EXPECT_EQ(true, last_toggle_request_.enable()); |
| EXPECT_EQ(false, last_toggle_request_.is_exclusive()); |
| InvokeSetSoftwareFeatureCallback(); |
| EXPECT_EQ(Result::kSuccess, GetResultAndReset()); |
| } |
| |
| TEST_F(DeviceSyncSoftwareFeatureManagerImplTest, |
| TestMultipleSetFeatureStatusRequests) { |
| SetFeatureStatus(kInstanceId0, |
| multidevice::SoftwareFeature::kBetterTogetherHost, |
| FeatureStatusChange::kEnableExclusively); |
| SetFeatureStatus(kInstanceId1, |
| multidevice::SoftwareFeature::kBetterTogetherClient, |
| FeatureStatusChange::kEnableNonExclusively); |
| SetFeatureStatus(kInstanceId2, |
| multidevice::SoftwareFeature::kBetterTogetherHost, |
| FeatureStatusChange::kEnableNonExclusively); |
| |
| VerifyLastSetFeatureStatusRequest( |
| kInstanceId0, multidevice::SoftwareFeature::kBetterTogetherHost, |
| FeatureStatusChange::kEnableExclusively); |
| InvokeSetFeatureStatusErrorCallback(); |
| EXPECT_EQ(Result::kErrorSettingFeatureStatus, GetResultAndReset()); |
| |
| VerifyLastSetFeatureStatusRequest( |
| kInstanceId1, multidevice::SoftwareFeature::kBetterTogetherClient, |
| FeatureStatusChange::kEnableNonExclusively); |
| InvokeSetFeatureStatusCallback(); |
| EXPECT_EQ(Result::kSuccess, GetResultAndReset()); |
| |
| VerifyLastSetFeatureStatusRequest( |
| kInstanceId2, multidevice::SoftwareFeature::kBetterTogetherHost, |
| FeatureStatusChange::kEnableNonExclusively); |
| InvokeSetFeatureStatusCallback(); |
| EXPECT_EQ(Result::kSuccess, GetResultAndReset()); |
| } |
| |
| TEST_F(DeviceSyncSoftwareFeatureManagerImplTest, |
| TestMultipleFindEligibleForUnlockDevicesRequests) { |
| FindEligibleDevices(multidevice::SoftwareFeature::kBetterTogetherHost); |
| FindEligibleDevices(multidevice::SoftwareFeature::kBetterTogetherClient); |
| FindEligibleDevices(multidevice::SoftwareFeature::kBetterTogetherHost); |
| |
| EXPECT_EQ(SoftwareFeatureEnumToString( |
| cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST), |
| last_find_request_.feature()); |
| EXPECT_EQ(kBetterTogetherHostCallbackBluetoothAddress, |
| last_find_request_.callback_bluetooth_address()); |
| InvokeFindEligibleDevicesCallback(CreateFindEligibleUnlockDevicesResponse()); |
| EXPECT_EQ(Result::kSuccess, GetResultAndReset()); |
| VerifyDeviceEligibility(); |
| |
| EXPECT_EQ(SoftwareFeatureEnumToString( |
| cryptauth::SoftwareFeature::BETTER_TOGETHER_CLIENT), |
| last_find_request_.feature()); |
| EXPECT_EQ(kBetterTogetherClientCallbackBluetoothAddress, |
| last_find_request_.callback_bluetooth_address()); |
| InvokeErrorCallback(); |
| EXPECT_EQ(Result::kErrorFindingEligible, GetResultAndReset()); |
| |
| EXPECT_EQ(SoftwareFeatureEnumToString( |
| cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST), |
| last_find_request_.feature()); |
| EXPECT_EQ(kBetterTogetherHostCallbackBluetoothAddress, |
| last_find_request_.callback_bluetooth_address()); |
| InvokeFindEligibleDevicesCallback(CreateFindEligibleUnlockDevicesResponse()); |
| EXPECT_EQ(Result::kSuccess, GetResultAndReset()); |
| VerifyDeviceEligibility(); |
| } |
| |
| TEST_F(DeviceSyncSoftwareFeatureManagerImplTest, TestOrderViaMultipleErrors) { |
| SetSoftwareFeatureState(multidevice::SoftwareFeature::kBetterTogetherHost, |
| test_eligible_external_devices_infos_[0], |
| true /* enable */); |
| SetFeatureStatus(kInstanceId0, |
| multidevice::SoftwareFeature::kBetterTogetherHost, |
| FeatureStatusChange::kEnableExclusively); |
| FindEligibleDevices(multidevice::SoftwareFeature::kBetterTogetherHost); |
| |
| EXPECT_EQ(SoftwareFeatureEnumToString( |
| cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST), |
| last_toggle_request_.feature()); |
| InvokeErrorCallback(); |
| EXPECT_EQ(Result::kErrorSettingSoftwareFeature, GetResultAndReset()); |
| |
| VerifyLastSetFeatureStatusRequest( |
| kInstanceId0, multidevice::SoftwareFeature::kBetterTogetherHost, |
| FeatureStatusChange::kEnableExclusively); |
| InvokeSetFeatureStatusErrorCallback(); |
| EXPECT_EQ(Result::kErrorSettingFeatureStatus, GetResultAndReset()); |
| |
| EXPECT_EQ(SoftwareFeatureEnumToString( |
| cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST), |
| last_find_request_.feature()); |
| EXPECT_EQ(kBetterTogetherHostCallbackBluetoothAddress, |
| last_find_request_.callback_bluetooth_address()); |
| InvokeErrorCallback(); |
| EXPECT_EQ(Result::kErrorFindingEligible, GetResultAndReset()); |
| } |
| |
| TEST_F(DeviceSyncSoftwareFeatureManagerImplTest, TestIsExclusive) { |
| SetSoftwareFeatureState(multidevice::SoftwareFeature::kBetterTogetherHost, |
| test_eligible_external_devices_infos_[0], |
| true /* enable */, true /* is_exclusive */); |
| |
| EXPECT_EQ(SoftwareFeatureEnumToString( |
| cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST), |
| last_toggle_request_.feature()); |
| EXPECT_EQ(true, last_toggle_request_.enable()); |
| EXPECT_EQ(true, last_toggle_request_.is_exclusive()); |
| InvokeErrorCallback(); |
| EXPECT_EQ(Result::kErrorSettingSoftwareFeature, GetResultAndReset()); |
| } |
| |
| TEST_F(DeviceSyncSoftwareFeatureManagerImplTest, TestEasyUnlockSpecialCase) { |
| SetSoftwareFeatureState(multidevice::SoftwareFeature::kSmartLockHost, |
| test_eligible_external_devices_infos_[0], |
| false /* enable */); |
| |
| EXPECT_EQ( |
| SoftwareFeatureEnumToString(cryptauth::SoftwareFeature::EASY_UNLOCK_HOST), |
| last_toggle_request_.feature()); |
| EXPECT_EQ(false, last_toggle_request_.enable()); |
| // apply_to_all() should be false when disabling EasyUnlock host capabilities. |
| EXPECT_EQ(true, last_toggle_request_.apply_to_all()); |
| EXPECT_FALSE(last_toggle_request_.has_public_key()); |
| InvokeErrorCallback(); |
| EXPECT_EQ(Result::kErrorSettingSoftwareFeature, GetResultAndReset()); |
| } |
| |
| } // namespace device_sync |
| |
| } // namespace chromeos |