diff options
author | joedow <joedow@chromium.org> | 2015-03-05 18:41:02 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-03-06 02:41:58 +0000 |
commit | dd5660bd5b757e906eee390b83c8a7585822a60d (patch) | |
tree | 32592da2e604f96a50e180e2e0cdecc60c56eb29 /remoting | |
parent | dbf8bfd7fa34d69e880f0b8073a0441f439bf08a (diff) | |
download | chromium_src-dd5660bd5b757e906eee390b83c8a7585822a60d.zip chromium_src-dd5660bd5b757e906eee390b83c8a7585822a60d.tar.gz chromium_src-dd5660bd5b757e906eee390b83c8a7585822a60d.tar.bz2 |
Adding the RemoteHostInfo and RemoteHostInfoFetcher classes and unittests for use with the App Remoting Test Driver.
This changelist also includes some lint error cleanup and updating of
assertions in the unittest code to remove the c_str() calls.
BUG=462307
Review URL: https://codereview.chromium.org/962763002
Cr-Commit-Position: refs/heads/master@{#319396}
Diffstat (limited to 'remoting')
21 files changed, 1053 insertions, 105 deletions
diff --git a/remoting/BUILD.gn b/remoting/BUILD.gn index f87db3d..047650f 100644 --- a/remoting/BUILD.gn +++ b/remoting/BUILD.gn @@ -33,12 +33,15 @@ source_set("test_support") { "test/fake_network_manager.h", "test/fake_port_allocator.cc", "test/fake_port_allocator.h", + "test/fake_remote_host_info_fetcher.cc", "test/fake_socket_factory.cc", "test/fake_socket_factory.h", "test/leaky_bucket.cc", "test/leaky_bucket.h", "test/mock_access_token_fetcher.cc", "test/refresh_token_store.cc", + "test/remote_host_info.cc", + "test/remote_host_info_fetcher.cc", ] deps = [ @@ -72,6 +75,7 @@ if (!is_win && !is_mac) { "signaling/server_log_entry_unittest.h", "test/access_token_fetcher_unittest.cc", "test/app_remoting_test_driver_environment_unittest.cc", + "test/remote_host_info_fetcher_unittest.cc", ] # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. diff --git a/remoting/app_remoting_test.gyp b/remoting/app_remoting_test.gyp index 1999e22..f4825df 100644 --- a/remoting/app_remoting_test.gyp +++ b/remoting/app_remoting_test.gyp @@ -33,6 +33,8 @@ 'test/access_token_fetcher.cc', 'test/app_remoting_test_driver_environment.cc', 'test/refresh_token_store.cc', + 'test/remote_host_info.cc', + 'test/remote_host_info_fetcher.cc', ], }, # end of target 'ar_test_driver_common' { diff --git a/remoting/remoting_test.gypi b/remoting/remoting_test.gypi index cb25f63..911af72 100644 --- a/remoting/remoting_test.gypi +++ b/remoting/remoting_test.gypi @@ -53,12 +53,15 @@ 'test/fake_network_manager.h', 'test/fake_port_allocator.cc', 'test/fake_port_allocator.h', + 'test/fake_remote_host_info_fetcher.cc', 'test/fake_socket_factory.cc', 'test/fake_socket_factory.h', 'test/leaky_bucket.cc', 'test/leaky_bucket.h', 'test/mock_access_token_fetcher.cc', 'test/refresh_token_store.cc', + 'test/remote_host_info.cc', + 'test/remote_host_info_fetcher.cc', ], 'conditions': [ ['enable_remoting_host == 0', { @@ -235,7 +238,8 @@ 'signaling/server_log_entry_unittest.cc', 'signaling/server_log_entry_unittest.h', 'test/access_token_fetcher_unittest.cc', - 'test/app_remoting_test_driver_environment_unittest.cc' + 'test/app_remoting_test_driver_environment_unittest.cc', + 'test/remote_host_info_fetcher_unittest.cc', ], 'conditions': [ [ 'OS=="win"', { diff --git a/remoting/test/access_token_fetcher.cc b/remoting/test/access_token_fetcher.cc index 9d858ff..5fc36ef 100644 --- a/remoting/test/access_token_fetcher.cc +++ b/remoting/test/access_token_fetcher.cc @@ -4,6 +4,9 @@ #include "remoting/test/access_token_fetcher.h" +#include <string> +#include <vector> + #include "base/bind.h" #include "base/logging.h" #include "base/message_loop/message_loop.h" @@ -38,8 +41,7 @@ const std::vector<std::string> MakeAppRemotingScopeVector() { const std::vector<std::string> kAppRemotingScopeVector = MakeAppRemotingScopeVector(); - -} +} // namespace namespace remoting { namespace test { @@ -51,8 +53,7 @@ AccessTokenFetcher::AccessTokenFetcher() { kOauthRedirectUrl}; } -AccessTokenFetcher::~AccessTokenFetcher() { -} +AccessTokenFetcher::~AccessTokenFetcher() {} void AccessTokenFetcher::GetAccessTokenFromAuthCode( const std::string& auth_code, diff --git a/remoting/test/access_token_fetcher_unittest.cc b/remoting/test/access_token_fetcher_unittest.cc index 46747ae..b061512 100644 --- a/remoting/test/access_token_fetcher_unittest.cc +++ b/remoting/test/access_token_fetcher_unittest.cc @@ -4,6 +4,8 @@ #include "remoting/test/access_token_fetcher.h" +#include <string> + #include "base/bind.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" @@ -12,25 +14,25 @@ #include "testing/gtest/include/gtest/gtest.h" namespace { - const char kAuthCodeValue[] = "test_auth_code_value"; - const char kAccessTokenValue[] = "test_access_token_value"; - const char kRefreshTokenValue[] = "test_refresh_token_value"; - const char kAuthCodeExchangeValidResponse[] = +const char kAuthCodeValue[] = "test_auth_code_value"; +const char kAccessTokenValue[] = "test_access_token_value"; +const char kRefreshTokenValue[] = "test_refresh_token_value"; +const char kAuthCodeExchangeValidResponse[] = "{" " \"refresh_token\": \"test_refresh_token_value\"," " \"access_token\": \"test_access_token_value\"," " \"expires_in\": 3600," " \"token_type\": \"Bearer\"" "}"; - const char kAuthCodeExchangeEmptyResponse[] = "{}"; - const char kRefreshTokenExchangeValidResponse[] = +const char kAuthCodeExchangeEmptyResponse[] = "{}"; +const char kRefreshTokenExchangeValidResponse[] = "{" " \"access_token\": \"test_access_token_value\"," " \"expires_in\": 3600," " \"token_type\": \"Bearer\"" "}"; - const char kRefreshTokenExchangeEmptyResponse[] = "{}"; - const char kValidTokenInfoResponse[] = +const char kRefreshTokenExchangeEmptyResponse[] = "{}"; +const char kValidTokenInfoResponse[] = "{" " \"audience\": \"blah.apps.googleusercontent.blah.com\"," " \"used_id\": \"1234567890\"," @@ -38,11 +40,11 @@ namespace { " \"expires_in\": \"1800\"," " \"token_type\": \"Bearer\"" "}"; - const char kInvalidTokenInfoResponse[] = +const char kInvalidTokenInfoResponse[] = "{" " \"error\": \"invalid_token\"" "}"; -} +} // namespace namespace remoting { namespace test { @@ -122,8 +124,8 @@ TEST_F(AccessTokenFetcherTest, ExchangeAuthCodeForAccessToken) { run_loop.Run(); - EXPECT_STREQ(kAccessTokenValue, access_token_retrieved_.c_str()); - EXPECT_STREQ(kRefreshTokenValue, refresh_token_retrieved_.c_str()); + EXPECT_EQ(access_token_retrieved_.compare(kAccessTokenValue), 0); + EXPECT_EQ(refresh_token_retrieved_.compare(kRefreshTokenValue), 0); } TEST_F(AccessTokenFetcherTest, ExchangeRefreshTokenForAccessToken) { @@ -152,8 +154,8 @@ TEST_F(AccessTokenFetcherTest, ExchangeRefreshTokenForAccessToken) { run_loop.Run(); - EXPECT_STREQ(kAccessTokenValue, access_token_retrieved_.c_str()); - EXPECT_STREQ(kRefreshTokenValue, refresh_token_retrieved_.c_str()); + EXPECT_EQ(access_token_retrieved_.compare(kAccessTokenValue), 0); + EXPECT_EQ(refresh_token_retrieved_.compare(kRefreshTokenValue), 0); } TEST_F(AccessTokenFetcherTest, MultipleAccessTokenCalls) { @@ -183,8 +185,8 @@ TEST_F(AccessTokenFetcherTest, MultipleAccessTokenCalls) { run_loop->Run(); - EXPECT_STREQ(kAccessTokenValue, access_token_retrieved_.c_str()); - EXPECT_STREQ(kRefreshTokenValue, refresh_token_retrieved_.c_str()); + EXPECT_EQ(access_token_retrieved_.compare(kAccessTokenValue), 0); + EXPECT_EQ(refresh_token_retrieved_.compare(kRefreshTokenValue), 0); // Reset our token data for the next iteration. access_token_retrieved_.clear(); @@ -209,10 +211,8 @@ TEST_F(AccessTokenFetcherTest, MultipleAccessTokenCalls) { run_loop->Run(); - EXPECT_STREQ(kAccessTokenValue, - access_token_retrieved_.c_str()); - EXPECT_STREQ(kRefreshTokenValue, - refresh_token_retrieved_.c_str()); + EXPECT_EQ(access_token_retrieved_.compare(kAccessTokenValue), 0); + EXPECT_EQ(refresh_token_retrieved_.compare(kRefreshTokenValue), 0); run_loop.reset(new base::RunLoop()); access_token_callback = @@ -230,10 +230,8 @@ TEST_F(AccessTokenFetcherTest, MultipleAccessTokenCalls) { run_loop->Run(); - EXPECT_STREQ(kAccessTokenValue, - access_token_retrieved_.c_str()); - EXPECT_STREQ(kRefreshTokenValue, - refresh_token_retrieved_.c_str()); + EXPECT_EQ(access_token_retrieved_.compare(kAccessTokenValue), 0); + EXPECT_EQ(refresh_token_retrieved_.compare(kRefreshTokenValue), 0); } TEST_F(AccessTokenFetcherTest, ExchangeAuthCode_Unauthorized_Error) { @@ -256,8 +254,9 @@ TEST_F(AccessTokenFetcherTest, ExchangeAuthCode_Unauthorized_Error) { run_loop.Run(); - EXPECT_STREQ("", access_token_retrieved_.c_str()); - EXPECT_STREQ("", refresh_token_retrieved_.c_str()); + // Our callback should have been called with empty strings. + EXPECT_TRUE(access_token_retrieved_.empty()); + EXPECT_TRUE(refresh_token_retrieved_.empty()); } TEST_F(AccessTokenFetcherTest, ExchangeRefreshToken_Unauthorized_Error) { @@ -280,8 +279,9 @@ TEST_F(AccessTokenFetcherTest, ExchangeRefreshToken_Unauthorized_Error) { run_loop.Run(); - EXPECT_STREQ("", access_token_retrieved_.c_str()); - EXPECT_STREQ("", refresh_token_retrieved_.c_str()); + // Our callback should have been called with empty strings. + EXPECT_TRUE(access_token_retrieved_.empty()); + EXPECT_TRUE(refresh_token_retrieved_.empty()); } TEST_F(AccessTokenFetcherTest, ExchangeAuthCode_NetworkError) { @@ -304,8 +304,9 @@ TEST_F(AccessTokenFetcherTest, ExchangeAuthCode_NetworkError) { run_loop.Run(); - EXPECT_STREQ("", access_token_retrieved_.c_str()); - EXPECT_STREQ("", refresh_token_retrieved_.c_str()); + // Our callback should have been called with empty strings. + EXPECT_TRUE(access_token_retrieved_.empty()); + EXPECT_TRUE(refresh_token_retrieved_.empty()); } TEST_F(AccessTokenFetcherTest, ExchangeRefreshToken_NetworkError) { @@ -328,8 +329,9 @@ TEST_F(AccessTokenFetcherTest, ExchangeRefreshToken_NetworkError) { run_loop.Run(); - EXPECT_STREQ("", access_token_retrieved_.c_str()); - EXPECT_STREQ("", refresh_token_retrieved_.c_str()); + // Our callback should have been called with empty strings. + EXPECT_TRUE(access_token_retrieved_.empty()); + EXPECT_TRUE(refresh_token_retrieved_.empty()); } TEST_F(AccessTokenFetcherTest, AuthCode_GetTokenInfoResponse_InvalidToken) { @@ -359,8 +361,8 @@ TEST_F(AccessTokenFetcherTest, AuthCode_GetTokenInfoResponse_InvalidToken) { run_loop.Run(); // Our callback should have been called with empty strings. - EXPECT_STREQ("", access_token_retrieved_.c_str()); - EXPECT_STREQ("", refresh_token_retrieved_.c_str()); + EXPECT_TRUE(access_token_retrieved_.empty()); + EXPECT_TRUE(refresh_token_retrieved_.empty()); } TEST_F(AccessTokenFetcherTest, ExchangeAuthCodeForAccessToken_EmptyToken) { @@ -384,8 +386,8 @@ TEST_F(AccessTokenFetcherTest, ExchangeAuthCodeForAccessToken_EmptyToken) { run_loop.Run(); // Our callback should have been called with empty strings. - EXPECT_STREQ("", access_token_retrieved_.c_str()); - EXPECT_STREQ("", refresh_token_retrieved_.c_str()); + EXPECT_TRUE(access_token_retrieved_.empty()); + EXPECT_TRUE(refresh_token_retrieved_.empty()); } TEST_F(AccessTokenFetcherTest, RefreshToken_GetTokenInfoResponse_InvalidToken) { @@ -415,8 +417,8 @@ TEST_F(AccessTokenFetcherTest, RefreshToken_GetTokenInfoResponse_InvalidToken) { run_loop.Run(); // Our callback should have been called with empty strings. - EXPECT_STREQ("", access_token_retrieved_.c_str()); - EXPECT_STREQ("", refresh_token_retrieved_.c_str()); + EXPECT_TRUE(access_token_retrieved_.empty()); + EXPECT_TRUE(refresh_token_retrieved_.empty()); } TEST_F(AccessTokenFetcherTest, ExchangeRefreshTokenForAccessToken_EmptyToken) { @@ -440,8 +442,8 @@ TEST_F(AccessTokenFetcherTest, ExchangeRefreshTokenForAccessToken_EmptyToken) { run_loop.Run(); // Our callback should have been called with empty strings. - EXPECT_STREQ("", access_token_retrieved_.c_str()); - EXPECT_STREQ("", refresh_token_retrieved_.c_str()); + EXPECT_TRUE(access_token_retrieved_.empty()); + EXPECT_TRUE(refresh_token_retrieved_.empty()); } } // namespace test diff --git a/remoting/test/app_remoting_test_driver.cc b/remoting/test/app_remoting_test_driver.cc index 532005a..3b2e997 100644 --- a/remoting/test/app_remoting_test_driver.cc +++ b/remoting/test/app_remoting_test_driver.cc @@ -160,16 +160,19 @@ int main(int argc, char** argv) { // refreshing their credentials. auth_code = command_line->GetSwitchValueASCII(switches::kAuthCodeSwitchName); - std::string service_environment; // If the user passed in a service environment, use it, otherwise set a // default value. - service_environment = command_line->GetSwitchValueASCII( + remoting::test::ServiceEnvironment service_environment; + std::string service_environment_switch = command_line->GetSwitchValueASCII( switches::kServiceEnvironmentSwitchName); - if (service_environment.empty()) { - // Default to the development service environment. - service_environment = "dev"; - } else if (service_environment != "test" && service_environment != "dev") { - // Only two values are allowed, so validate them before proceeding. + if (service_environment_switch.empty() || + service_environment_switch == "dev") { + service_environment = + remoting::test::ServiceEnvironment::kDeveloperEnvironment; + } else if (service_environment_switch == "test") { + service_environment = + remoting::test::ServiceEnvironment::kTestingEnvironment; + } else { LOG(ERROR) << "Invalid " << switches::kServiceEnvironmentSwitchName << " argument passed in."; PrintUsage(); diff --git a/remoting/test/app_remoting_test_driver_environment.cc b/remoting/test/app_remoting_test_driver_environment.cc index 119e6e9..874e46a 100644 --- a/remoting/test/app_remoting_test_driver_environment.cc +++ b/remoting/test/app_remoting_test_driver_environment.cc @@ -9,6 +9,9 @@ #include "base/logging.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" +#include "remoting/test/access_token_fetcher.h" +#include "remoting/test/refresh_token_store.h" +#include "remoting/test/remote_host_info.h" namespace remoting { namespace test { @@ -17,13 +20,14 @@ AppRemotingTestDriverEnvironment* AppRemotingSharedData; AppRemotingTestDriverEnvironment::AppRemotingTestDriverEnvironment( const std::string& user_name, - const std::string& service_environment) + ServiceEnvironment service_environment) : user_name_(user_name), service_environment_(service_environment), test_access_token_fetcher_(nullptr), - test_refresh_token_store_(nullptr) { + test_refresh_token_store_(nullptr), + test_remote_host_info_fetcher_(nullptr) { DCHECK(!user_name_.empty()); - DCHECK(!service_environment.empty()); + DCHECK(service_environment < kUnknownEnvironment); } AppRemotingTestDriverEnvironment::~AppRemotingTestDriverEnvironment() { @@ -74,6 +78,55 @@ bool AppRemotingTestDriverEnvironment::RefreshAccessToken() { return RetrieveAccessToken(std::string()); } +bool AppRemotingTestDriverEnvironment::GetRemoteHostInfoForApplicationId( + const std::string& application_id, + RemoteHostInfo* remote_host_info) { + DCHECK(!application_id.empty()); + DCHECK(remote_host_info); + + if (access_token_.empty()) { + LOG(ERROR) << "RemoteHostInfo requested without a valid access token. " + << "Ensure the environment object has been initialized."; + return false; + } + + scoped_ptr<base::MessageLoopForIO> message_loop; + if (!base::MessageLoop::current()) { + // Create a temporary message loop if the current thread does not already + // have one so we can use its task runner for our network request. + message_loop.reset(new base::MessageLoopForIO); + } + + base::RunLoop run_loop; + + RemoteHostInfoCallback remote_host_info_fetch_callback = + base::Bind(&AppRemotingTestDriverEnvironment::OnRemoteHostInfoRetrieved, + base::Unretained(this), + run_loop.QuitClosure(), + remote_host_info); + + // If a unit test has set |test_remote_host_info_fetcher_| then we should use + // it below. Note that we do not want to destroy the test object at the end + // of the function which is why we have the dance below. + scoped_ptr<RemoteHostInfoFetcher> temporary_remote_host_info_fetcher; + RemoteHostInfoFetcher* remote_host_info_fetcher = + test_remote_host_info_fetcher_; + if (!remote_host_info_fetcher) { + temporary_remote_host_info_fetcher.reset(new RemoteHostInfoFetcher()); + remote_host_info_fetcher = temporary_remote_host_info_fetcher.get(); + } + + remote_host_info_fetcher->RetrieveRemoteHostInfo( + application_id, + access_token_, + service_environment_, + remote_host_info_fetch_callback); + + run_loop.Run(); + + return remote_host_info->IsReadyForConnection(); +} + void AppRemotingTestDriverEnvironment::SetAccessTokenFetcherForTest( AccessTokenFetcher* access_token_fetcher) { DCHECK(access_token_fetcher); @@ -88,6 +141,13 @@ void AppRemotingTestDriverEnvironment::SetRefreshTokenStoreForTest( test_refresh_token_store_ = refresh_token_store; } +void AppRemotingTestDriverEnvironment::SetRemoteHostInfoFetcherForTest( + RemoteHostInfoFetcher* remote_host_info_fetcher) { + DCHECK(remote_host_info_fetcher); + + test_remote_host_info_fetcher_ = remote_host_info_fetcher; +} + bool AppRemotingTestDriverEnvironment::RetrieveAccessToken( const std::string& auth_code) { scoped_ptr<base::MessageLoopForIO> message_loop; @@ -177,5 +237,18 @@ void AppRemotingTestDriverEnvironment::OnAccessTokenRetrieved( done_closure.Run(); } +void AppRemotingTestDriverEnvironment::OnRemoteHostInfoRetrieved( + base::Closure done_closure, + RemoteHostInfo* remote_host_info, + const RemoteHostInfo& retrieved_remote_host_info) { + DCHECK(remote_host_info); + + if (retrieved_remote_host_info.IsReadyForConnection()) { + *remote_host_info = retrieved_remote_host_info; + } + + done_closure.Run(); +} + } // namespace test } // namespace remoting diff --git a/remoting/test/app_remoting_test_driver_environment.h b/remoting/test/app_remoting_test_driver_environment.h index 579e209..c814f0b 100644 --- a/remoting/test/app_remoting_test_driver_environment.h +++ b/remoting/test/app_remoting_test_driver_environment.h @@ -5,23 +5,27 @@ #ifndef REMOTING_TEST_APP_REMOTING_TEST_DRIVER_ENVIRONMENT_H_ #define REMOTING_TEST_APP_REMOTING_TEST_DRIVER_ENVIRONMENT_H_ +#include <string> + #include "base/memory/scoped_ptr.h" -#include "remoting/test/access_token_fetcher.h" -#include "remoting/test/refresh_token_store.h" +#include "remoting/test/remote_host_info_fetcher.h" #include "testing/gtest/include/gtest/gtest.h" namespace remoting { namespace test { +class AccessTokenFetcher; +class RefreshTokenStore; +struct RemoteHostInfo; + // Globally accessible to all test fixtures and cases and has its // lifetime managed by the GTest framework. It is responsible for managing -// access tokens and caching remote host connection information. -// TODO(joedow) Add remote host connection functionality. +// access tokens and retrieving remote host connection information. class AppRemotingTestDriverEnvironment : public testing::Environment { public: AppRemotingTestDriverEnvironment( const std::string& user_name, - const std::string& service_environment); + ServiceEnvironment service_environment); ~AppRemotingTestDriverEnvironment() override; // Returns false if a valid access token cannot be retrieved. @@ -31,9 +35,17 @@ class AppRemotingTestDriverEnvironment : public testing::Environment { // Returns true if a valid access token has been retrieved. bool RefreshAccessToken(); + // Synchronously request remote host information for |application_id|. + // Returns true if the request was successful and |remote_host_info| is valid. + bool GetRemoteHostInfoForApplicationId( + const std::string& application_id, + RemoteHostInfo* remote_host_info); + // Used to set fake/mock objects for AppRemotingTestDriverEnvironment tests. void SetAccessTokenFetcherForTest(AccessTokenFetcher* access_token_fetcher); void SetRefreshTokenStoreForTest(RefreshTokenStore* refresh_token_store); + void SetRemoteHostInfoFetcherForTest( + RemoteHostInfoFetcher* remote_host_info_fetcher); // Accessors for fields used by tests. const std::string& access_token() const { return access_token_; } @@ -48,9 +60,16 @@ class AppRemotingTestDriverEnvironment : public testing::Environment { // Called after the access token fetcher completes. // The tokens will be empty on failure. void OnAccessTokenRetrieved( - base::Closure done_closure, - const std::string& access_token, - const std::string& refresh_token); + base::Closure done_closure, + const std::string& access_token, + const std::string& refresh_token); + + // Called after the remote host info fetcher completes. + // |remote_host_info| is not modified on failure. + void OnRemoteHostInfoRetrieved( + base::Closure done_closure, + RemoteHostInfo* remote_host_info, + const RemoteHostInfo& retrieved_remote_host_info); // Used for authenticating with the app remoting service API. std::string access_token_; @@ -62,8 +81,7 @@ class AppRemotingTestDriverEnvironment : public testing::Environment { std::string user_name_; // Service API to target when retrieving remote host connection information. - // TODO(joedow): Turn this into an enum when remote_host code is added. - std::string service_environment_; + ServiceEnvironment service_environment_; // Access token fetcher used by TestDriverEnvironment tests. remoting::test::AccessTokenFetcher* test_access_token_fetcher_; @@ -71,6 +89,9 @@ class AppRemotingTestDriverEnvironment : public testing::Environment { // RefreshTokenStore used by TestDriverEnvironment tests. remoting::test::RefreshTokenStore* test_refresh_token_store_; + // RemoteHostInfoFetcher used by TestDriverEnvironment tests. + remoting::test::RemoteHostInfoFetcher* test_remote_host_info_fetcher_; + DISALLOW_COPY_AND_ASSIGN(AppRemotingTestDriverEnvironment); }; diff --git a/remoting/test/app_remoting_test_driver_environment_unittest.cc b/remoting/test/app_remoting_test_driver_environment_unittest.cc index 58e96ea..97638bf 100644 --- a/remoting/test/app_remoting_test_driver_environment_unittest.cc +++ b/remoting/test/app_remoting_test_driver_environment_unittest.cc @@ -5,6 +5,7 @@ #include "remoting/test/app_remoting_test_driver_environment.h" #include "remoting/test/fake_access_token_fetcher.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/gtest/include/gtest/gtest.h" @@ -13,7 +14,7 @@ namespace { const char kAuthCodeValue[] = "4/892379827345jkefvkdfbv"; const char kRefreshTokenValue[] = "1/lkjalseLKJlsiJgr45jbv"; const char kUserNameValue[] = "remoting_user@gmail.com"; -const char kDevEnvironmentValue[] = "dev"; +const char kTestApplicationId[] = "sadlkjlsjgadjfgoajdfgagb"; } namespace remoting { @@ -25,12 +26,10 @@ using testing::_; // file system dependencies when testing the TestDriverEnvironment. class FakeRefreshTokenStore : public RefreshTokenStore { public: - FakeRefreshTokenStore() { - // Set some success defaults. - refresh_token_value = kRefreshTokenValue; - refresh_token_write_attempted = false; - refresh_token_write_succeeded = true; - } + FakeRefreshTokenStore() : + refresh_token_value(kRefreshTokenValue), + refresh_token_write_succeeded(true), + refresh_token_write_attempted(false) {} ~FakeRefreshTokenStore() override {} std::string FetchRefreshToken() override { @@ -53,6 +52,7 @@ class FakeRefreshTokenStore : public RefreshTokenStore { bool refresh_token_write_attempted; std::string refresh_token_value_written; + private: DISALLOW_COPY_AND_ASSIGN(FakeRefreshTokenStore); }; @@ -72,7 +72,7 @@ TEST(AppRemotingTestDriverEnvironmentTest, InitializeObjectWithAuthCode) { AppRemotingTestDriverEnvironment environment_object( kUserNameValue, - kDevEnvironmentValue); + kDeveloperEnvironment); environment_object.SetAccessTokenFetcherForTest(&mock_access_token_fetcher); @@ -82,11 +82,11 @@ TEST(AppRemotingTestDriverEnvironmentTest, InitializeObjectWithAuthCode) { EXPECT_TRUE(init_result); EXPECT_TRUE(fake_token_store.refresh_token_write_attempted); - EXPECT_STREQ(kFakeAccessTokenFetcherRefreshTokenValue, - fake_token_store.refresh_token_value_written.c_str()); - EXPECT_STREQ(kUserNameValue, environment_object.user_name().c_str()); - EXPECT_STREQ(kFakeAccessTokenFetcherAccessTokenValue, - environment_object.access_token().c_str()); + EXPECT_EQ(fake_token_store.refresh_token_value_written.compare( + kFakeAccessTokenFetcherRefreshTokenValue), 0); + EXPECT_EQ(environment_object.user_name().compare(kUserNameValue), 0); + EXPECT_EQ(environment_object.access_token().compare( + kFakeAccessTokenFetcherAccessTokenValue), 0); // Attempt to init again, we should not see any additional calls or errors. init_result = environment_object.Initialize(kAuthCodeValue); @@ -114,7 +114,7 @@ TEST(AppRemotingTestDriverEnvironmentTest, InitializeObjectWithAuthCodeFailed) { AppRemotingTestDriverEnvironment environment_object( kUserNameValue, - kDevEnvironmentValue); + kDeveloperEnvironment); environment_object.SetAccessTokenFetcherForTest(&mock_access_token_fetcher); @@ -142,7 +142,7 @@ TEST(AppRemotingTestDriverEnvironmentTest, InitializeObjectWithRefreshToken) { AppRemotingTestDriverEnvironment environment_object( kUserNameValue, - kDevEnvironmentValue); + kDeveloperEnvironment); environment_object.SetAccessTokenFetcherForTest(&mock_access_token_fetcher); @@ -158,9 +158,9 @@ TEST(AppRemotingTestDriverEnvironmentTest, InitializeObjectWithRefreshToken) { EXPECT_FALSE(fake_token_store.refresh_token_write_attempted); // Verify the object was initialized correctly. - EXPECT_STREQ(kUserNameValue, environment_object.user_name().c_str()); - EXPECT_STREQ(kFakeAccessTokenFetcherAccessTokenValue, - environment_object.access_token().c_str()); + EXPECT_EQ(environment_object.user_name().compare(kUserNameValue), 0); + EXPECT_EQ(environment_object.access_token().compare( + kFakeAccessTokenFetcherAccessTokenValue), 0); // Attempt to init again, we should not see any additional calls or errors. init_result = environment_object.Initialize(std::string()); @@ -189,7 +189,7 @@ TEST(AppRemotingTestDriverEnvironmentTest, AppRemotingTestDriverEnvironment environment_object( kUserNameValue, - kDevEnvironmentValue); + kDeveloperEnvironment); environment_object.SetAccessTokenFetcherForTest(&mock_access_token_fetcher); @@ -220,7 +220,7 @@ TEST(AppRemotingTestDriverEnvironmentTest, AppRemotingTestDriverEnvironment environment_object( kUserNameValue, - kDevEnvironmentValue); + kDeveloperEnvironment); environment_object.SetAccessTokenFetcherForTest(&mock_access_token_fetcher); @@ -254,7 +254,7 @@ TEST(AppRemotingTestDriverEnvironmentTest, AppRemotingTestDriverEnvironment environment_object( kUserNameValue, - kDevEnvironmentValue); + kDeveloperEnvironment); environment_object.SetAccessTokenFetcherForTest(&mock_access_token_fetcher); @@ -290,7 +290,7 @@ TEST(AppRemotingTestDriverEnvironmentTest, AppRemotingTestDriverEnvironment environment_object( kUserNameValue, - kDevEnvironmentValue); + kDeveloperEnvironment); environment_object.SetAccessTokenFetcherForTest(&mock_access_token_fetcher); @@ -300,11 +300,11 @@ TEST(AppRemotingTestDriverEnvironmentTest, EXPECT_TRUE(init_result); EXPECT_TRUE(fake_token_store.refresh_token_write_attempted); - EXPECT_STREQ(kFakeAccessTokenFetcherRefreshTokenValue, - fake_token_store.refresh_token_value_written.c_str()); - EXPECT_STREQ(kUserNameValue, environment_object.user_name().c_str()); - EXPECT_STREQ(kFakeAccessTokenFetcherAccessTokenValue, - environment_object.access_token().c_str()); + EXPECT_EQ(fake_token_store.refresh_token_value_written.compare( + kFakeAccessTokenFetcherRefreshTokenValue), 0); + EXPECT_EQ(environment_object.user_name().compare(kUserNameValue), 0); + EXPECT_EQ(environment_object.access_token().compare( + kFakeAccessTokenFetcherAccessTokenValue), 0); // Attempt to init again, we should not see any additional calls or errors. bool refresh_result = environment_object.RefreshAccessToken(); @@ -337,7 +337,7 @@ TEST(AppRemotingTestDriverEnvironmentTest, RefreshAccessTokenFailure) { AppRemotingTestDriverEnvironment environment_object( kUserNameValue, - kDevEnvironmentValue); + kDeveloperEnvironment); environment_object.SetAccessTokenFetcherForTest(&mock_access_token_fetcher); @@ -347,11 +347,11 @@ TEST(AppRemotingTestDriverEnvironmentTest, RefreshAccessTokenFailure) { EXPECT_TRUE(init_result); EXPECT_TRUE(fake_token_store.refresh_token_write_attempted); - EXPECT_STREQ(kFakeAccessTokenFetcherRefreshTokenValue, - fake_token_store.refresh_token_value_written.c_str()); - EXPECT_STREQ(kUserNameValue, environment_object.user_name().c_str()); - EXPECT_STREQ(kFakeAccessTokenFetcherAccessTokenValue, - environment_object.access_token().c_str()); + EXPECT_EQ(fake_token_store.refresh_token_value_written.compare( + kFakeAccessTokenFetcherRefreshTokenValue), 0); + EXPECT_EQ(environment_object.user_name().compare(kUserNameValue), 0); + EXPECT_EQ(environment_object.access_token().compare( + kFakeAccessTokenFetcherAccessTokenValue), 0); fake_access_token_fetcher->set_fail_access_token_from_refresh_token(true); @@ -360,8 +360,84 @@ TEST(AppRemotingTestDriverEnvironmentTest, RefreshAccessTokenFailure) { // We expect the refresh to have failed, the user name to remain valid, // and the access token to have been cleared. EXPECT_FALSE(refresh_result); - EXPECT_STREQ(kUserNameValue, environment_object.user_name().c_str()); - EXPECT_STREQ("", environment_object.access_token().c_str()); + EXPECT_TRUE(environment_object.access_token().empty()); + EXPECT_EQ(environment_object.user_name().compare(kUserNameValue), 0); +} + +TEST(AppRemotingTestDriverEnvironmentTest, GetRemoteHostInfoSuccess) { + AppRemotingTestDriverEnvironment environment_object(kUserNameValue, + kDeveloperEnvironment); + + FakeAccessTokenFetcher fake_access_token_fetcher; + environment_object.SetAccessTokenFetcherForTest(&fake_access_token_fetcher); + + FakeRefreshTokenStore fake_token_store; + environment_object.SetRefreshTokenStoreForTest(&fake_token_store); + + // Pass in an empty auth code since we are using a refresh token. + bool init_result = environment_object.Initialize(std::string()); + + EXPECT_TRUE(init_result); + + FakeRemoteHostInfoFetcher fake_remote_host_info_fetcher; + environment_object.SetRemoteHostInfoFetcherForTest( + &fake_remote_host_info_fetcher); + + RemoteHostInfo remote_host_info; + bool request_result = environment_object.GetRemoteHostInfoForApplicationId( + kTestApplicationId, &remote_host_info); + + EXPECT_TRUE(request_result); + EXPECT_TRUE(remote_host_info.IsReadyForConnection()); +} + +TEST(AppRemotingTestDriverEnvironmentTest, GetRemoteHostInfoFailure) { + AppRemotingTestDriverEnvironment environment_object(kUserNameValue, + kDeveloperEnvironment); + + FakeAccessTokenFetcher fake_access_token_fetcher; + environment_object.SetAccessTokenFetcherForTest(&fake_access_token_fetcher); + + FakeRefreshTokenStore fake_token_store; + environment_object.SetRefreshTokenStoreForTest(&fake_token_store); + + // Pass in an empty auth code since we are using a refresh token. + bool init_result = environment_object.Initialize(std::string()); + + EXPECT_TRUE(init_result); + + FakeRemoteHostInfoFetcher fake_remote_host_info_fetcher; + fake_remote_host_info_fetcher.set_fail_retrieve_remote_host_info(true); + environment_object.SetRemoteHostInfoFetcherForTest( + &fake_remote_host_info_fetcher); + + RemoteHostInfo remote_host_info; + bool request_result = environment_object.GetRemoteHostInfoForApplicationId( + kTestApplicationId, &remote_host_info); + + EXPECT_FALSE(request_result); +} + +TEST(AppRemotingTestDriverEnvironmentTest, + GetRemoteHostInfoWithoutInitializing) { + AppRemotingTestDriverEnvironment environment_object(kUserNameValue, + kDeveloperEnvironment); + + FakeAccessTokenFetcher fake_access_token_fetcher; + environment_object.SetAccessTokenFetcherForTest(&fake_access_token_fetcher); + + FakeRefreshTokenStore fake_token_store; + environment_object.SetRefreshTokenStoreForTest(&fake_token_store); + + FakeRemoteHostInfoFetcher fake_remote_host_info_fetcher; + environment_object.SetRemoteHostInfoFetcherForTest( + &fake_remote_host_info_fetcher); + + RemoteHostInfo remote_host_info; + bool request_result = environment_object.GetRemoteHostInfoForApplicationId( + kTestApplicationId, &remote_host_info); + + EXPECT_FALSE(request_result); } } // namespace test diff --git a/remoting/test/fake_access_token_fetcher.h b/remoting/test/fake_access_token_fetcher.h index 45856fd..173469b 100644 --- a/remoting/test/fake_access_token_fetcher.h +++ b/remoting/test/fake_access_token_fetcher.h @@ -5,9 +5,9 @@ #ifndef REMOTING_TEST_FAKE_ACCESS_TOKEN_FETCHER_H_ #define REMOTING_TEST_FAKE_ACCESS_TOKEN_FETCHER_H_ -#include "remoting/test/access_token_fetcher.h" +#include <string> -#include "testing/gtest/include/gtest/gtest.h" +#include "remoting/test/access_token_fetcher.h" namespace remoting { namespace test { diff --git a/remoting/test/fake_network_dispatcher.h b/remoting/test/fake_network_dispatcher.h index fcdfef5..7ecbee9 100644 --- a/remoting/test/fake_network_dispatcher.h +++ b/remoting/test/fake_network_dispatcher.h @@ -27,7 +27,7 @@ class FakeNetworkDispatcher public: class Node { public: - virtual ~Node() {}; + virtual ~Node() {} // Return thread on which ReceivePacket() should be called. virtual const scoped_refptr<base::SingleThreadTaskRunner>& GetThread() diff --git a/remoting/test/fake_network_manager.h b/remoting/test/fake_network_manager.h index 59a8029..01da153 100644 --- a/remoting/test/fake_network_manager.h +++ b/remoting/test/fake_network_manager.h @@ -15,7 +15,7 @@ namespace remoting { // specified in the constructor. class FakeNetworkManager : public rtc::NetworkManager { public: - FakeNetworkManager(const rtc::IPAddress& address); + explicit FakeNetworkManager(const rtc::IPAddress& address); ~FakeNetworkManager() override; // rtc::NetworkManager interface. diff --git a/remoting/test/fake_remote_host_info_fetcher.cc b/remoting/test/fake_remote_host_info_fetcher.cc new file mode 100644 index 0000000..8270984 --- /dev/null +++ b/remoting/test/fake_remote_host_info_fetcher.cc @@ -0,0 +1,35 @@ +// 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/fake_remote_host_info_fetcher.h" + +namespace remoting { +namespace test { + +FakeRemoteHostInfoFetcher::FakeRemoteHostInfoFetcher() : + fail_retrieve_remote_host_info_(false) {} + +FakeRemoteHostInfoFetcher::~FakeRemoteHostInfoFetcher() {} + +bool FakeRemoteHostInfoFetcher::RetrieveRemoteHostInfo( + const std::string& application_id, + const std::string& access_token, + ServiceEnvironment service_environment, + const RemoteHostInfoCallback& callback) { + RemoteHostInfo remote_host_info; + + if (fail_retrieve_remote_host_info_) { + remote_host_info.remote_host_status = kRemoteHostStatusPending; + } else { + remote_host_info.remote_host_status = kRemoteHostStatusReady; + remote_host_info.application_id = application_id; + } + + callback.Run(remote_host_info); + + return !fail_retrieve_remote_host_info_; +} + +} // namespace test +} // namespace remoting diff --git a/remoting/test/fake_remote_host_info_fetcher.h b/remoting/test/fake_remote_host_info_fetcher.h new file mode 100644 index 0000000..d82860f --- /dev/null +++ b/remoting/test/fake_remote_host_info_fetcher.h @@ -0,0 +1,44 @@ +// 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. + +#ifndef REMOTING_TEST_FAKE_REMOTE_HOST_INFO_FETCHER_H_ +#define REMOTING_TEST_FAKE_REMOTE_HOST_INFO_FETCHER_H_ + +#include <string> + +#include "remoting/test/remote_host_info_fetcher.h" + +namespace remoting { +namespace test { + +// Used for testing classes which rely on the RemoteHostInfoFetcher and want to +// simulate success and failure scenarios without using the actual class and +// network connection. +class FakeRemoteHostInfoFetcher : public RemoteHostInfoFetcher { + public: + FakeRemoteHostInfoFetcher(); + ~FakeRemoteHostInfoFetcher() override; + + // RemoteHostInfoFetcher interface. + bool RetrieveRemoteHostInfo( + const std::string& application_id, + const std::string& access_token, + ServiceEnvironment service_environment, + const RemoteHostInfoCallback& callback) override; + + void set_fail_retrieve_remote_host_info(bool fail) { + fail_retrieve_remote_host_info_ = fail; + } + + private: + // True if RetrieveRemoteHostInfo() should fail. + bool fail_retrieve_remote_host_info_; + + DISALLOW_COPY_AND_ASSIGN(FakeRemoteHostInfoFetcher); +}; + +} // namespace test +} // namespace remoting + +#endif // REMOTING_TEST_FAKE_REMOTE_HOST_INFO_FETCHER_H_ diff --git a/remoting/test/protocol_perftest.cc b/remoting/test/protocol_perftest.cc index d08b117..6401c46 100644 --- a/remoting/test/protocol_perftest.cc +++ b/remoting/test/protocol_perftest.cc @@ -365,6 +365,7 @@ class ProtocolPerfTest scoped_ptr<VideoPacket> last_video_packet_; + private: DISALLOW_COPY_AND_ASSIGN(ProtocolPerfTest); }; diff --git a/remoting/test/refresh_token_store.cc b/remoting/test/refresh_token_store.cc index 0f70ecdc..dfbf6dd 100644 --- a/remoting/test/refresh_token_store.cc +++ b/remoting/test/refresh_token_store.cc @@ -44,7 +44,7 @@ namespace test { // read it back during subsequent tool runs. class RefreshTokenStoreOnDisk : public RefreshTokenStore { public: - RefreshTokenStoreOnDisk(const std::string user_name); + explicit RefreshTokenStoreOnDisk(const std::string user_name); ~RefreshTokenStoreOnDisk() override; // RefreshTokenStore interface. diff --git a/remoting/test/remote_host_info.cc b/remoting/test/remote_host_info.cc new file mode 100644 index 0000000..0383745 --- /dev/null +++ b/remoting/test/remote_host_info.cc @@ -0,0 +1,34 @@ +// 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/remote_host_info.h" + +#include "base/logging.h" + +namespace remoting { +namespace test { + +RemoteHostInfo::RemoteHostInfo() : + remote_host_status(kRemoteHostStatusUnknown) {} + +RemoteHostInfo::~RemoteHostInfo() {} + +bool RemoteHostInfo::IsReadyForConnection() const { + return (remote_host_status == kRemoteHostStatusReady); +} + +void RemoteHostInfo::SetRemoteHostStatusFromString( + const std::string& status_string) { + if (status_string == "done") { + remote_host_status = kRemoteHostStatusReady; + } else if (status_string == "pending") { + remote_host_status = kRemoteHostStatusPending; + } else { + LOG(WARNING) << "Unknown status passed in: " << status_string; + remote_host_status = kRemoteHostStatusUnknown; + } +} + +} // namespace test +} // namespace remoting diff --git a/remoting/test/remote_host_info.h b/remoting/test/remote_host_info.h new file mode 100644 index 0000000..fe9aa5c --- /dev/null +++ b/remoting/test/remote_host_info.h @@ -0,0 +1,42 @@ +// 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. + +#ifndef REMOTING_TEST_REMOTE_HOST_INFO_H_ +#define REMOTING_TEST_REMOTE_HOST_INFO_H_ + +#include <string> + +namespace remoting { +namespace test { + +enum RemoteHostStatus { + kRemoteHostStatusReady, + kRemoteHostStatusPending, + kRemoteHostStatusUnknown +}; + +// Holds the information needed to establish a connection with a remote host. +struct RemoteHostInfo { + RemoteHostInfo(); + ~RemoteHostInfo(); + + // Returns true if the remote host is ready to accept connections. + bool IsReadyForConnection() const; + + // Sets the |remote_host_status| based on the caller supplied string. + void SetRemoteHostStatusFromString(const std::string& status_string); + + // Data used to establish a connection with a remote host. + RemoteHostStatus remote_host_status; + std::string application_id; + std::string host_id; + std::string host_jid; + std::string authorization_code; + std::string shared_secret; +}; + +} // namespace test +} // namespace remoting + +#endif // REMOTING_TEST_REMOTE_HOST_INFO_H_ diff --git a/remoting/test/remote_host_info_fetcher.cc b/remoting/test/remote_host_info_fetcher.cc new file mode 100644 index 0000000..e7dc095 --- /dev/null +++ b/remoting/test/remote_host_info_fetcher.cc @@ -0,0 +1,140 @@ +// 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/remote_host_info_fetcher.h" + +#include "base/bind.h" +#include "base/json/json_reader.h" +#include "base/json/json_writer.h" +#include "base/logging.h" +#include "base/message_loop/message_loop.h" +#include "base/strings/stringprintf.h" +#include "base/thread_task_runner_handle.h" +#include "base/values.h" +#include "net/http/http_response_headers.h" +#include "net/http/http_status_code.h" +#include "net/url_request/url_fetcher.h" +#include "remoting/base/url_request_context_getter.h" + +namespace { +const char kRequestTestOrigin[] = + "Origin: chrome-extension://ljacajndfccfgnfohlgkdphmbnpkjflk"; +} + +namespace remoting { +namespace test { + +RemoteHostInfoFetcher::RemoteHostInfoFetcher() {} + +RemoteHostInfoFetcher::~RemoteHostInfoFetcher() {} + +bool RemoteHostInfoFetcher::RetrieveRemoteHostInfo( + const std::string& application_id, + const std::string& access_token, + ServiceEnvironment service_environment, + const RemoteHostInfoCallback& callback) { + DCHECK(!application_id.empty()); + DCHECK(!access_token.empty()); + DCHECK(!callback.is_null()); + DCHECK(remote_host_info_callback_.is_null()); + + DVLOG(2) << "RemoteHostInfoFetcher::RetrieveRemoteHostInfo() called"; + + std::string service_url; + switch (service_environment) { + case kDeveloperEnvironment: + DVLOG(1) << "Configuring service request for dev environment"; + service_url = base::StringPrintf(kDevServiceEnvironmentUrlFormat, + application_id.c_str()); + break; + + case kTestingEnvironment: + DVLOG(1) << "Configuring service request for test environment"; + service_url = base::StringPrintf(kTestServiceEnvironmentUrlFormat, + application_id.c_str()); + break; + + default: + LOG(ERROR) << "Unrecognized service type: " << service_environment; + return false; + } + + remote_host_info_callback_ = callback; + + scoped_refptr<remoting::URLRequestContextGetter> request_context_getter; + request_context_getter = new remoting::URLRequestContextGetter( + base::ThreadTaskRunnerHandle::Get(), // network_runner + base::ThreadTaskRunnerHandle::Get()); // file_runner + + request_.reset( + net::URLFetcher::Create(GURL(service_url), net::URLFetcher::POST, this)); + request_->SetRequestContext(request_context_getter.get()); + request_->AddExtraRequestHeader("Authorization: OAuth " + access_token); + request_->AddExtraRequestHeader(kRequestTestOrigin); + request_->SetUploadData("application/json; charset=UTF-8", "{}"); + request_->Start(); + + return true; +} + +void RemoteHostInfoFetcher::OnURLFetchComplete(const net::URLFetcher* source) { + DCHECK(source); + DVLOG(2) << "URL Fetch Completed for: " << source->GetOriginalURL(); + + RemoteHostInfo remote_host_info; + int response_code = request_->GetResponseCode(); + if (response_code != net::HTTP_OK) { + LOG(ERROR) << "RemoteHostInfo request failed with error code: " + << response_code; + remote_host_info_callback_.Run(remote_host_info); + remote_host_info_callback_.Reset(); + return; + } + + std::string response_string; + if (!request_->GetResponseAsString(&response_string)) { + LOG(ERROR) << "Failed to retrieve RemoteHostInfo response data"; + remote_host_info_callback_.Run(remote_host_info); + remote_host_info_callback_.Reset(); + return; + } + + scoped_ptr<base::Value> response_value( + base::JSONReader::Read(response_string)); + if (!response_value || + !response_value->IsType(base::Value::TYPE_DICTIONARY)) { + LOG(ERROR) << "Failed to parse response string to JSON"; + remote_host_info_callback_.Run(remote_host_info); + remote_host_info_callback_.Reset(); + return; + } + + std::string remote_host_status; + const base::DictionaryValue* response; + if (response_value->GetAsDictionary(&response)) { + response->GetString("status", &remote_host_status); + } else { + LOG(ERROR) << "Failed to convert parsed JSON to a dictionary object"; + remote_host_info_callback_.Run(remote_host_info); + remote_host_info_callback_.Reset(); + return; + } + + remote_host_info.SetRemoteHostStatusFromString(remote_host_status); + + if (remote_host_info.IsReadyForConnection()) { + response->GetString("host.applicationId", &remote_host_info.application_id); + response->GetString("host.hostId", &remote_host_info.host_id); + response->GetString("hostJid", &remote_host_info.host_jid); + response->GetString("authorizationCode", + &remote_host_info.authorization_code); + response->GetString("sharedSecret", &remote_host_info.shared_secret); + } + + remote_host_info_callback_.Run(remote_host_info); + remote_host_info_callback_.Reset(); +} + +} // namespace test +} // namespace remoting diff --git a/remoting/test/remote_host_info_fetcher.h b/remoting/test/remote_host_info_fetcher.h new file mode 100644 index 0000000..a9fd742 --- /dev/null +++ b/remoting/test/remote_host_info_fetcher.h @@ -0,0 +1,83 @@ +// 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. + +#ifndef REMOTING_TEST_REMOTE_HOST_INFO_FETCHER_H_ +#define REMOTING_TEST_REMOTE_HOST_INFO_FETCHER_H_ + +#include <string> + +#include "base/callback.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "net/url_request/url_fetcher_delegate.h" +#include "remoting/test/remote_host_info.h" + +namespace net { +class UrlFetcher; +} +namespace remoting { +class URLRequestContextGetter; +} + +namespace remoting { +namespace test { + +// Used by the RemoteHostInfoFetcher to make HTTP requests and also by the +// unittests for this class to set fake response data for these URLs. +const char kDevServiceEnvironmentUrlFormat[] = + "https://www-googleapis-test.sandbox.google.com/appremoting/v1beta1_dev/" + "applications/%s/run"; +const char kTestServiceEnvironmentUrlFormat[] = + "https://www-googleapis-test.sandbox.google.com/appremoting/v1beta1/" + "applications/%s/run"; + +// Specifies the service API to call for app remoting host information. +// Note: When adding new environments, add them before kUnknownEnvironment as +// the last entry is used for bounds checking. +enum ServiceEnvironment { + kDeveloperEnvironment, + kTestingEnvironment, + kUnknownEnvironment +}; + +// Supplied by the client for each remote host info request and returns a valid, +// initialized RemoteHostInfo object on success. +typedef base::Callback<void(const RemoteHostInfo& remote_host_info)> + RemoteHostInfoCallback; + +// Calls the App Remoting service API to request connection info for a remote +// host. Destroying the RemoteHostInfoFetcher while a request is outstanding +// will cancel the request. It is safe to delete the fetcher from within a +// completion callback. Must be used from a thread running an IO message loop. +// The public method is virtual to allow for mocking and fakes. +class RemoteHostInfoFetcher : public net::URLFetcherDelegate { + public: + RemoteHostInfoFetcher(); + ~RemoteHostInfoFetcher() override; + + // Makes a service call to retrieve the details for a remote host. The + // callback will be called once the HTTP request has completed. + virtual bool RetrieveRemoteHostInfo( + const std::string& application_id, + const std::string& access_token, + ServiceEnvironment service_environment, + const RemoteHostInfoCallback& callback); + + private: + // net::URLFetcherDelegate interface. + void OnURLFetchComplete(const net::URLFetcher* source) override; + + // Holds the URLFetcher for the RemoteHostInfo request. + scoped_ptr<net::URLFetcher> request_; + + // Caller-supplied callback used to return remote host info on success. + RemoteHostInfoCallback remote_host_info_callback_; + + DISALLOW_COPY_AND_ASSIGN(RemoteHostInfoFetcher); +}; + +} // namespace test +} // namespace remoting + +#endif // REMOTING_TEST_REMOTE_HOST_INFO_FETCHER_H_ diff --git a/remoting/test/remote_host_info_fetcher_unittest.cc b/remoting/test/remote_host_info_fetcher_unittest.cc new file mode 100644 index 0000000..e04f2e3 --- /dev/null +++ b/remoting/test/remote_host_info_fetcher_unittest.cc @@ -0,0 +1,383 @@ +// 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/remote_host_info_fetcher.h" + +#include "base/bind.h" +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "base/strings/stringprintf.h" +#include "net/url_request/test_url_fetcher_factory.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { +const char kTestApplicationId[] = "klasdfjlkasdfjklasjfdkljsadf"; +const char kAccessTokenValue[] = "test_access_token_value"; +const char kRemoteHostInfoReadyResponse[] = + "{" + " \"status\": \"done\"," + " \"host\": {" + " \"kind\": \"test_kind\"," + " \"applicationId\": \"klasdfjlkasdfjklasjfdkljsadf\"," + " \"hostId\": \"test_host_id\"" + " }," + " \"hostJid\": \"test_host_jid\"," + " \"authorizationCode\": \"test_authorization_code\"," + " \"sharedSecret\": \"test_shared_secret\"" + "}"; +const char kRemoteHostInfoPendingResponse[] = + "{" + " \"status\": \"pending\"" + "}"; +const char kRemoteHostInfoEmptyResponse[] = "{}"; +} // namespace + +namespace remoting { +namespace test { + +// Provides base functionality for the RemoteHostInfoFetcher Tests below. The +// FakeURLFetcherFactory allows us to override the response data and payload for +// specified URLs. We use this to stub out network calls made by the +// RemoteHostInfoFetcher. This fixture also creates an IO MessageLoop, if +// necessary, for use by the RemoteHostInfoFetcher. +class RemoteHostInfoFetcherTest : public ::testing::Test { + public: + RemoteHostInfoFetcherTest() : + url_fetcher_factory_(nullptr) {} + ~RemoteHostInfoFetcherTest() override {} + + // Used as a RemoteHostInfoCallback for testing. + void OnRemoteHostInfoRetrieved( + base::Closure done_closure, + const RemoteHostInfo& retrieved_remote_host_info); + + protected: + // testing::Test interface. + void SetUp() override; + + // Sets the HTTP status and data returned for a specified URL. + void SetFakeResponse( + const GURL& url, + const std::string& data, + net::HttpStatusCode code, + net::URLRequestStatus::Status status); + + // Used for result verification. + RemoteHostInfo remote_host_info_; + + protected: + std::string dev_service_environment_url_; + std::string test_service_environment_url_; + + private: + net::FakeURLFetcherFactory url_fetcher_factory_; + scoped_ptr<base::MessageLoopForIO> message_loop_; + + DISALLOW_COPY_AND_ASSIGN(RemoteHostInfoFetcherTest); +}; + +void RemoteHostInfoFetcherTest::OnRemoteHostInfoRetrieved( + base::Closure done_closure, + const RemoteHostInfo& retrieved_remote_host_info) { + remote_host_info_ = retrieved_remote_host_info; + + done_closure.Run(); +} + +void RemoteHostInfoFetcherTest::SetUp() { + if (!base::MessageLoop::current()) { + // Create a temporary message loop if the current thread does not already + // have one so we can use its task runner to create a request object. + message_loop_.reset(new base::MessageLoopForIO); + } + + dev_service_environment_url_ = base::StringPrintf( + kDevServiceEnvironmentUrlFormat, + kTestApplicationId); + + test_service_environment_url_ = base::StringPrintf( + kTestServiceEnvironmentUrlFormat, + kTestApplicationId); +} + +void RemoteHostInfoFetcherTest::SetFakeResponse( + const GURL& url, + const std::string& data, + net::HttpStatusCode code, + net::URLRequestStatus::Status status) { + url_fetcher_factory_.SetFakeResponse(url, data, code, status); +} + +TEST_F(RemoteHostInfoFetcherTest, RetrieveRemoteHostInfoFromDev) { + SetFakeResponse( + GURL(dev_service_environment_url_), + kRemoteHostInfoReadyResponse, + net::HTTP_OK, + net::URLRequestStatus::SUCCESS); + + SetFakeResponse( + GURL(test_service_environment_url_), + kRemoteHostInfoEmptyResponse, + net::HTTP_NOT_FOUND, + net::URLRequestStatus::FAILED); + + base::RunLoop run_loop; + RemoteHostInfoCallback remote_host_info_callback = + base::Bind(&RemoteHostInfoFetcherTest::OnRemoteHostInfoRetrieved, + base::Unretained(this), + run_loop.QuitClosure()); + + RemoteHostInfoFetcher remote_host_info_fetcher; + bool request_started = remote_host_info_fetcher.RetrieveRemoteHostInfo( + kTestApplicationId, + kAccessTokenValue, + kDeveloperEnvironment, + remote_host_info_callback); + + run_loop.Run(); + + EXPECT_TRUE(request_started); + EXPECT_TRUE(remote_host_info_.IsReadyForConnection()); + EXPECT_EQ(remote_host_info_.application_id.compare(kTestApplicationId), 0); + EXPECT_TRUE(!remote_host_info_.host_id.empty()); + EXPECT_TRUE(!remote_host_info_.host_jid.empty()); + EXPECT_TRUE(!remote_host_info_.authorization_code.empty()); + EXPECT_TRUE(!remote_host_info_.shared_secret.empty()); +} + +TEST_F(RemoteHostInfoFetcherTest, RetrieveRemoteHostInfoFromTest) { + SetFakeResponse( + GURL(test_service_environment_url_), + kRemoteHostInfoReadyResponse, + net::HTTP_OK, + net::URLRequestStatus::SUCCESS); + + SetFakeResponse( + GURL(dev_service_environment_url_), + kRemoteHostInfoEmptyResponse, + net::HTTP_NOT_FOUND, + net::URLRequestStatus::FAILED); + + base::RunLoop run_loop; + RemoteHostInfoCallback remote_host_info_callback = + base::Bind(&RemoteHostInfoFetcherTest::OnRemoteHostInfoRetrieved, + base::Unretained(this), + run_loop.QuitClosure()); + + RemoteHostInfoFetcher remote_host_info_fetcher; + bool request_started = remote_host_info_fetcher.RetrieveRemoteHostInfo( + kTestApplicationId, + kAccessTokenValue, + kTestingEnvironment, + remote_host_info_callback); + + run_loop.Run(); + + EXPECT_TRUE(request_started); + EXPECT_TRUE(remote_host_info_.IsReadyForConnection()); + EXPECT_EQ(remote_host_info_.application_id.compare(kTestApplicationId), 0); + EXPECT_TRUE(!remote_host_info_.host_id.empty()); + EXPECT_TRUE(!remote_host_info_.host_jid.empty()); + EXPECT_TRUE(!remote_host_info_.authorization_code.empty()); + EXPECT_TRUE(!remote_host_info_.shared_secret.empty()); +} + +TEST_F(RemoteHostInfoFetcherTest, RetrieveRemoteHostInfoInvalidEnvironment) { + base::RunLoop run_loop; + RemoteHostInfoCallback remote_host_info_callback = + base::Bind(&RemoteHostInfoFetcherTest::OnRemoteHostInfoRetrieved, + base::Unretained(this), + run_loop.QuitClosure()); + + RemoteHostInfoFetcher remote_host_info_fetcher; + bool request_started = remote_host_info_fetcher.RetrieveRemoteHostInfo( + kTestApplicationId, + kAccessTokenValue, + kUnknownEnvironment, + remote_host_info_callback); + + EXPECT_FALSE(request_started); +} + +TEST_F(RemoteHostInfoFetcherTest, RetrieveRemoteHostInfoNetworkError) { + SetFakeResponse( + GURL(dev_service_environment_url_), + kRemoteHostInfoReadyResponse, + net::HTTP_NOT_FOUND, + net::URLRequestStatus::FAILED); + + base::RunLoop run_loop; + RemoteHostInfoCallback remote_host_info_callback = + base::Bind(&RemoteHostInfoFetcherTest::OnRemoteHostInfoRetrieved, + base::Unretained(this), + run_loop.QuitClosure()); + + RemoteHostInfoFetcher remote_host_info_fetcher; + bool request_started = remote_host_info_fetcher.RetrieveRemoteHostInfo( + kTestApplicationId, + kAccessTokenValue, + kDeveloperEnvironment, + remote_host_info_callback); + + run_loop.Run(); + + EXPECT_TRUE(request_started); + EXPECT_FALSE(remote_host_info_.IsReadyForConnection()); + + // If there was a network error retrieving the remote host info, then none of + // the connection details should be populated. + EXPECT_TRUE(remote_host_info_.application_id.empty()); + EXPECT_TRUE(remote_host_info_.host_id.empty()); + EXPECT_TRUE(remote_host_info_.host_jid.empty()); + EXPECT_TRUE(remote_host_info_.authorization_code.empty()); + EXPECT_TRUE(remote_host_info_.shared_secret.empty()); +} + +TEST_F(RemoteHostInfoFetcherTest, RetrieveRemoteHostInfoPendingResponse) { + SetFakeResponse( + GURL(dev_service_environment_url_), + kRemoteHostInfoPendingResponse, + net::HTTP_OK, + net::URLRequestStatus::SUCCESS); + + base::RunLoop run_loop; + RemoteHostInfoCallback remote_host_info_callback = + base::Bind(&RemoteHostInfoFetcherTest::OnRemoteHostInfoRetrieved, + base::Unretained(this), + run_loop.QuitClosure()); + + RemoteHostInfoFetcher remote_host_info_fetcher; + bool request_started = remote_host_info_fetcher.RetrieveRemoteHostInfo( + kTestApplicationId, + kAccessTokenValue, + kDeveloperEnvironment, + remote_host_info_callback); + + run_loop.Run(); + + EXPECT_TRUE(request_started); + EXPECT_FALSE(remote_host_info_.IsReadyForConnection()); + + // If the remote host request is pending, then none of the connection details + // should be populated. + EXPECT_TRUE(remote_host_info_.application_id.empty()); + EXPECT_TRUE(remote_host_info_.host_id.empty()); + EXPECT_TRUE(remote_host_info_.host_jid.empty()); + EXPECT_TRUE(remote_host_info_.authorization_code.empty()); + EXPECT_TRUE(remote_host_info_.shared_secret.empty()); +} + +TEST_F(RemoteHostInfoFetcherTest, RetrieveRemoteHostInfoEmptyResponse) { + SetFakeResponse( + GURL(dev_service_environment_url_), + kRemoteHostInfoEmptyResponse, + net::HTTP_OK, + net::URLRequestStatus::SUCCESS); + + base::RunLoop run_loop; + RemoteHostInfoCallback remote_host_info_callback = + base::Bind(&RemoteHostInfoFetcherTest::OnRemoteHostInfoRetrieved, + base::Unretained(this), + run_loop.QuitClosure()); + + RemoteHostInfoFetcher remote_host_info_fetcher; + bool request_started = remote_host_info_fetcher.RetrieveRemoteHostInfo( + kTestApplicationId, + kAccessTokenValue, + kDeveloperEnvironment, + remote_host_info_callback); + + run_loop.Run(); + + EXPECT_TRUE(request_started); + EXPECT_FALSE(remote_host_info_.IsReadyForConnection()); + + // If we received an empty response, then none of the connection details + // should be populated. + EXPECT_TRUE(remote_host_info_.application_id.empty()); + EXPECT_TRUE(remote_host_info_.host_id.empty()); + EXPECT_TRUE(remote_host_info_.host_jid.empty()); + EXPECT_TRUE(remote_host_info_.authorization_code.empty()); + EXPECT_TRUE(remote_host_info_.shared_secret.empty()); +} + +TEST_F(RemoteHostInfoFetcherTest, MultipleRetrieveRemoteHostInfoRequests) { + // First, we will fetch info from the development service environment. + SetFakeResponse( + GURL(dev_service_environment_url_), + kRemoteHostInfoReadyResponse, + net::HTTP_OK, + net::URLRequestStatus::SUCCESS); + + SetFakeResponse( + GURL(test_service_environment_url_), + kRemoteHostInfoEmptyResponse, + net::HTTP_NOT_FOUND, + net::URLRequestStatus::FAILED); + + base::RunLoop dev_run_loop; + RemoteHostInfoCallback dev_remote_host_info_callback = + base::Bind(&RemoteHostInfoFetcherTest::OnRemoteHostInfoRetrieved, + base::Unretained(this), + dev_run_loop.QuitClosure()); + + RemoteHostInfoFetcher remote_host_info_fetcher; + bool dev_request_started = remote_host_info_fetcher.RetrieveRemoteHostInfo( + kTestApplicationId, + kAccessTokenValue, + kDeveloperEnvironment, + dev_remote_host_info_callback); + + dev_run_loop.Run(); + + EXPECT_TRUE(dev_request_started); + EXPECT_TRUE(remote_host_info_.IsReadyForConnection()); + EXPECT_EQ(remote_host_info_.application_id.compare(kTestApplicationId), 0); + EXPECT_TRUE(!remote_host_info_.host_id.empty()); + EXPECT_TRUE(!remote_host_info_.host_jid.empty()); + EXPECT_TRUE(!remote_host_info_.authorization_code.empty()); + EXPECT_TRUE(!remote_host_info_.shared_secret.empty()); + + // Next, we will fetch info from the test service environment. + SetFakeResponse( + GURL(test_service_environment_url_), + kRemoteHostInfoReadyResponse, + net::HTTP_OK, + net::URLRequestStatus::SUCCESS); + + SetFakeResponse( + GURL(dev_service_environment_url_), + kRemoteHostInfoEmptyResponse, + net::HTTP_NOT_FOUND, + net::URLRequestStatus::FAILED); + + base::RunLoop test_run_loop; + RemoteHostInfoCallback test_remote_host_info_callback = + base::Bind(&RemoteHostInfoFetcherTest::OnRemoteHostInfoRetrieved, + base::Unretained(this), + test_run_loop.QuitClosure()); + + // Reset the state of our internal |remote_host_info_| object. + remote_host_info_ = RemoteHostInfo(); + EXPECT_FALSE(remote_host_info_.IsReadyForConnection()); + + bool test_request_started = remote_host_info_fetcher.RetrieveRemoteHostInfo( + kTestApplicationId, + kAccessTokenValue, + kTestingEnvironment, + test_remote_host_info_callback); + + test_run_loop.Run(); + + EXPECT_TRUE(test_request_started); + EXPECT_TRUE(remote_host_info_.IsReadyForConnection()); + EXPECT_EQ(remote_host_info_.application_id.compare(kTestApplicationId), 0); + EXPECT_TRUE(!remote_host_info_.host_id.empty()); + EXPECT_TRUE(!remote_host_info_.host_jid.empty()); + EXPECT_TRUE(!remote_host_info_.authorization_code.empty()); + EXPECT_TRUE(!remote_host_info_.shared_secret.empty()); +} + +} // namespace test +} // namespace remoting |