// Copyright 2015 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 "remoting/test/app_remoting_test_driver_environment.h" #include #include #include #include "base/files/file_path.h" #include "base/macros.h" #include "remoting/test/fake_access_token_fetcher.h" #include "remoting/test/fake_app_remoting_report_issue_request.h" #include "remoting/test/fake_refresh_token_store.h" #include "remoting/test/fake_remote_host_info_fetcher.h" #include "remoting/test/mock_access_token_fetcher.h" #include "remoting/test/refresh_token_store.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" namespace { const char kAuthCodeValue[] = "4/892379827345jkefvkdfbv"; const char kUserNameValue[] = "remoting_user@gmail.com"; const char kTestApplicationId[] = "sadlkjlsjgadjfgoajdfgagb"; const char kAnotherTestApplicationId[] = "waklgoisdhfnvjkdsfbljn"; const char kTestHostId1[] = "awesome_test_host_id"; const char kTestHostId2[] = "super_awesome_test_host_id"; const char kTestHostId3[] = "uber_awesome_test_host_id"; } namespace remoting { namespace test { using testing::_; class AppRemotingTestDriverEnvironmentTest : public ::testing::Test { public: AppRemotingTestDriverEnvironmentTest(); ~AppRemotingTestDriverEnvironmentTest() override; FakeAccessTokenFetcher* fake_access_token_fetcher() const { return fake_access_token_fetcher_; } protected: void Initialize(); void Initialize( const AppRemotingTestDriverEnvironment::EnvironmentOptions& options); FakeAccessTokenFetcher* fake_access_token_fetcher_; FakeAppRemotingReportIssueRequest fake_report_issue_request_; FakeRefreshTokenStore fake_token_store_; FakeRemoteHostInfoFetcher fake_remote_host_info_fetcher_; MockAccessTokenFetcher mock_access_token_fetcher_; scoped_ptr environment_object_; private: DISALLOW_COPY_AND_ASSIGN(AppRemotingTestDriverEnvironmentTest); }; AppRemotingTestDriverEnvironmentTest::AppRemotingTestDriverEnvironmentTest() : fake_access_token_fetcher_(nullptr) { } AppRemotingTestDriverEnvironmentTest::~AppRemotingTestDriverEnvironmentTest() { } void AppRemotingTestDriverEnvironmentTest::Initialize() { AppRemotingTestDriverEnvironment::EnvironmentOptions options; options.user_name = kUserNameValue; options.service_environment = kDeveloperEnvironment; Initialize(options); } void AppRemotingTestDriverEnvironmentTest::Initialize( const AppRemotingTestDriverEnvironment::EnvironmentOptions& options) { environment_object_.reset(new AppRemotingTestDriverEnvironment(options)); scoped_ptr fake_access_token_fetcher( new FakeAccessTokenFetcher()); fake_access_token_fetcher_ = fake_access_token_fetcher.get(); mock_access_token_fetcher_.SetAccessTokenFetcher( std::move(fake_access_token_fetcher)); environment_object_->SetAccessTokenFetcherForTest( &mock_access_token_fetcher_); environment_object_->SetAppRemotingReportIssueRequestForTest( &fake_report_issue_request_); environment_object_->SetRefreshTokenStoreForTest(&fake_token_store_); environment_object_->SetRemoteHostInfoFetcherForTest( &fake_remote_host_info_fetcher_); } TEST_F(AppRemotingTestDriverEnvironmentTest, InitializeObjectWithAuthCode) { Initialize(); EXPECT_CALL(mock_access_token_fetcher_, GetAccessTokenFromAuthCode(_, _)); EXPECT_CALL(mock_access_token_fetcher_, GetAccessTokenFromRefreshToken(_, _)) .Times(0); EXPECT_TRUE(environment_object_->Initialize(kAuthCodeValue)); EXPECT_TRUE(fake_token_store_.refresh_token_write_attempted()); EXPECT_EQ(fake_token_store_.stored_refresh_token_value(), kFakeAccessTokenFetcherRefreshTokenValue); EXPECT_EQ(environment_object_->user_name(), kUserNameValue); EXPECT_EQ(environment_object_->access_token(), kFakeAccessTokenFetcherAccessTokenValue); // Attempt to init again, we should not see any additional calls or errors. EXPECT_TRUE(environment_object_->Initialize(kAuthCodeValue)); } TEST_F(AppRemotingTestDriverEnvironmentTest, InitializeObjectWithAuthCodeFailed) { Initialize(); fake_access_token_fetcher()->set_fail_access_token_from_auth_code(true); EXPECT_CALL(mock_access_token_fetcher_, GetAccessTokenFromAuthCode(_, _)); EXPECT_CALL(mock_access_token_fetcher_, GetAccessTokenFromRefreshToken(_, _)) .Times(0); EXPECT_FALSE(environment_object_->Initialize(kAuthCodeValue)); EXPECT_FALSE(fake_token_store_.refresh_token_write_attempted()); } TEST_F(AppRemotingTestDriverEnvironmentTest, InitializeObjectWithRefreshToken) { Initialize(); EXPECT_CALL(mock_access_token_fetcher_, GetAccessTokenFromRefreshToken(_, _)); EXPECT_CALL(mock_access_token_fetcher_, GetAccessTokenFromAuthCode(_, _)) .Times(0); // Pass in an empty auth code since we are using a refresh token. EXPECT_TRUE(environment_object_->Initialize(std::string())); // We should not write the refresh token a second time if we read from the // disk originally. EXPECT_FALSE(fake_token_store_.refresh_token_write_attempted()); // Verify the object was initialized correctly. EXPECT_EQ(environment_object_->user_name(), kUserNameValue); EXPECT_EQ(environment_object_->access_token(), kFakeAccessTokenFetcherAccessTokenValue); // Attempt to init again, we should not see any additional calls or errors. EXPECT_TRUE(environment_object_->Initialize(std::string())); } TEST_F(AppRemotingTestDriverEnvironmentTest, TearDownAfterInitializeSucceeds) { Initialize(); EXPECT_CALL(mock_access_token_fetcher_, GetAccessTokenFromRefreshToken(_, _)); EXPECT_CALL(mock_access_token_fetcher_, GetAccessTokenFromAuthCode(_, _)) .Times(0); // Pass in an empty auth code since we are using a refresh token. EXPECT_TRUE(environment_object_->Initialize(std::string())); // Note: We are using a static cast here because the TearDown() method is // private as it is an interface method that we only want to call // directly in tests or by the GTEST framework. static_cast(environment_object_.get())->TearDown(); } TEST_F(AppRemotingTestDriverEnvironmentTest, InitializeObjectWithRefreshTokenFailed) { Initialize(); fake_access_token_fetcher()->set_fail_access_token_from_refresh_token(true); EXPECT_CALL(mock_access_token_fetcher_, GetAccessTokenFromRefreshToken(_, _)); EXPECT_CALL(mock_access_token_fetcher_, GetAccessTokenFromAuthCode(_, _)) .Times(0); // Pass in an empty auth code since we are using a refresh token. EXPECT_FALSE(environment_object_->Initialize(std::string())); EXPECT_FALSE(fake_token_store_.refresh_token_write_attempted()); } TEST_F(AppRemotingTestDriverEnvironmentTest, InitializeObjectNoAuthCodeOrRefreshToken) { Initialize(); // Neither method should be called in this scenario. EXPECT_CALL(mock_access_token_fetcher_, GetAccessTokenFromAuthCode(_, _)) .Times(0); EXPECT_CALL(mock_access_token_fetcher_, GetAccessTokenFromRefreshToken(_, _)) .Times(0); // Clear out the 'stored' refresh token value. fake_token_store_.set_refresh_token_value(std::string()); // With no auth code or refresh token, then the initialization should fail. EXPECT_FALSE(environment_object_->Initialize(std::string())); EXPECT_FALSE(fake_token_store_.refresh_token_write_attempted()); } TEST_F(AppRemotingTestDriverEnvironmentTest, InitializeObjectWithAuthCodeWriteFailed) { Initialize(); EXPECT_CALL(mock_access_token_fetcher_, GetAccessTokenFromAuthCode(_, _)); EXPECT_CALL(mock_access_token_fetcher_, GetAccessTokenFromRefreshToken(_, _)) .Times(0); // Simulate a failure writing the token to the disk. fake_token_store_.set_refresh_token_write_succeeded(false); EXPECT_FALSE(environment_object_->Initialize(kAuthCodeValue)); EXPECT_TRUE(fake_token_store_.refresh_token_write_attempted()); } TEST_F(AppRemotingTestDriverEnvironmentTest, RefreshAccessTokenAfterUsingAuthCode) { Initialize(); { testing::InSequence call_sequence; EXPECT_CALL(mock_access_token_fetcher_, GetAccessTokenFromAuthCode(_, _)); EXPECT_CALL(mock_access_token_fetcher_, GetAccessTokenFromRefreshToken(_, _)); } EXPECT_TRUE(environment_object_->Initialize(kAuthCodeValue)); EXPECT_TRUE(fake_token_store_.refresh_token_write_attempted()); EXPECT_EQ(fake_token_store_.stored_refresh_token_value(), kFakeAccessTokenFetcherRefreshTokenValue); EXPECT_EQ(environment_object_->user_name(), kUserNameValue); EXPECT_EQ(environment_object_->access_token(), kFakeAccessTokenFetcherAccessTokenValue); // Attempt to init again, we should not see any additional calls or errors. EXPECT_TRUE(environment_object_->RefreshAccessToken()); } TEST_F(AppRemotingTestDriverEnvironmentTest, RefreshAccessTokenFailure) { Initialize(); { testing::InSequence call_sequence; // Mock is set up for this call to succeed. EXPECT_CALL(mock_access_token_fetcher_, GetAccessTokenFromAuthCode(_, _)); // Mock is set up for this call to fail. EXPECT_CALL(mock_access_token_fetcher_, GetAccessTokenFromRefreshToken(_, _)); } EXPECT_TRUE(environment_object_->Initialize(kAuthCodeValue)); EXPECT_TRUE(fake_token_store_.refresh_token_write_attempted()); EXPECT_EQ(fake_token_store_.stored_refresh_token_value(), kFakeAccessTokenFetcherRefreshTokenValue); EXPECT_EQ(environment_object_->user_name(), kUserNameValue); EXPECT_EQ(environment_object_->access_token(), kFakeAccessTokenFetcherAccessTokenValue); fake_access_token_fetcher()->set_fail_access_token_from_refresh_token(true); // We expect the refresh to have failed, the user name to remain valid, // and the access token to have been cleared. EXPECT_FALSE(environment_object_->RefreshAccessToken()); EXPECT_TRUE(environment_object_->access_token().empty()); EXPECT_EQ(environment_object_->user_name(), kUserNameValue); } TEST_F(AppRemotingTestDriverEnvironmentTest, GetRemoteHostInfoSuccess) { Initialize(); // Pass in an empty auth code since we are using a refresh token. EXPECT_TRUE(environment_object_->Initialize(std::string())); RemoteHostInfo remote_host_info; EXPECT_TRUE(environment_object_->GetRemoteHostInfoForApplicationId( kTestApplicationId, &remote_host_info)); EXPECT_TRUE(remote_host_info.IsReadyForConnection()); } TEST_F(AppRemotingTestDriverEnvironmentTest, GetRemoteHostInfoFailure) { Initialize(); // Pass in an empty auth code since we are using a refresh token. EXPECT_TRUE(environment_object_->Initialize(std::string())); fake_remote_host_info_fetcher_.set_fail_retrieve_remote_host_info(true); RemoteHostInfo remote_host_info; EXPECT_FALSE(environment_object_->GetRemoteHostInfoForApplicationId( kTestApplicationId, &remote_host_info)); } TEST_F(AppRemotingTestDriverEnvironmentTest, GetRemoteHostInfoWithoutInitializing) { Initialize(); RemoteHostInfo remote_host_info; EXPECT_FALSE(environment_object_->GetRemoteHostInfoForApplicationId( kTestApplicationId, &remote_host_info)); } TEST_F(AppRemotingTestDriverEnvironmentTest, NoRemoteHostsReleasedOnTearDown) { // Use the default options as the flag to release the remote hosts is not // enabled by default. Initialize(); // Pass in an empty auth code since we are using a refresh token. EXPECT_TRUE(environment_object_->Initialize(std::string())); RemoteHostInfo remote_host_info; EXPECT_TRUE(environment_object_->GetRemoteHostInfoForApplicationId( kTestApplicationId, &remote_host_info)); EXPECT_TRUE(remote_host_info.IsReadyForConnection()); EXPECT_EQ(fake_report_issue_request_.get_host_ids_released().size(), 0UL); environment_object_->AddHostToReleaseList(kTestApplicationId, kTestHostId1); // Note: We are using a static cast here because the TearDown() method is // private as it is an interface method that we only want to call // directly in tests or by the GTEST framework. static_cast(environment_object_.get())->TearDown(); // Verify no hosts were released via a report issue request. EXPECT_EQ(fake_report_issue_request_.get_host_ids_released().size(), 0UL); } TEST_F(AppRemotingTestDriverEnvironmentTest, OneRemoteHostReleasedOnTearDown) { AppRemotingTestDriverEnvironment::EnvironmentOptions options; options.user_name = kUserNameValue; options.release_hosts_when_done = true; options.service_environment = kDeveloperEnvironment; Initialize(options); // Pass in an empty auth code since we are using a refresh token. EXPECT_TRUE(environment_object_->Initialize(std::string())); RemoteHostInfo remote_host_info; EXPECT_TRUE(environment_object_->GetRemoteHostInfoForApplicationId( kTestApplicationId, &remote_host_info)); EXPECT_TRUE(remote_host_info.IsReadyForConnection()); EXPECT_EQ(fake_report_issue_request_.get_host_ids_released().size(), 0UL); environment_object_->AddHostToReleaseList(kTestApplicationId, kTestHostId1); // Note: We are using a static cast here because the TearDown() method is // private as it is an interface method that we only want to call // directly in tests or by the GTEST framework. static_cast(environment_object_.get())->TearDown(); std::string expected_host( MakeFormattedStringForReleasedHost(kTestApplicationId, kTestHostId1)); std::vector actual_host_list = fake_report_issue_request_.get_host_ids_released(); EXPECT_EQ(actual_host_list.size(), 1UL); EXPECT_EQ(actual_host_list[0], expected_host); } TEST_F(AppRemotingTestDriverEnvironmentTest, RemoteHostsReleasedOnTearDown) { AppRemotingTestDriverEnvironment::EnvironmentOptions options; options.user_name = kUserNameValue; options.release_hosts_when_done = true; options.service_environment = kDeveloperEnvironment; Initialize(options); // Pass in an empty auth code since we are using a refresh token. EXPECT_TRUE(environment_object_->Initialize(std::string())); RemoteHostInfo remote_host_info; EXPECT_TRUE(environment_object_->GetRemoteHostInfoForApplicationId( kTestApplicationId, &remote_host_info)); EXPECT_TRUE(remote_host_info.IsReadyForConnection()); std::vector expected_host_list; environment_object_->AddHostToReleaseList(kTestApplicationId, kTestHostId1); expected_host_list.push_back( MakeFormattedStringForReleasedHost(kTestApplicationId, kTestHostId1)); environment_object_->AddHostToReleaseList(kAnotherTestApplicationId, kTestHostId2); expected_host_list.push_back(MakeFormattedStringForReleasedHost( kAnotherTestApplicationId, kTestHostId2)); environment_object_->AddHostToReleaseList(kTestApplicationId, kTestHostId3); expected_host_list.push_back( MakeFormattedStringForReleasedHost(kTestApplicationId, kTestHostId3)); // Note: We are using a static cast here because the TearDown() method is // private as it is an interface method that we only want to call // directly in tests or by the GTEST framework. static_cast(environment_object_.get())->TearDown(); std::vector actual_host_list = fake_report_issue_request_.get_host_ids_released(); std::sort(actual_host_list.begin(), actual_host_list.end()); std::sort(expected_host_list.begin(), expected_host_list.end()); EXPECT_EQ(actual_host_list.size(), expected_host_list.size()); for (size_t i = 0; i < actual_host_list.size(); ++i) { EXPECT_EQ(actual_host_list[i], expected_host_list[i]); } } TEST_F(AppRemotingTestDriverEnvironmentTest, RemoteHostsReleasedOnce) { AppRemotingTestDriverEnvironment::EnvironmentOptions options; options.user_name = kUserNameValue; options.release_hosts_when_done = true; options.service_environment = kDeveloperEnvironment; Initialize(options); // Pass in an empty auth code since we are using a refresh token. EXPECT_TRUE(environment_object_->Initialize(std::string())); RemoteHostInfo remote_host_info; EXPECT_TRUE(environment_object_->GetRemoteHostInfoForApplicationId( kTestApplicationId, &remote_host_info)); EXPECT_TRUE(remote_host_info.IsReadyForConnection()); std::vector expected_host_list; environment_object_->AddHostToReleaseList(kTestApplicationId, kTestHostId1); expected_host_list.push_back( MakeFormattedStringForReleasedHost(kTestApplicationId, kTestHostId1)); environment_object_->AddHostToReleaseList(kAnotherTestApplicationId, kTestHostId2); expected_host_list.push_back(MakeFormattedStringForReleasedHost( kAnotherTestApplicationId, kTestHostId2)); environment_object_->AddHostToReleaseList(kTestApplicationId, kTestHostId3); expected_host_list.push_back( MakeFormattedStringForReleasedHost(kTestApplicationId, kTestHostId3)); // Attempt to add the previous hosts again, they should not be added since // they will already exist in the list of hosts to release. environment_object_->AddHostToReleaseList(kTestApplicationId, kTestHostId1); environment_object_->AddHostToReleaseList(kAnotherTestApplicationId, kTestHostId2); environment_object_->AddHostToReleaseList(kTestApplicationId, kTestHostId3); // Note: We are using a static cast here because the TearDown() method is // private as it is an interface method that we only want to call // directly in tests or by the GTEST framework. static_cast(environment_object_.get())->TearDown(); std::vector actual_host_list = fake_report_issue_request_.get_host_ids_released(); std::sort(actual_host_list.begin(), actual_host_list.end()); std::sort(expected_host_list.begin(), expected_host_list.end()); EXPECT_EQ(actual_host_list.size(), expected_host_list.size()); for (size_t i = 0; i < actual_host_list.size(); ++i) { EXPECT_EQ(actual_host_list[i], expected_host_list[i]); } } } // namespace test } // namespace remoting