blob: 7cb0576ed45b25b1f94bc7feca80c065952d380d [file] [log] [blame]
// Copyright 2018 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 <algorithm>
#include <memory>
#include <vector>
#include "base/run_loop.h"
#include "base/test/scoped_task_environment.h"
#include "chromeos/services/device_sync/public/cpp/fake_device_sync_client.h"
#include "chromeos/services/multidevice_setup/account_status_change_delegate_notifier_impl.h"
#include "chromeos/services/multidevice_setup/eligible_host_devices_provider_impl.h"
#include "chromeos/services/multidevice_setup/fake_account_status_change_delegate.h"
#include "chromeos/services/multidevice_setup/fake_account_status_change_delegate_notifier.h"
#include "chromeos/services/multidevice_setup/fake_eligible_host_devices_provider.h"
#include "chromeos/services/multidevice_setup/fake_host_backend_delegate.h"
#include "chromeos/services/multidevice_setup/fake_host_status_observer.h"
#include "chromeos/services/multidevice_setup/fake_host_status_provider.h"
#include "chromeos/services/multidevice_setup/fake_host_verifier.h"
#include "chromeos/services/multidevice_setup/fake_setup_flow_completion_recorder.h"
#include "chromeos/services/multidevice_setup/host_backend_delegate_impl.h"
#include "chromeos/services/multidevice_setup/host_status_provider_impl.h"
#include "chromeos/services/multidevice_setup/host_verifier_impl.h"
#include "chromeos/services/multidevice_setup/multidevice_setup_impl.h"
#include "chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom.h"
#include "chromeos/services/multidevice_setup/setup_flow_completion_recorder_impl.h"
#include "chromeos/services/secure_channel/public/cpp/client/fake_secure_channel_client.h"
#include "components/cryptauth/remote_device_test_util.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
namespace multidevice_setup {
namespace {
const size_t kNumTestDevices = 3;
cryptauth::RemoteDeviceList RefListToRawList(
const cryptauth::RemoteDeviceRefList& ref_list) {
cryptauth::RemoteDeviceList raw_list;
std::transform(ref_list.begin(), ref_list.end(), std::back_inserter(raw_list),
[](const cryptauth::RemoteDeviceRef ref) {
return *GetMutableRemoteDevice(ref);
});
return raw_list;
}
base::Optional<cryptauth::RemoteDevice> RefToRaw(
const base::Optional<cryptauth::RemoteDeviceRef>& ref) {
if (!ref)
return base::nullopt;
return *GetMutableRemoteDevice(*ref);
}
class FakeEligibleHostDevicesProviderFactory
: public EligibleHostDevicesProviderImpl::Factory {
public:
FakeEligibleHostDevicesProviderFactory(
device_sync::FakeDeviceSyncClient* expected_device_sync_client)
: expected_device_sync_client_(expected_device_sync_client) {}
~FakeEligibleHostDevicesProviderFactory() override = default;
FakeEligibleHostDevicesProvider* instance() { return instance_; }
private:
// EligibleHostDevicesProviderImpl::Factory:
std::unique_ptr<EligibleHostDevicesProvider> BuildInstance(
device_sync::DeviceSyncClient* device_sync_client) override {
EXPECT_FALSE(instance_);
EXPECT_EQ(expected_device_sync_client_, device_sync_client);
auto instance = std::make_unique<FakeEligibleHostDevicesProvider>();
instance_ = instance.get();
return instance;
}
device_sync::FakeDeviceSyncClient* expected_device_sync_client_;
FakeEligibleHostDevicesProvider* instance_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(FakeEligibleHostDevicesProviderFactory);
};
class FakeHostBackendDelegateFactory : public HostBackendDelegateImpl::Factory {
public:
FakeHostBackendDelegateFactory(
FakeEligibleHostDevicesProviderFactory*
fake_eligible_host_devices_provider_factory,
sync_preferences::TestingPrefServiceSyncable*
expected_testing_pref_service,
device_sync::FakeDeviceSyncClient* expected_device_sync_client)
: fake_eligible_host_devices_provider_factory_(
fake_eligible_host_devices_provider_factory),
expected_testing_pref_service_(expected_testing_pref_service),
expected_device_sync_client_(expected_device_sync_client) {}
~FakeHostBackendDelegateFactory() override = default;
FakeHostBackendDelegate* instance() { return instance_; }
private:
// HostBackendDelegateImpl::Factory:
std::unique_ptr<HostBackendDelegate> BuildInstance(
EligibleHostDevicesProvider* eligible_host_devices_provider,
PrefService* pref_service,
device_sync::DeviceSyncClient* device_sync_client,
std::unique_ptr<base::OneShotTimer> timer) override {
EXPECT_FALSE(instance_);
EXPECT_EQ(fake_eligible_host_devices_provider_factory_->instance(),
eligible_host_devices_provider);
EXPECT_EQ(expected_testing_pref_service_, pref_service);
EXPECT_EQ(expected_device_sync_client_, device_sync_client);
auto instance = std::make_unique<FakeHostBackendDelegate>();
instance_ = instance.get();
return instance;
}
FakeEligibleHostDevicesProviderFactory*
fake_eligible_host_devices_provider_factory_;
sync_preferences::TestingPrefServiceSyncable* expected_testing_pref_service_;
device_sync::FakeDeviceSyncClient* expected_device_sync_client_;
FakeHostBackendDelegate* instance_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(FakeHostBackendDelegateFactory);
};
class FakeHostVerifierFactory : public HostVerifierImpl::Factory {
public:
FakeHostVerifierFactory(
FakeHostBackendDelegateFactory* fake_host_backend_delegate_factory,
device_sync::FakeDeviceSyncClient* expected_device_sync_client,
sync_preferences::TestingPrefServiceSyncable*
expected_testing_pref_service)
: fake_host_backend_delegate_factory_(fake_host_backend_delegate_factory),
expected_device_sync_client_(expected_device_sync_client),
expected_testing_pref_service_(expected_testing_pref_service) {}
~FakeHostVerifierFactory() override = default;
FakeHostVerifier* instance() { return instance_; }
private:
// HostVerifierImpl::Factory:
std::unique_ptr<HostVerifier> BuildInstance(
HostBackendDelegate* host_backend_delegate,
device_sync::DeviceSyncClient* device_sync_client,
PrefService* pref_service,
base::Clock* clock,
std::unique_ptr<base::OneShotTimer> timer) override {
EXPECT_FALSE(instance_);
EXPECT_EQ(fake_host_backend_delegate_factory_->instance(),
host_backend_delegate);
EXPECT_EQ(expected_device_sync_client_, device_sync_client);
EXPECT_EQ(expected_testing_pref_service_, pref_service);
auto instance = std::make_unique<FakeHostVerifier>();
instance_ = instance.get();
return instance;
}
FakeHostBackendDelegateFactory* fake_host_backend_delegate_factory_;
device_sync::FakeDeviceSyncClient* expected_device_sync_client_;
sync_preferences::TestingPrefServiceSyncable* expected_testing_pref_service_;
FakeHostVerifier* instance_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(FakeHostVerifierFactory);
};
class FakeHostStatusProviderFactory : public HostStatusProviderImpl::Factory {
public:
FakeHostStatusProviderFactory(
FakeEligibleHostDevicesProviderFactory*
fake_eligible_host_devices_provider_factory,
FakeHostBackendDelegateFactory* fake_host_backend_delegate_factory,
FakeHostVerifierFactory* fake_host_verifier_factory,
device_sync::FakeDeviceSyncClient* expected_device_sync_client)
: fake_eligible_host_devices_provider_factory_(
fake_eligible_host_devices_provider_factory),
fake_host_backend_delegate_factory_(fake_host_backend_delegate_factory),
fake_host_verifier_factory_(fake_host_verifier_factory),
expected_device_sync_client_(expected_device_sync_client) {}
~FakeHostStatusProviderFactory() override = default;
FakeHostStatusProvider* instance() { return instance_; }
private:
// HostStatusProviderImpl::Factory:
std::unique_ptr<HostStatusProvider> BuildInstance(
EligibleHostDevicesProvider* eligible_host_devices_provider,
HostBackendDelegate* host_backend_delegate,
HostVerifier* host_verifier,
device_sync::DeviceSyncClient* device_sync_client) override {
EXPECT_FALSE(instance_);
EXPECT_EQ(fake_eligible_host_devices_provider_factory_->instance(),
eligible_host_devices_provider);
EXPECT_EQ(fake_host_backend_delegate_factory_->instance(),
host_backend_delegate);
EXPECT_EQ(fake_host_verifier_factory_->instance(), host_verifier);
EXPECT_EQ(expected_device_sync_client_, device_sync_client);
auto instance = std::make_unique<FakeHostStatusProvider>();
instance_ = instance.get();
return instance;
}
FakeEligibleHostDevicesProviderFactory*
fake_eligible_host_devices_provider_factory_;
FakeHostBackendDelegateFactory* fake_host_backend_delegate_factory_;
FakeHostVerifierFactory* fake_host_verifier_factory_;
device_sync::FakeDeviceSyncClient* expected_device_sync_client_;
FakeHostStatusProvider* instance_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(FakeHostStatusProviderFactory);
};
class FakeSetupFlowCompletionRecorderFactory
: public SetupFlowCompletionRecorderImpl::Factory {
public:
FakeSetupFlowCompletionRecorderFactory(
sync_preferences::TestingPrefServiceSyncable*
expected_testing_pref_service)
: expected_testing_pref_service_(expected_testing_pref_service) {}
~FakeSetupFlowCompletionRecorderFactory() override = default;
FakeSetupFlowCompletionRecorder* instance() { return instance_; }
private:
// SetupFlowCompletionRecorderImpl::Factory:
std::unique_ptr<SetupFlowCompletionRecorder> BuildInstance(
PrefService* pref_service,
base::Clock* clock) override {
EXPECT_FALSE(instance_);
EXPECT_EQ(expected_testing_pref_service_, pref_service);
auto instance = std::make_unique<FakeSetupFlowCompletionRecorder>();
instance_ = instance.get();
return instance;
}
sync_preferences::TestingPrefServiceSyncable* expected_testing_pref_service_;
FakeSetupFlowCompletionRecorder* instance_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(FakeSetupFlowCompletionRecorderFactory);
};
class FakeAccountStatusChangeDelegateNotifierFactory
: public AccountStatusChangeDelegateNotifierImpl::Factory {
public:
FakeAccountStatusChangeDelegateNotifierFactory(
device_sync::FakeDeviceSyncClient* expected_device_sync_client,
sync_preferences::TestingPrefServiceSyncable*
expected_testing_pref_service,
FakeSetupFlowCompletionRecorderFactory*
fake_setup_flow_completion_recorder_factory)
: expected_device_sync_client_(expected_device_sync_client),
expected_testing_pref_service_(expected_testing_pref_service),
fake_setup_flow_completion_recorder_factory_(
fake_setup_flow_completion_recorder_factory) {}
~FakeAccountStatusChangeDelegateNotifierFactory() override = default;
FakeAccountStatusChangeDelegateNotifier* instance() { return instance_; }
private:
// AccountStatusChangeDelegateNotifierImpl::Factory:
std::unique_ptr<AccountStatusChangeDelegateNotifier> BuildInstance(
device_sync::DeviceSyncClient* device_sync_client,
PrefService* pref_service,
SetupFlowCompletionRecorder* setup_flow_completion_recorder,
base::Clock* clock) override {
EXPECT_FALSE(instance_);
EXPECT_EQ(expected_device_sync_client_, device_sync_client);
EXPECT_EQ(expected_testing_pref_service_, pref_service);
EXPECT_EQ(fake_setup_flow_completion_recorder_factory_->instance(),
setup_flow_completion_recorder);
auto instance = std::make_unique<FakeAccountStatusChangeDelegateNotifier>();
instance_ = instance.get();
return instance;
}
device_sync::FakeDeviceSyncClient* expected_device_sync_client_;
sync_preferences::TestingPrefServiceSyncable* expected_testing_pref_service_;
FakeSetupFlowCompletionRecorderFactory*
fake_setup_flow_completion_recorder_factory_;
FakeAccountStatusChangeDelegateNotifier* instance_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(FakeAccountStatusChangeDelegateNotifierFactory);
};
} // namespace
class MultiDeviceSetupImplTest : public testing::Test {
protected:
MultiDeviceSetupImplTest()
: test_devices_(
cryptauth::CreateRemoteDeviceRefListForTest(kNumTestDevices)) {}
~MultiDeviceSetupImplTest() override = default;
void SetUp() override {
test_pref_service_ =
std::make_unique<sync_preferences::TestingPrefServiceSyncable>();
fake_device_sync_client_ =
std::make_unique<device_sync::FakeDeviceSyncClient>();
fake_secure_channel_client_ =
std::make_unique<secure_channel::FakeSecureChannelClient>();
fake_eligible_host_devices_provider_factory_ =
std::make_unique<FakeEligibleHostDevicesProviderFactory>(
fake_device_sync_client_.get());
EligibleHostDevicesProviderImpl::Factory::SetFactoryForTesting(
fake_eligible_host_devices_provider_factory_.get());
fake_host_backend_delegate_factory_ =
std::make_unique<FakeHostBackendDelegateFactory>(
fake_eligible_host_devices_provider_factory_.get(),
test_pref_service_.get(), fake_device_sync_client_.get());
HostBackendDelegateImpl::Factory::SetFactoryForTesting(
fake_host_backend_delegate_factory_.get());
fake_host_verifier_factory_ = std::make_unique<FakeHostVerifierFactory>(
fake_host_backend_delegate_factory_.get(),
fake_device_sync_client_.get(), test_pref_service_.get());
HostVerifierImpl::Factory::SetFactoryForTesting(
fake_host_verifier_factory_.get());
fake_host_status_provider_factory_ =
std::make_unique<FakeHostStatusProviderFactory>(
fake_eligible_host_devices_provider_factory_.get(),
fake_host_backend_delegate_factory_.get(),
fake_host_verifier_factory_.get(), fake_device_sync_client_.get());
HostStatusProviderImpl::Factory::SetFactoryForTesting(
fake_host_status_provider_factory_.get());
fake_setup_flow_completion_recorder_factory_ =
std::make_unique<FakeSetupFlowCompletionRecorderFactory>(
test_pref_service_.get());
SetupFlowCompletionRecorderImpl::Factory::SetFactoryForTesting(
fake_setup_flow_completion_recorder_factory_.get());
fake_account_status_change_delegate_notifier_factory_ =
std::make_unique<FakeAccountStatusChangeDelegateNotifierFactory>(
fake_device_sync_client_.get(), test_pref_service_.get(),
fake_setup_flow_completion_recorder_factory_.get());
AccountStatusChangeDelegateNotifierImpl::Factory::SetFactoryForTesting(
fake_account_status_change_delegate_notifier_factory_.get());
multidevice_setup_ = MultiDeviceSetupImpl::Factory::Get()->BuildInstance(
test_pref_service_.get(), fake_device_sync_client_.get(),
fake_secure_channel_client_.get());
}
void TearDown() override {
EligibleHostDevicesProviderImpl::Factory::SetFactoryForTesting(nullptr);
HostBackendDelegateImpl::Factory::SetFactoryForTesting(nullptr);
HostVerifierImpl::Factory::SetFactoryForTesting(nullptr);
HostStatusProviderImpl::Factory::SetFactoryForTesting(nullptr);
SetupFlowCompletionRecorderImpl::Factory::SetFactoryForTesting(nullptr);
AccountStatusChangeDelegateNotifierImpl::Factory::SetFactoryForTesting(
nullptr);
}
void CallSetAccountStatusChangeDelegate() {
EXPECT_FALSE(fake_account_status_change_delegate_);
fake_account_status_change_delegate_ =
std::make_unique<FakeAccountStatusChangeDelegate>();
EXPECT_FALSE(fake_account_status_change_delegate_notifier()->delegate());
multidevice_setup_->SetAccountStatusChangeDelegate(
fake_account_status_change_delegate_->GenerateInterfacePtr());
EXPECT_TRUE(fake_account_status_change_delegate_notifier()->delegate());
}
cryptauth::RemoteDeviceList CallGetEligibleHostDevices() {
base::RunLoop run_loop;
multidevice_setup_->GetEligibleHostDevices(
base::BindOnce(&MultiDeviceSetupImplTest::OnEligibleDevicesFetched,
base::Unretained(this), run_loop.QuitClosure()));
run_loop.Run();
cryptauth::RemoteDeviceList eligible_devices_list =
*last_eligible_devices_list_;
last_eligible_devices_list_.reset();
return eligible_devices_list;
}
bool CallSetHostDevice(const std::string& host_public_key) {
base::RunLoop run_loop;
multidevice_setup_->SetHostDevice(
host_public_key,
base::BindOnce(&MultiDeviceSetupImplTest::OnHostSet,
base::Unretained(this), run_loop.QuitClosure()));
run_loop.Run();
bool success = *last_set_host_success_;
last_set_host_success_.reset();
return success;
}
std::pair<mojom::HostStatus, base::Optional<cryptauth::RemoteDevice>>
CallGetHostStatus() {
base::RunLoop run_loop;
multidevice_setup_->GetHostStatus(
base::BindOnce(&MultiDeviceSetupImplTest::OnHostStatusReceived,
base::Unretained(this), run_loop.QuitClosure()));
run_loop.Run();
std::pair<mojom::HostStatus, base::Optional<cryptauth::RemoteDevice>>
host_status_update = *last_host_status_;
last_host_status_.reset();
return host_status_update;
}
bool CallRetrySetHostNow() {
base::RunLoop run_loop;
multidevice_setup_->RetrySetHostNow(
base::BindOnce(&MultiDeviceSetupImplTest::OnHostRetried,
base::Unretained(this), run_loop.QuitClosure()));
run_loop.Run();
bool success = *last_retry_success_;
last_retry_success_.reset();
return success;
}
bool CallTriggerEventForDebugging(mojom::EventTypeForDebugging type) {
base::RunLoop run_loop;
multidevice_setup_->TriggerEventForDebugging(
type, base::BindOnce(&MultiDeviceSetupImplTest::OnDebugEventTriggered,
base::Unretained(this), run_loop.QuitClosure()));
run_loop.Run();
bool success = *last_debug_event_success_;
last_debug_event_success_.reset();
// If the delegate was set, fire off any pending Mojo messages.
if (success)
fake_account_status_change_delegate_notifier()->FlushForTesting();
return success;
}
void VerifyCurrentHostStatus(
mojom::HostStatus host_status,
const base::Optional<cryptauth::RemoteDeviceRef>& host_device,
FakeHostStatusObserver* observer = nullptr,
size_t expected_observer_index = 0u) {
std::pair<mojom::HostStatus, base::Optional<cryptauth::RemoteDevice>>
host_status_and_device = CallGetHostStatus();
EXPECT_EQ(host_status, host_status_and_device.first);
EXPECT_EQ(RefToRaw(host_device), host_status_and_device.second);
if (!observer)
return;
EXPECT_EQ(host_status,
observer->host_status_updates()[expected_observer_index].first);
EXPECT_EQ(RefToRaw(host_device),
observer->host_status_updates()[expected_observer_index].second);
}
void SendPendingObserverMessages() {
MultiDeviceSetupImpl* derived_ptr =
static_cast<MultiDeviceSetupImpl*>(multidevice_setup_.get());
derived_ptr->FlushForTesting();
}
FakeAccountStatusChangeDelegate* fake_account_status_change_delegate() {
return fake_account_status_change_delegate_.get();
}
FakeEligibleHostDevicesProvider* fake_eligible_host_devices_provider() {
return fake_eligible_host_devices_provider_factory_->instance();
}
FakeHostBackendDelegate* fake_host_backend_delegate() {
return fake_host_backend_delegate_factory_->instance();
}
FakeHostVerifier* fake_host_verifier() {
return fake_host_verifier_factory_->instance();
}
FakeHostStatusProvider* fake_host_status_provider() {
return fake_host_status_provider_factory_->instance();
}
FakeSetupFlowCompletionRecorder* fake_setup_flow_completion_recorder() {
return fake_setup_flow_completion_recorder_factory_->instance();
}
FakeAccountStatusChangeDelegateNotifier*
fake_account_status_change_delegate_notifier() {
return fake_account_status_change_delegate_notifier_factory_->instance();
}
cryptauth::RemoteDeviceRefList& test_devices() { return test_devices_; }
mojom::MultiDeviceSetup* multidevice_setup() {
return multidevice_setup_.get();
}
private:
void OnEligibleDevicesFetched(
base::OnceClosure quit_closure,
const cryptauth::RemoteDeviceList& eligible_devices_list) {
EXPECT_FALSE(last_eligible_devices_list_);
last_eligible_devices_list_ = eligible_devices_list;
std::move(quit_closure).Run();
}
void OnHostSet(base::OnceClosure quit_closure, bool success) {
EXPECT_FALSE(last_set_host_success_);
last_set_host_success_ = success;
std::move(quit_closure).Run();
}
void OnHostStatusReceived(
base::OnceClosure quit_closure,
mojom::HostStatus host_status,
const base::Optional<cryptauth::RemoteDevice>& host_device) {
EXPECT_FALSE(last_host_status_);
last_host_status_ = std::make_pair(host_status, host_device);
std::move(quit_closure).Run();
}
void OnHostRetried(base::OnceClosure quit_closure, bool success) {
EXPECT_FALSE(last_retry_success_);
last_retry_success_ = success;
std::move(quit_closure).Run();
}
void OnDebugEventTriggered(base::OnceClosure quit_closure, bool success) {
EXPECT_FALSE(last_debug_event_success_);
last_debug_event_success_ = success;
std::move(quit_closure).Run();
}
const base::test::ScopedTaskEnvironment scoped_task_environment_;
cryptauth::RemoteDeviceRefList test_devices_;
std::unique_ptr<sync_preferences::TestingPrefServiceSyncable>
test_pref_service_;
std::unique_ptr<device_sync::FakeDeviceSyncClient> fake_device_sync_client_;
std::unique_ptr<secure_channel::FakeSecureChannelClient>
fake_secure_channel_client_;
std::unique_ptr<FakeEligibleHostDevicesProviderFactory>
fake_eligible_host_devices_provider_factory_;
std::unique_ptr<FakeHostBackendDelegateFactory>
fake_host_backend_delegate_factory_;
std::unique_ptr<FakeHostVerifierFactory> fake_host_verifier_factory_;
std::unique_ptr<FakeHostStatusProviderFactory>
fake_host_status_provider_factory_;
std::unique_ptr<FakeSetupFlowCompletionRecorderFactory>
fake_setup_flow_completion_recorder_factory_;
std::unique_ptr<FakeAccountStatusChangeDelegateNotifierFactory>
fake_account_status_change_delegate_notifier_factory_;
std::unique_ptr<FakeAccountStatusChangeDelegate>
fake_account_status_change_delegate_;
base::Optional<bool> last_debug_event_success_;
base::Optional<cryptauth::RemoteDeviceList> last_eligible_devices_list_;
base::Optional<bool> last_set_host_success_;
base::Optional<
std::pair<mojom::HostStatus, base::Optional<cryptauth::RemoteDevice>>>
last_host_status_;
base::Optional<bool> last_retry_success_;
std::unique_ptr<mojom::MultiDeviceSetup> multidevice_setup_;
DISALLOW_COPY_AND_ASSIGN(MultiDeviceSetupImplTest);
};
TEST_F(MultiDeviceSetupImplTest, AccountStatusChangeDelegate) {
// All requests to trigger debug events should fail before the delegate has
// been set.
EXPECT_FALSE(CallTriggerEventForDebugging(
mojom::EventTypeForDebugging::kNewUserPotentialHostExists));
EXPECT_FALSE(CallTriggerEventForDebugging(
mojom::EventTypeForDebugging::kExistingUserConnectedHostSwitched));
EXPECT_FALSE(CallTriggerEventForDebugging(
mojom::EventTypeForDebugging::kExistingUserNewChromebookAdded));
CallSetAccountStatusChangeDelegate();
// All debug trigger events should now succeed.
EXPECT_TRUE(CallTriggerEventForDebugging(
mojom::EventTypeForDebugging::kNewUserPotentialHostExists));
EXPECT_EQ(
1u, fake_account_status_change_delegate()->num_new_user_events_handled());
EXPECT_TRUE(CallTriggerEventForDebugging(
mojom::EventTypeForDebugging::kExistingUserConnectedHostSwitched));
EXPECT_EQ(1u, fake_account_status_change_delegate()
->num_existing_user_host_switched_events_handled());
EXPECT_TRUE(CallTriggerEventForDebugging(
mojom::EventTypeForDebugging::kExistingUserNewChromebookAdded));
EXPECT_EQ(1u, fake_account_status_change_delegate()
->num_existing_user_chromebook_added_events_handled());
}
TEST_F(MultiDeviceSetupImplTest, ComprehensiveHostTest) {
// Start with no eligible devices.
EXPECT_TRUE(CallGetEligibleHostDevices().empty());
VerifyCurrentHostStatus(mojom::HostStatus::kNoEligibleHosts,
base::nullopt /* host_device */);
// Cannot retry without a host.
EXPECT_FALSE(CallRetrySetHostNow());
// Add a status observer.
auto observer = std::make_unique<FakeHostStatusObserver>();
multidevice_setup()->AddHostStatusObserver(observer->GenerateInterfacePtr());
// Simulate a sync occurring; now, all of the test devices are eligible hosts.
fake_eligible_host_devices_provider()->set_eligible_host_devices(
test_devices());
EXPECT_EQ(RefListToRawList(test_devices()), CallGetEligibleHostDevices());
fake_host_status_provider()->SetHostWithStatus(
mojom::HostStatus::kEligibleHostExistsButNoHostSet,
base::nullopt /* host_device */);
SendPendingObserverMessages();
VerifyCurrentHostStatus(mojom::HostStatus::kEligibleHostExistsButNoHostSet,
base::nullopt /* host_device */, observer.get(),
0u /* expected_observer_index */);
// There are eligible hosts, but none is set; thus, cannot retry.
EXPECT_FALSE(CallRetrySetHostNow());
// Set an invalid host as the host device; this should fail.
EXPECT_FALSE(CallSetHostDevice("invalidHostPublicKey"));
EXPECT_FALSE(fake_host_backend_delegate()->HasPendingHostRequest());
// Set device 0 as the host; this should succeed.
EXPECT_TRUE(CallSetHostDevice(test_devices()[0].public_key()));
EXPECT_TRUE(fake_host_backend_delegate()->HasPendingHostRequest());
EXPECT_EQ(test_devices()[0],
fake_host_backend_delegate()->GetPendingHostRequest());
fake_host_status_provider()->SetHostWithStatus(
mojom::HostStatus::kHostSetLocallyButWaitingForBackendConfirmation,
test_devices()[0]);
SendPendingObserverMessages();
VerifyCurrentHostStatus(
mojom::HostStatus::kHostSetLocallyButWaitingForBackendConfirmation,
test_devices()[0], observer.get(), 1u /* expected_observer_index */);
// It should now be possible to retry.
EXPECT_TRUE(CallRetrySetHostNow());
// Simulate the retry succeeding and the host being set on the back-end.
fake_host_backend_delegate()->NotifyHostChangedOnBackend(test_devices()[0]);
fake_host_status_provider()->SetHostWithStatus(
mojom::HostStatus::kHostSetButNotYetVerified, test_devices()[0]);
SendPendingObserverMessages();
VerifyCurrentHostStatus(mojom::HostStatus::kHostSetButNotYetVerified,
test_devices()[0], observer.get(),
2u /* expected_observer_index */);
// It should still be possible to retry (this time, retrying verification).
EXPECT_TRUE(CallRetrySetHostNow());
// Simulate verification succeeding.
fake_host_verifier()->set_is_host_verified(true);
fake_host_status_provider()->SetHostWithStatus(
mojom::HostStatus::kHostVerified, test_devices()[0]);
SendPendingObserverMessages();
VerifyCurrentHostStatus(mojom::HostStatus::kHostVerified, test_devices()[0],
observer.get(), 3u /* expected_observer_index */);
// Remove the host.
multidevice_setup()->RemoveHostDevice();
fake_host_verifier()->set_is_host_verified(false);
fake_host_status_provider()->SetHostWithStatus(
mojom::HostStatus::kEligibleHostExistsButNoHostSet,
base::nullopt /* host_device */);
SendPendingObserverMessages();
VerifyCurrentHostStatus(mojom::HostStatus::kEligibleHostExistsButNoHostSet,
base::nullopt /* host_device */, observer.get(),
4u /* expected_observer_index */);
// Simulate the host being removed on the back-end.
fake_host_backend_delegate()->NotifyHostChangedOnBackend(base::nullopt);
}
} // namespace multidevice_setup
} // namespace chromeos