| // Copyright 2024 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "remoting/host/setup/host_starter_base.h" |
| |
| #include <optional> |
| #include <string> |
| #include <utility> |
| |
| #include "base/run_loop.h" |
| #include "base/test/task_environment.h" |
| #include "google_apis/gaia/gaia_urls.h" |
| #include "net/http/http_status_code.h" |
| #include "remoting/base/auto_thread_task_runner.h" |
| #include "remoting/host/host_config.h" |
| #include "remoting/host/setup/daemon_controller.h" |
| #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" |
| #include "services/network/test/test_shared_url_loader_factory.h" |
| #include "services/network/test/test_url_loader_factory.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace remoting { |
| |
| namespace { |
| |
| // Response for spoofing Gaia calls. |
| constexpr char kAccessToken[] = "LEGIT_ACCESS_TOKEN"; |
| constexpr char kRefreshToken[] = "LEGIT_REFRESH_TOKEN"; |
| constexpr char kGetTokensResponse[] = R"({ |
| "refresh_token": "LEGIT_REFRESH_TOKEN", |
| "access_token": "LEGIT_ACCESS_TOKEN", |
| "expires_in": 3600, |
| "token_type": "Bearer" |
| })"; |
| constexpr char kGetUserEmailResponseForServiceAccount[] = |
| R"({"email": "robot@chromoting.com"})"; |
| |
| // Known values for testing config file generation. |
| constexpr char kTestUserEmail[] = "user@test.com"; |
| constexpr char kTestRobotEmail[] = "robot@chromoting.com"; |
| constexpr char kTestRobotAuthCode[] = "robot_auth_code"; |
| constexpr char kTestDirectoryId[] = "test_directory_id"; |
| constexpr char kTestMachineName[] = "test_machine_name"; |
| |
| constexpr char kTestConfigValuePath[] = "test_config_value"; |
| constexpr char kTestConfigValue[] = "so_much_value"; |
| |
| class TestDaemonControllerDelegate : public DaemonController::Delegate { |
| public: |
| TestDaemonControllerDelegate(); |
| |
| TestDaemonControllerDelegate(const TestDaemonControllerDelegate&) = delete; |
| TestDaemonControllerDelegate& operator=(const TestDaemonControllerDelegate&) = |
| delete; |
| |
| ~TestDaemonControllerDelegate() override; |
| |
| // DaemonController::Delegate interface. |
| DaemonController::State GetState() override; |
| std::optional<base::Value::Dict> GetConfig() override; |
| void CheckPermission(bool it2me, |
| DaemonController::BoolCallback callback) override; |
| void SetConfigAndStart(base::Value::Dict config, |
| bool consent, |
| DaemonController::CompletionCallback done) override; |
| void UpdateConfig(base::Value::Dict config, |
| DaemonController::CompletionCallback done) override; |
| void Stop(DaemonController::CompletionCallback done) override; |
| DaemonController::UsageStatsConsent GetUsageStatsConsent() override; |
| |
| // Methods used for controlling behavior of the fake instance. |
| void set_result_for_config_and_start(DaemonController::AsyncResult result) { |
| result_for_config_and_start_ = result; |
| } |
| void set_initial_config(base::Value::Dict config) { |
| config_ = std::move(config); |
| } |
| |
| bool stop_called() { return stop_called_; } |
| |
| private: |
| bool stop_called_ = false; |
| DaemonController::State state_ = DaemonController::STATE_STOPPED; |
| DaemonController::AsyncResult result_for_config_and_start_ = |
| DaemonController::RESULT_OK; |
| base::Value::Dict config_; |
| }; |
| |
| TestDaemonControllerDelegate::TestDaemonControllerDelegate() = default; |
| |
| TestDaemonControllerDelegate::~TestDaemonControllerDelegate() = default; |
| |
| DaemonController::State TestDaemonControllerDelegate::GetState() { |
| return state_; |
| } |
| |
| std::optional<base::Value::Dict> TestDaemonControllerDelegate::GetConfig() { |
| return config_.Clone(); |
| } |
| |
| void TestDaemonControllerDelegate::CheckPermission( |
| bool it2me, |
| DaemonController::BoolCallback callback) { |
| ADD_FAILURE() << "Unexpected call to CheckPermission()"; |
| } |
| |
| void TestDaemonControllerDelegate::SetConfigAndStart( |
| base::Value::Dict config, |
| bool consent, |
| DaemonController::CompletionCallback done) { |
| config_ = std::move(config); |
| state_ = DaemonController::STATE_STARTED; |
| std::move(done).Run(result_for_config_and_start_); |
| } |
| |
| void TestDaemonControllerDelegate::UpdateConfig( |
| base::Value::Dict config, |
| DaemonController::CompletionCallback done) { |
| ADD_FAILURE() << "Unexpected call to UpdateConfig()"; |
| } |
| |
| void TestDaemonControllerDelegate::Stop( |
| DaemonController::CompletionCallback done) { |
| stop_called_ = true; |
| state_ = DaemonController::STATE_STOPPED; |
| std::move(done).Run(DaemonController::RESULT_OK); |
| } |
| |
| DaemonController::UsageStatsConsent |
| TestDaemonControllerDelegate::GetUsageStatsConsent() { |
| ADD_FAILURE() << "Unexpected call to GetUsageStatsConsent()"; |
| return DaemonController::UsageStatsConsent(); |
| } |
| |
| class TestHostStarter : public HostStarterBase { |
| public: |
| TestHostStarter( |
| scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, |
| scoped_refptr<DaemonController> daemon_controller, |
| base::OnceClosure configure_gaia_for_service_account); |
| |
| TestHostStarter(const TestHostStarter&) = delete; |
| TestHostStarter& operator=(const TestHostStarter&) = delete; |
| |
| ~TestHostStarter() override; |
| |
| // HostStarterBase implementation. |
| void RetrieveApiAccessToken() override; |
| void RegisterNewHost(std::optional<std::string> access_token) override; |
| void RemoveOldHostFromDirectory(base::OnceClosure on_removed) override; |
| void ApplyConfigValues(base::Value::Dict& config) override; |
| void ReportError(const std::string& error_message, |
| base::OnceClosure on_done) override; |
| |
| std::string& user_access_token() { return user_access_token_; } |
| std::string& error_message() { return error_message_; } |
| |
| void clear_api_access_token() { api_access_token_.clear(); } |
| |
| void clear_directory_id() { directory_id_.clear(); } |
| |
| void clear_owner_account_email() { owner_account_email_.clear(); } |
| |
| void clear_service_account_email() { service_account_email_.clear(); } |
| |
| void clear_robot_authorization_code() { robot_authorization_code_.clear(); } |
| |
| private: |
| std::string user_access_token_; |
| std::string error_message_; |
| |
| std::string api_access_token_{kAccessToken}; |
| std::string directory_id_{kTestDirectoryId}; |
| std::string owner_account_email_{kTestUserEmail}; |
| std::string service_account_email_{kTestRobotEmail}; |
| std::string robot_authorization_code_{kTestRobotAuthCode}; |
| |
| base::OnceClosure configure_gaia_for_service_account_; |
| }; |
| |
| TestHostStarter::TestHostStarter( |
| scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, |
| scoped_refptr<DaemonController> daemon_controller, |
| base::OnceClosure configure_gaia_for_service_account) |
| : HostStarterBase(url_loader_factory), |
| configure_gaia_for_service_account_( |
| std::move(configure_gaia_for_service_account)) { |
| SetDaemonControllerForTest(daemon_controller); |
| } |
| |
| TestHostStarter::~TestHostStarter() = default; |
| |
| void TestHostStarter::RetrieveApiAccessToken() { |
| if (!api_access_token_.empty()) { |
| RegisterNewHost(api_access_token_); |
| } else { |
| HostStarterBase::RetrieveApiAccessToken(); |
| } |
| } |
| |
| void TestHostStarter::RegisterNewHost(std::optional<std::string> access_token) { |
| // Set up the TestUrlLoaderFactory so it will provide service account |
| // responses rather than user account responses. |
| std::move(configure_gaia_for_service_account_).Run(); |
| |
| user_access_token_ = access_token.value_or(std::string()); |
| OnNewHostRegistered(directory_id_, owner_account_email_, |
| service_account_email_, robot_authorization_code_); |
| } |
| |
| void TestHostStarter::RemoveOldHostFromDirectory(base::OnceClosure on_removed) { |
| std::move(on_removed).Run(); |
| } |
| |
| void TestHostStarter::ApplyConfigValues(base::Value::Dict& config) { |
| config.Set(kTestConfigValuePath, kTestConfigValue); |
| } |
| |
| void TestHostStarter::ReportError(const std::string& error_message, |
| base::OnceClosure on_done) { |
| error_message_ = error_message; |
| LOG(ERROR) << error_message_; |
| std::move(on_done).Run(); |
| } |
| |
| } // namespace |
| |
| class HostStarterBaseTest : public testing::Test { |
| public: |
| HostStarterBaseTest(); |
| ~HostStarterBaseTest() override; |
| |
| void SetUp() override; |
| void TearDown() override; |
| |
| HostStarter::CompletionCallback GetCompletionCallback() { |
| return base::BindOnce(&HostStarterBaseTest::CompletionHandler, |
| base::Unretained(this)); |
| } |
| |
| protected: |
| void RunUntilQuit(); |
| void CompletionHandler(HostStarter::Result result); |
| |
| void ConfigureGaiaResponseForUser(); |
| void ConfigureGaiaResponseForServiceAccount(); |
| |
| TestHostStarter& test_host_starter() { return *test_host_starter_; } |
| std::optional<HostStarter::Result>& start_result() { return start_result_; } |
| TestDaemonControllerDelegate& test_daemon_controller_delegate() { |
| return *test_daemon_controller_delegate_; |
| } |
| |
| private: |
| base::RepeatingClosure quit_closure_; |
| |
| base::test::TaskEnvironment task_environment_{ |
| base::test::TaskEnvironment::MainThreadType::IO}; |
| |
| network::TestURLLoaderFactory test_url_loader_factory_; |
| scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_; |
| |
| // Reference to the DaemonControllerDelegate used for testing, which is owned |
| // by |test_host_starter_|. |
| raw_ptr<TestDaemonControllerDelegate> test_daemon_controller_delegate_; |
| scoped_refptr<DaemonController> daemon_controller_; |
| |
| std::optional<HostStarter::Result> start_result_; |
| std::unique_ptr<TestHostStarter> test_host_starter_; |
| }; |
| |
| HostStarterBaseTest::HostStarterBaseTest() = default; |
| |
| HostStarterBaseTest::~HostStarterBaseTest() = default; |
| |
| void HostStarterBaseTest::SetUp() { |
| shared_url_loader_factory_ = test_url_loader_factory_.GetSafeWeakWrapper(); |
| test_daemon_controller_delegate_ = new TestDaemonControllerDelegate(); |
| daemon_controller_ = new DaemonController( |
| base::WrapUnique(test_daemon_controller_delegate_.get())); |
| test_host_starter_ = std::make_unique<TestHostStarter>( |
| shared_url_loader_factory_, daemon_controller_, |
| base::BindOnce( |
| &HostStarterBaseTest::ConfigureGaiaResponseForServiceAccount, |
| base::Unretained(this))); |
| quit_closure_ = task_environment_.QuitClosure(); |
| } |
| |
| void HostStarterBaseTest::TearDown() { |
| // Clear the raw pointer so it doesn't appear to be hanging. |
| test_daemon_controller_delegate_ = nullptr; |
| // Clear the test instance and allow the threads to shut down so ASAN doesn't |
| // detect it as leaked. |
| test_host_starter_.reset(); |
| |
| task_environment_.GetMainThreadTaskRunner()->ReleaseSoon( |
| FROM_HERE, std::move(daemon_controller_)); |
| |
| task_environment_.RunUntilIdle(); |
| } |
| |
| void HostStarterBaseTest::RunUntilQuit() { |
| task_environment_.RunUntilQuit(); |
| } |
| |
| void HostStarterBaseTest::CompletionHandler(HostStarter::Result result) { |
| start_result_ = result; |
| quit_closure_.Run(); |
| } |
| |
| void HostStarterBaseTest::ConfigureGaiaResponseForServiceAccount() { |
| test_url_loader_factory_.AddResponse( |
| GaiaUrls::GetInstance()->oauth2_token_url().spec(), kGetTokensResponse); |
| test_url_loader_factory_.AddResponse( |
| GaiaUrls::GetInstance()->oauth_user_info_url().spec(), |
| kGetUserEmailResponseForServiceAccount); |
| } |
| |
| TEST_F(HostStarterBaseTest, StartHostUsingOAuth) { |
| HostStarter::Params params; |
| params.pin = "123456"; |
| params.name = kTestMachineName; |
| params.auth_code = "auth_me_dude"; |
| params.redirect_url = "/redirect"; |
| |
| test_host_starter().StartHost(std::move(params), GetCompletionCallback()); |
| RunUntilQuit(); |
| |
| // Make sure the operation completed successfully. |
| EXPECT_EQ(start_result(), HostStarter::START_COMPLETE); |
| |
| // Verify the user access token was provided to the subclass and no errors |
| // were reported. |
| EXPECT_EQ(test_host_starter().user_access_token(), kAccessToken); |
| EXPECT_EQ(test_host_starter().error_message(), std::string()); |
| |
| // Verify the configuration dict has the expected fields populated. |
| auto config = test_daemon_controller_delegate().GetConfig(); |
| ASSERT_TRUE(config.has_value()); |
| const std::string* value = config->FindString(kHostOwnerConfigPath); |
| ASSERT_NE(value, nullptr); |
| EXPECT_EQ(*value, kTestUserEmail); |
| value = config->FindString(kServiceAccountConfigPath); |
| ASSERT_NE(value, nullptr); |
| EXPECT_EQ(*value, kTestRobotEmail); |
| value = config->FindString(kOAuthRefreshTokenConfigPath); |
| ASSERT_NE(value, nullptr); |
| EXPECT_EQ(*value, kRefreshToken); |
| value = config->FindString(kHostIdConfigPath); |
| ASSERT_NE(value, nullptr); |
| EXPECT_EQ(*value, kTestDirectoryId); |
| value = config->FindString(kHostNameConfigPath); |
| ASSERT_NE(value, nullptr); |
| EXPECT_EQ(*value, kTestMachineName); |
| // Verify subclass value was applied. |
| value = config->FindString(kTestConfigValuePath); |
| ASSERT_NE(value, nullptr); |
| EXPECT_EQ(*value, kTestConfigValue); |
| |
| // Verify Stop() was not called. |
| EXPECT_FALSE(test_daemon_controller_delegate().stop_called()); |
| } |
| |
| TEST_F(HostStarterBaseTest, CorpCodePath) { |
| HostStarter::Params params; |
| params.username = kTestUserEmail; |
| |
| // Run the non-OAuth codepath. |
| test_host_starter().clear_api_access_token(); |
| |
| test_host_starter().StartHost(std::move(params), GetCompletionCallback()); |
| RunUntilQuit(); |
| |
| // Make sure the operation completed successfully. |
| EXPECT_EQ(start_result(), HostStarter::START_COMPLETE); |
| |
| // Verify no user access token was provided and no errors were reported. |
| EXPECT_EQ(test_host_starter().user_access_token(), std::string()); |
| EXPECT_EQ(test_host_starter().error_message(), std::string()); |
| |
| // Verify the configuration dict has the expected fields populated. |
| auto config = test_daemon_controller_delegate().GetConfig(); |
| ASSERT_TRUE(config.has_value()); |
| const std::string* value = config->FindString(kHostOwnerConfigPath); |
| ASSERT_NE(value, nullptr); |
| EXPECT_EQ(*value, kTestUserEmail); |
| value = config->FindString(kServiceAccountConfigPath); |
| ASSERT_NE(value, nullptr); |
| EXPECT_EQ(*value, kTestRobotEmail); |
| value = config->FindString(kOAuthRefreshTokenConfigPath); |
| ASSERT_NE(value, nullptr); |
| EXPECT_EQ(*value, kRefreshToken); |
| value = config->FindString(kHostIdConfigPath); |
| ASSERT_NE(value, nullptr); |
| EXPECT_EQ(*value, kTestDirectoryId); |
| // We use the value from GetHostname() if no name is provided. |
| EXPECT_TRUE(config->FindString(kHostNameConfigPath)); |
| // Verify subclass value was applied. |
| value = config->FindString(kTestConfigValuePath); |
| ASSERT_NE(value, nullptr); |
| EXPECT_EQ(*value, kTestConfigValue); |
| |
| // Verify Stop() was not called. |
| EXPECT_FALSE(test_daemon_controller_delegate().stop_called()); |
| } |
| |
| TEST_F(HostStarterBaseTest, CloudCodePath) { |
| HostStarter::Params params; |
| params.owner_email = kTestUserEmail; |
| params.api_key = "API_KEY_FOR_TESTING"; |
| |
| // Run the non-OAuth codepath. |
| test_host_starter().clear_api_access_token(); |
| |
| test_host_starter().StartHost(std::move(params), GetCompletionCallback()); |
| RunUntilQuit(); |
| |
| // Make sure the operation completed successfully. |
| EXPECT_EQ(start_result(), HostStarter::START_COMPLETE); |
| |
| // Verify no user access token was provided and no errors were reported. |
| EXPECT_EQ(test_host_starter().user_access_token(), std::string()); |
| EXPECT_EQ(test_host_starter().error_message(), std::string()); |
| |
| // Verify the configuration dict has the expected fields populated. |
| auto config = test_daemon_controller_delegate().GetConfig(); |
| ASSERT_TRUE(config.has_value()); |
| const std::string* value = config->FindString(kHostOwnerConfigPath); |
| ASSERT_NE(value, nullptr); |
| EXPECT_EQ(*value, kTestUserEmail); |
| value = config->FindString(kServiceAccountConfigPath); |
| ASSERT_NE(value, nullptr); |
| EXPECT_EQ(*value, kTestRobotEmail); |
| value = config->FindString(kOAuthRefreshTokenConfigPath); |
| ASSERT_NE(value, nullptr); |
| EXPECT_EQ(*value, kRefreshToken); |
| value = config->FindString(kHostIdConfigPath); |
| ASSERT_NE(value, nullptr); |
| EXPECT_EQ(*value, kTestDirectoryId); |
| // We use the value from GetHostname() if no name is provided. |
| EXPECT_TRUE(config->FindString(kHostNameConfigPath)); |
| // Verify subclass value was applied. |
| value = config->FindString(kTestConfigValuePath); |
| ASSERT_NE(value, nullptr); |
| EXPECT_EQ(*value, kTestConfigValue); |
| |
| // Verify Stop() was not called. |
| EXPECT_FALSE(test_daemon_controller_delegate().stop_called()); |
| } |
| |
| TEST_F(HostStarterBaseTest, LegacyCloudCodePath) { |
| HostStarter::Params params; |
| params.owner_email = kTestUserEmail; |
| params.pin = "123456"; |
| |
| // Run the non-OAuth codepath. |
| test_host_starter().clear_api_access_token(); |
| |
| test_host_starter().StartHost(std::move(params), GetCompletionCallback()); |
| RunUntilQuit(); |
| |
| // Make sure the operation completed successfully. |
| EXPECT_EQ(start_result(), HostStarter::START_COMPLETE); |
| |
| // Verify no user access token was provided and no errors were reported. |
| EXPECT_EQ(test_host_starter().user_access_token(), std::string()); |
| EXPECT_EQ(test_host_starter().error_message(), std::string()); |
| |
| // Verify the configuration dict has the expected fields populated. |
| auto config = test_daemon_controller_delegate().GetConfig(); |
| ASSERT_TRUE(config.has_value()); |
| const std::string* value = config->FindString(kHostOwnerConfigPath); |
| ASSERT_NE(value, nullptr); |
| EXPECT_EQ(*value, kTestUserEmail); |
| value = config->FindString(kServiceAccountConfigPath); |
| ASSERT_NE(value, nullptr); |
| EXPECT_EQ(*value, kTestRobotEmail); |
| value = config->FindString(kOAuthRefreshTokenConfigPath); |
| ASSERT_NE(value, nullptr); |
| EXPECT_EQ(*value, kRefreshToken); |
| value = config->FindString(kHostIdConfigPath); |
| ASSERT_NE(value, nullptr); |
| EXPECT_EQ(*value, kTestDirectoryId); |
| // We use the value from GetHostname() if no name is provided. |
| EXPECT_TRUE(config->FindString(kHostNameConfigPath)); |
| // Verify subclass value was applied. |
| value = config->FindString(kTestConfigValuePath); |
| ASSERT_NE(value, nullptr); |
| EXPECT_EQ(*value, kTestConfigValue); |
| |
| // Verify Stop() was not called. |
| EXPECT_FALSE(test_daemon_controller_delegate().stop_called()); |
| } |
| |
| TEST_F(HostStarterBaseTest, ExistingHostIsStopped) { |
| HostStarter::Params params; |
| params.owner_email = kTestUserEmail; |
| |
| base::Value::Dict initial_config; |
| initial_config.Set(kHostIdConfigPath, "old_crusty_host_id"); |
| test_daemon_controller_delegate().set_initial_config( |
| std::move(initial_config)); |
| |
| // Run the non-OAuth codepath. |
| test_host_starter().clear_api_access_token(); |
| |
| test_host_starter().StartHost(std::move(params), GetCompletionCallback()); |
| RunUntilQuit(); |
| |
| // Make sure the operation completed successfully. |
| EXPECT_EQ(start_result(), HostStarter::START_COMPLETE); |
| |
| // Verify no errors were reported. |
| EXPECT_TRUE(test_host_starter().error_message().empty()); |
| |
| // Verify Stop() was called. |
| EXPECT_TRUE(test_daemon_controller_delegate().stop_called()); |
| } |
| |
| TEST_F(HostStarterBaseTest, CorpFlowWithMismatchedOwnerEmailValue) { |
| HostStarter::Params params; |
| params.owner_email = "PLACEHOLDER_VALUE"; |
| |
| // Run the non-OAuth codepath. |
| test_host_starter().clear_api_access_token(); |
| |
| test_host_starter().StartHost(std::move(params), GetCompletionCallback()); |
| RunUntilQuit(); |
| |
| // Make sure the operation completed successfully. |
| EXPECT_EQ(start_result(), HostStarter::START_COMPLETE); |
| |
| // Verify owner from the service was written to the config rather than the |
| // placeholder value. |
| auto config = test_daemon_controller_delegate().GetConfig(); |
| ASSERT_TRUE(config.has_value()); |
| const std::string* value = config->FindString(kHostOwnerConfigPath); |
| ASSERT_NE(value, nullptr); |
| EXPECT_EQ(*value, kTestUserEmail); |
| } |
| |
| TEST_F(HostStarterBaseTest, RegisterNewHostCallbackDoesNotProvideId) { |
| test_host_starter().clear_directory_id(); |
| |
| HostStarter::Params params; |
| params.owner_email = kTestUserEmail; |
| |
| // Run the non-OAuth codepath. |
| test_host_starter().clear_api_access_token(); |
| |
| test_host_starter().StartHost(std::move(params), GetCompletionCallback()); |
| RunUntilQuit(); |
| |
| // Make sure the operation failed for the expected reason. |
| EXPECT_EQ(start_result(), HostStarter::REGISTRATION_ERROR); |
| |
| // Verify an error was reported. |
| EXPECT_NE(test_host_starter().error_message(), std::string()); |
| } |
| |
| TEST_F(HostStarterBaseTest, RegisterNewHostCallbackProvideMismatchedId) { |
| HostStarter::Params params; |
| params.id = "my-guid"; |
| params.owner_email = kTestUserEmail; |
| |
| // Run the non-OAuth codepath. |
| test_host_starter().clear_api_access_token(); |
| |
| test_host_starter().StartHost(std::move(params), GetCompletionCallback()); |
| RunUntilQuit(); |
| |
| // Make sure the operation failed for the expected reason. |
| EXPECT_EQ(start_result(), HostStarter::REGISTRATION_ERROR); |
| |
| // Verify an error was reported. |
| EXPECT_NE(test_host_starter().error_message(), std::string()); |
| } |
| |
| TEST_F(HostStarterBaseTest, RegisterNewHostCallbackDoesNotProvideAuthCode) { |
| test_host_starter().clear_robot_authorization_code(); |
| |
| HostStarter::Params params; |
| params.owner_email = kTestUserEmail; |
| |
| // Run the non-OAuth codepath. |
| test_host_starter().clear_api_access_token(); |
| |
| test_host_starter().StartHost(std::move(params), GetCompletionCallback()); |
| RunUntilQuit(); |
| |
| // Make sure the operation failed for the expected reason. |
| EXPECT_EQ(start_result(), HostStarter::REGISTRATION_ERROR); |
| |
| // Verify an error was reported. |
| EXPECT_NE(test_host_starter().error_message(), std::string()); |
| } |
| |
| TEST_F(HostStarterBaseTest, RegisterNewHostCallbackDoesNotProvideOwnerEmail) { |
| test_host_starter().clear_owner_account_email(); |
| |
| HostStarter::Params params; |
| params.owner_email = kTestUserEmail; |
| |
| // Run the non-OAuth codepath. |
| test_host_starter().clear_api_access_token(); |
| |
| test_host_starter().StartHost(std::move(params), GetCompletionCallback()); |
| RunUntilQuit(); |
| |
| // Make sure the operation completed successfully. |
| EXPECT_EQ(start_result(), HostStarter::START_COMPLETE); |
| |
| // Verify the owner email to be written to the config. |
| auto config = test_daemon_controller_delegate().GetConfig(); |
| ASSERT_TRUE(config.has_value()); |
| const std::string* value = config->FindString(kHostOwnerConfigPath); |
| ASSERT_NE(value, nullptr); |
| EXPECT_EQ(*value, kTestUserEmail); |
| } |
| |
| TEST_F(HostStarterBaseTest, |
| RegisterNewHostCallbackDoesNotProvideServiceAccount) { |
| test_host_starter().clear_service_account_email(); |
| |
| HostStarter::Params params; |
| params.owner_email = kTestUserEmail; |
| |
| // Run the non-OAuth codepath. |
| test_host_starter().clear_api_access_token(); |
| |
| test_host_starter().StartHost(std::move(params), GetCompletionCallback()); |
| RunUntilQuit(); |
| |
| // Make sure the operation completed successfully. |
| EXPECT_EQ(start_result(), HostStarter::START_COMPLETE); |
| |
| // Verify the expected service account was written to the config. |
| auto config = test_daemon_controller_delegate().GetConfig(); |
| ASSERT_TRUE(config.has_value()); |
| const std::string* value = config->FindString(kServiceAccountConfigPath); |
| ASSERT_NE(value, nullptr); |
| EXPECT_EQ(*value, kTestRobotEmail); |
| } |
| |
| TEST_F(HostStarterBaseTest, NewHostFailsToStart) { |
| test_daemon_controller_delegate().set_result_for_config_and_start( |
| DaemonController::RESULT_FAILED); |
| |
| HostStarter::Params params; |
| params.owner_email = kTestUserEmail; |
| |
| // Run the non-OAuth codepath. |
| test_host_starter().clear_api_access_token(); |
| |
| test_host_starter().StartHost(std::move(params), GetCompletionCallback()); |
| RunUntilQuit(); |
| |
| // Make sure the operation failed for the expected reason. |
| EXPECT_EQ(start_result(), HostStarter::START_ERROR); |
| |
| // Verify an error was reported. |
| EXPECT_NE(test_host_starter().error_message(), std::string()); |
| } |
| |
| } // namespace remoting |