1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "google_apis/gaia/oauth2_token_service_request.h" 6 7 #include <set> 8 #include <string> 9 #include <vector> 10 #include "base/threading/thread.h" 11 #include "google_apis/gaia/fake_oauth2_token_service.h" 12 #include "google_apis/gaia/google_service_auth_error.h" 13 #include "google_apis/gaia/oauth2_token_service.h" 14 #include "testing/gtest/include/gtest/gtest.h" 15 16 namespace { 17 18 const char kAccessToken[] = "access_token"; 19 const char kAccountId[] = "test_user (at) gmail.com"; 20 const char kScope[] = "SCOPE"; 21 22 class TestingOAuth2TokenServiceConsumer : public OAuth2TokenService::Consumer { 23 public: 24 TestingOAuth2TokenServiceConsumer(); 25 virtual ~TestingOAuth2TokenServiceConsumer(); 26 27 virtual void OnGetTokenSuccess(const OAuth2TokenService::Request* request, 28 const std::string& access_token, 29 const base::Time& expiration_time) OVERRIDE; 30 virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request, 31 const GoogleServiceAuthError& error) OVERRIDE; 32 33 int num_get_token_success_; 34 int num_get_token_failure_; 35 std::string last_token_; 36 GoogleServiceAuthError last_error_; 37 }; 38 39 TestingOAuth2TokenServiceConsumer::TestingOAuth2TokenServiceConsumer() 40 : OAuth2TokenService::Consumer("test"), 41 num_get_token_success_(0), 42 num_get_token_failure_(0), 43 last_error_(GoogleServiceAuthError::AuthErrorNone()) { 44 } 45 46 TestingOAuth2TokenServiceConsumer::~TestingOAuth2TokenServiceConsumer() { 47 } 48 49 void TestingOAuth2TokenServiceConsumer::OnGetTokenSuccess( 50 const OAuth2TokenService::Request* request, 51 const std::string& token, 52 const base::Time& expiration_date) { 53 last_token_ = token; 54 ++num_get_token_success_; 55 } 56 57 void TestingOAuth2TokenServiceConsumer::OnGetTokenFailure( 58 const OAuth2TokenService::Request* request, 59 const GoogleServiceAuthError& error) { 60 last_error_ = error; 61 ++num_get_token_failure_; 62 } 63 64 // A mock implementation of an OAuth2TokenService. 65 // 66 // Use SetResponse to vary the response to token requests. 67 class MockOAuth2TokenService : public FakeOAuth2TokenService { 68 public: 69 MockOAuth2TokenService(); 70 virtual ~MockOAuth2TokenService(); 71 72 void SetResponse(const GoogleServiceAuthError& error, 73 const std::string& access_token, 74 const base::Time& expiration); 75 76 int num_invalidate_token() const { return num_invalidate_token_; } 77 78 const std::string& last_token_invalidated() const { 79 return last_token_invalidated_; 80 } 81 82 protected: 83 virtual void FetchOAuth2Token(RequestImpl* request, 84 const std::string& account_id, 85 net::URLRequestContextGetter* getter, 86 const std::string& client_id, 87 const std::string& client_secret, 88 const ScopeSet& scopes) OVERRIDE; 89 90 virtual void InvalidateOAuth2Token(const std::string& account_id, 91 const std::string& client_id, 92 const ScopeSet& scopes, 93 const std::string& access_token) OVERRIDE; 94 95 private: 96 GoogleServiceAuthError response_error_; 97 std::string response_access_token_; 98 base::Time response_expiration_; 99 int num_invalidate_token_; 100 std::string last_token_invalidated_; 101 }; 102 103 MockOAuth2TokenService::MockOAuth2TokenService() 104 : response_error_(GoogleServiceAuthError::AuthErrorNone()), 105 response_access_token_(kAccessToken), 106 response_expiration_(base::Time::Max()), 107 num_invalidate_token_(0) { 108 } 109 110 MockOAuth2TokenService::~MockOAuth2TokenService() { 111 } 112 113 void MockOAuth2TokenService::SetResponse(const GoogleServiceAuthError& error, 114 const std::string& access_token, 115 const base::Time& expiration) { 116 response_error_ = error; 117 response_access_token_ = access_token; 118 response_expiration_ = expiration; 119 } 120 121 void MockOAuth2TokenService::FetchOAuth2Token( 122 RequestImpl* request, 123 const std::string& account_id, 124 net::URLRequestContextGetter* getter, 125 const std::string& client_id, 126 const std::string& client_secret, 127 const ScopeSet& scopes) { 128 base::MessageLoop::current()->PostTask( 129 FROM_HERE, 130 base::Bind(&OAuth2TokenService::RequestImpl::InformConsumer, 131 request->AsWeakPtr(), 132 response_error_, 133 response_access_token_, 134 response_expiration_)); 135 } 136 137 void MockOAuth2TokenService::InvalidateOAuth2Token( 138 const std::string& account_id, 139 const std::string& client_id, 140 const ScopeSet& scopes, 141 const std::string& access_token) { 142 ++num_invalidate_token_; 143 last_token_invalidated_ = access_token; 144 } 145 146 class OAuth2TokenServiceRequestTest : public testing::Test { 147 public: 148 virtual void SetUp() OVERRIDE; 149 virtual void TearDown() OVERRIDE; 150 151 protected: 152 class Provider : public OAuth2TokenServiceRequest::TokenServiceProvider { 153 public: 154 Provider(const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, 155 OAuth2TokenService* token_service); 156 157 virtual scoped_refptr<base::SingleThreadTaskRunner> 158 GetTokenServiceTaskRunner() OVERRIDE; 159 virtual OAuth2TokenService* GetTokenService() OVERRIDE; 160 161 private: 162 virtual ~Provider(); 163 164 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; 165 OAuth2TokenService* token_service_; 166 }; 167 168 base::MessageLoop ui_loop_; 169 OAuth2TokenService::ScopeSet scopes_; 170 scoped_ptr<MockOAuth2TokenService> oauth2_service_; 171 scoped_refptr<OAuth2TokenServiceRequest::TokenServiceProvider> provider_; 172 TestingOAuth2TokenServiceConsumer consumer_; 173 }; 174 175 void OAuth2TokenServiceRequestTest::SetUp() { 176 scopes_.insert(kScope); 177 oauth2_service_.reset(new MockOAuth2TokenService); 178 oauth2_service_->AddAccount(kAccountId); 179 provider_ = 180 new Provider(base::MessageLoopProxy::current(), oauth2_service_.get()); 181 } 182 183 void OAuth2TokenServiceRequestTest::TearDown() { 184 // Run the loop to execute any pending tasks that may free resources. 185 ui_loop_.RunUntilIdle(); 186 } 187 188 OAuth2TokenServiceRequestTest::Provider::Provider( 189 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, 190 OAuth2TokenService* token_service) 191 : task_runner_(task_runner), token_service_(token_service) { 192 } 193 194 scoped_refptr<base::SingleThreadTaskRunner> 195 OAuth2TokenServiceRequestTest::Provider::GetTokenServiceTaskRunner() { 196 return task_runner_; 197 } 198 199 OAuth2TokenService* OAuth2TokenServiceRequestTest::Provider::GetTokenService() { 200 return token_service_; 201 } 202 203 OAuth2TokenServiceRequestTest::Provider::~Provider() { 204 } 205 206 TEST_F(OAuth2TokenServiceRequestTest, CreateAndStart_Failure) { 207 oauth2_service_->SetResponse( 208 GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE), 209 std::string(), 210 base::Time()); 211 scoped_ptr<OAuth2TokenServiceRequest> request( 212 OAuth2TokenServiceRequest::CreateAndStart( 213 provider_.get(), kAccountId, scopes_, &consumer_)); 214 ui_loop_.RunUntilIdle(); 215 EXPECT_EQ(0, consumer_.num_get_token_success_); 216 EXPECT_EQ(1, consumer_.num_get_token_failure_); 217 EXPECT_EQ(GoogleServiceAuthError::SERVICE_UNAVAILABLE, 218 consumer_.last_error_.state()); 219 EXPECT_EQ(0, oauth2_service_->num_invalidate_token()); 220 } 221 222 TEST_F(OAuth2TokenServiceRequestTest, CreateAndStart_Success) { 223 scoped_ptr<OAuth2TokenServiceRequest> request( 224 OAuth2TokenServiceRequest::CreateAndStart( 225 provider_.get(), kAccountId, scopes_, &consumer_)); 226 ui_loop_.RunUntilIdle(); 227 EXPECT_EQ(1, consumer_.num_get_token_success_); 228 EXPECT_EQ(0, consumer_.num_get_token_failure_); 229 EXPECT_EQ(kAccessToken, consumer_.last_token_); 230 EXPECT_EQ(0, oauth2_service_->num_invalidate_token()); 231 } 232 233 TEST_F(OAuth2TokenServiceRequestTest, 234 CreateAndStart_DestroyRequestBeforeCompletes) { 235 scoped_ptr<OAuth2TokenServiceRequest> request( 236 OAuth2TokenServiceRequest::CreateAndStart( 237 provider_.get(), kAccountId, scopes_, &consumer_)); 238 request.reset(); 239 ui_loop_.RunUntilIdle(); 240 EXPECT_EQ(0, consumer_.num_get_token_success_); 241 EXPECT_EQ(0, consumer_.num_get_token_failure_); 242 EXPECT_EQ(0, oauth2_service_->num_invalidate_token()); 243 } 244 245 TEST_F(OAuth2TokenServiceRequestTest, 246 CreateAndStart_DestroyRequestAfterCompletes) { 247 scoped_ptr<OAuth2TokenServiceRequest> request( 248 OAuth2TokenServiceRequest::CreateAndStart( 249 provider_.get(), kAccountId, scopes_, &consumer_)); 250 ui_loop_.RunUntilIdle(); 251 request.reset(); 252 EXPECT_EQ(1, consumer_.num_get_token_success_); 253 EXPECT_EQ(0, consumer_.num_get_token_failure_); 254 EXPECT_EQ(kAccessToken, consumer_.last_token_); 255 EXPECT_EQ(0, oauth2_service_->num_invalidate_token()); 256 } 257 258 TEST_F(OAuth2TokenServiceRequestTest, InvalidateToken) { 259 OAuth2TokenServiceRequest::InvalidateToken( 260 provider_.get(), kAccountId, scopes_, kAccessToken); 261 ui_loop_.RunUntilIdle(); 262 EXPECT_EQ(0, consumer_.num_get_token_success_); 263 EXPECT_EQ(0, consumer_.num_get_token_failure_); 264 EXPECT_EQ(kAccessToken, oauth2_service_->last_token_invalidated()); 265 EXPECT_EQ(1, oauth2_service_->num_invalidate_token()); 266 } 267 268 } // namespace 269