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 // A complete set of unit tests for OAuth2AccessTokenFetcherImpl. 6 7 #include <string> 8 9 #include "base/memory/scoped_ptr.h" 10 #include "base/run_loop.h" 11 #include "google_apis/gaia/gaia_urls.h" 12 #include "google_apis/gaia/google_service_auth_error.h" 13 #include "google_apis/gaia/oauth2_access_token_consumer.h" 14 #include "google_apis/gaia/oauth2_access_token_fetcher_impl.h" 15 #include "net/http/http_status_code.h" 16 #include "net/url_request/test_url_fetcher_factory.h" 17 #include "net/url_request/url_fetcher.h" 18 #include "net/url_request/url_fetcher_delegate.h" 19 #include "net/url_request/url_fetcher_factory.h" 20 #include "net/url_request/url_request.h" 21 #include "net/url_request/url_request_status.h" 22 #include "net/url_request/url_request_test_util.h" 23 #include "testing/gmock/include/gmock/gmock.h" 24 #include "testing/gtest/include/gtest/gtest.h" 25 #include "url/gurl.h" 26 27 using net::ResponseCookies; 28 using net::ScopedURLFetcherFactory; 29 using net::TestURLFetcher; 30 using net::URLFetcher; 31 using net::URLFetcherDelegate; 32 using net::URLFetcherFactory; 33 using net::URLRequestStatus; 34 using testing::_; 35 using testing::Return; 36 37 namespace { 38 39 typedef std::vector<std::string> ScopeList; 40 41 static const char kValidTokenResponse[] = 42 "{" 43 " \"access_token\": \"at1\"," 44 " \"expires_in\": 3600," 45 " \"token_type\": \"Bearer\"" 46 "}"; 47 static const char kTokenResponseNoAccessToken[] = 48 "{" 49 " \"expires_in\": 3600," 50 " \"token_type\": \"Bearer\"" 51 "}"; 52 53 static const char kValidFailureTokenResponse[] = 54 "{" 55 " \"error\": \"invalid_grant\"" 56 "}"; 57 58 class MockUrlFetcherFactory : public ScopedURLFetcherFactory, 59 public URLFetcherFactory { 60 public: 61 MockUrlFetcherFactory() : ScopedURLFetcherFactory(this) {} 62 virtual ~MockUrlFetcherFactory() {} 63 64 MOCK_METHOD4(CreateURLFetcher, 65 URLFetcher*(int id, 66 const GURL& url, 67 URLFetcher::RequestType request_type, 68 URLFetcherDelegate* d)); 69 }; 70 71 class MockOAuth2AccessTokenConsumer : public OAuth2AccessTokenConsumer { 72 public: 73 MockOAuth2AccessTokenConsumer() {} 74 ~MockOAuth2AccessTokenConsumer() {} 75 76 MOCK_METHOD2(OnGetTokenSuccess, 77 void(const std::string& access_token, 78 const base::Time& expiration_time)); 79 MOCK_METHOD1(OnGetTokenFailure, void(const GoogleServiceAuthError& error)); 80 }; 81 82 } // namespace 83 84 class OAuth2AccessTokenFetcherImplTest : public testing::Test { 85 public: 86 OAuth2AccessTokenFetcherImplTest() 87 : request_context_getter_(new net::TestURLRequestContextGetter( 88 base::MessageLoopProxy::current())), 89 fetcher_(&consumer_, request_context_getter_, "refresh_token") { 90 base::RunLoop().RunUntilIdle(); 91 } 92 93 virtual ~OAuth2AccessTokenFetcherImplTest() {} 94 95 virtual TestURLFetcher* SetupGetAccessToken(bool fetch_succeeds, 96 int response_code, 97 const std::string& body) { 98 GURL url(GaiaUrls::GetInstance()->oauth2_token_url()); 99 TestURLFetcher* url_fetcher = new TestURLFetcher(0, url, &fetcher_); 100 URLRequestStatus::Status status = 101 fetch_succeeds ? URLRequestStatus::SUCCESS : URLRequestStatus::FAILED; 102 url_fetcher->set_status(URLRequestStatus(status, 0)); 103 104 if (response_code != 0) 105 url_fetcher->set_response_code(response_code); 106 107 if (!body.empty()) 108 url_fetcher->SetResponseString(body); 109 110 EXPECT_CALL(factory_, CreateURLFetcher(_, url, _, _)) 111 .WillOnce(Return(url_fetcher)); 112 return url_fetcher; 113 } 114 115 protected: 116 base::MessageLoop message_loop_; 117 MockUrlFetcherFactory factory_; 118 MockOAuth2AccessTokenConsumer consumer_; 119 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_; 120 OAuth2AccessTokenFetcherImpl fetcher_; 121 }; 122 123 // These four tests time out, see http://crbug.com/113446. 124 TEST_F(OAuth2AccessTokenFetcherImplTest, 125 DISABLED_GetAccessTokenRequestFailure) { 126 TestURLFetcher* url_fetcher = SetupGetAccessToken(false, 0, std::string()); 127 EXPECT_CALL(consumer_, OnGetTokenFailure(_)).Times(1); 128 fetcher_.Start("client_id", "client_secret", ScopeList()); 129 fetcher_.OnURLFetchComplete(url_fetcher); 130 } 131 132 TEST_F(OAuth2AccessTokenFetcherImplTest, 133 DISABLED_GetAccessTokenResponseCodeFailure) { 134 TestURLFetcher* url_fetcher = 135 SetupGetAccessToken(true, net::HTTP_FORBIDDEN, std::string()); 136 EXPECT_CALL(consumer_, OnGetTokenFailure(_)).Times(1); 137 fetcher_.Start("client_id", "client_secret", ScopeList()); 138 fetcher_.OnURLFetchComplete(url_fetcher); 139 } 140 141 TEST_F(OAuth2AccessTokenFetcherImplTest, DISABLED_Success) { 142 TestURLFetcher* url_fetcher = 143 SetupGetAccessToken(true, net::HTTP_OK, kValidTokenResponse); 144 EXPECT_CALL(consumer_, OnGetTokenSuccess("at1", _)).Times(1); 145 fetcher_.Start("client_id", "client_secret", ScopeList()); 146 fetcher_.OnURLFetchComplete(url_fetcher); 147 } 148 149 TEST_F(OAuth2AccessTokenFetcherImplTest, DISABLED_MakeGetAccessTokenBody) { 150 { // No scope. 151 std::string body = 152 "client_id=cid1&" 153 "client_secret=cs1&" 154 "grant_type=refresh_token&" 155 "refresh_token=rt1"; 156 EXPECT_EQ(body, 157 OAuth2AccessTokenFetcherImpl::MakeGetAccessTokenBody( 158 "cid1", "cs1", "rt1", ScopeList())); 159 } 160 161 { // One scope. 162 std::string body = 163 "client_id=cid1&" 164 "client_secret=cs1&" 165 "grant_type=refresh_token&" 166 "refresh_token=rt1&" 167 "scope=https://www.googleapis.com/foo"; 168 ScopeList scopes; 169 scopes.push_back("https://www.googleapis.com/foo"); 170 EXPECT_EQ(body, 171 OAuth2AccessTokenFetcherImpl::MakeGetAccessTokenBody( 172 "cid1", "cs1", "rt1", scopes)); 173 } 174 175 { // Multiple scopes. 176 std::string body = 177 "client_id=cid1&" 178 "client_secret=cs1&" 179 "grant_type=refresh_token&" 180 "refresh_token=rt1&" 181 "scope=https://www.googleapis.com/foo+" 182 "https://www.googleapis.com/bar+" 183 "https://www.googleapis.com/baz"; 184 ScopeList scopes; 185 scopes.push_back("https://www.googleapis.com/foo"); 186 scopes.push_back("https://www.googleapis.com/bar"); 187 scopes.push_back("https://www.googleapis.com/baz"); 188 EXPECT_EQ(body, 189 OAuth2AccessTokenFetcherImpl::MakeGetAccessTokenBody( 190 "cid1", "cs1", "rt1", scopes)); 191 } 192 } 193 194 // http://crbug.com/114215 195 #if defined(OS_WIN) 196 #define MAYBE_ParseGetAccessTokenResponse DISABLED_ParseGetAccessTokenResponse 197 #else 198 #define MAYBE_ParseGetAccessTokenResponse ParseGetAccessTokenResponse 199 #endif // defined(OS_WIN) 200 TEST_F(OAuth2AccessTokenFetcherImplTest, MAYBE_ParseGetAccessTokenResponse) { 201 { // No body. 202 TestURLFetcher url_fetcher(0, GURL("www.google.com"), NULL); 203 204 std::string at; 205 int expires_in; 206 EXPECT_FALSE( 207 OAuth2AccessTokenFetcherImpl::ParseGetAccessTokenSuccessResponse( 208 &url_fetcher, &at, &expires_in)); 209 EXPECT_TRUE(at.empty()); 210 } 211 { // Bad json. 212 TestURLFetcher url_fetcher(0, GURL("www.google.com"), NULL); 213 url_fetcher.SetResponseString("foo"); 214 215 std::string at; 216 int expires_in; 217 EXPECT_FALSE( 218 OAuth2AccessTokenFetcherImpl::ParseGetAccessTokenSuccessResponse( 219 &url_fetcher, &at, &expires_in)); 220 EXPECT_TRUE(at.empty()); 221 } 222 { // Valid json: access token missing. 223 TestURLFetcher url_fetcher(0, GURL("www.google.com"), NULL); 224 url_fetcher.SetResponseString(kTokenResponseNoAccessToken); 225 226 std::string at; 227 int expires_in; 228 EXPECT_FALSE( 229 OAuth2AccessTokenFetcherImpl::ParseGetAccessTokenSuccessResponse( 230 &url_fetcher, &at, &expires_in)); 231 EXPECT_TRUE(at.empty()); 232 } 233 { // Valid json: all good. 234 TestURLFetcher url_fetcher(0, GURL("www.google.com"), NULL); 235 url_fetcher.SetResponseString(kValidTokenResponse); 236 237 std::string at; 238 int expires_in; 239 EXPECT_TRUE( 240 OAuth2AccessTokenFetcherImpl::ParseGetAccessTokenSuccessResponse( 241 &url_fetcher, &at, &expires_in)); 242 EXPECT_EQ("at1", at); 243 EXPECT_EQ(3600, expires_in); 244 } 245 { // Valid json: invalid error response. 246 TestURLFetcher url_fetcher(0, GURL("www.google.com"), NULL); 247 url_fetcher.SetResponseString(kTokenResponseNoAccessToken); 248 249 std::string error; 250 EXPECT_FALSE( 251 OAuth2AccessTokenFetcherImpl::ParseGetAccessTokenFailureResponse( 252 &url_fetcher, &error)); 253 EXPECT_TRUE(error.empty()); 254 } 255 { // Valid json: error response. 256 TestURLFetcher url_fetcher(0, GURL("www.google.com"), NULL); 257 url_fetcher.SetResponseString(kValidFailureTokenResponse); 258 259 std::string error; 260 EXPECT_TRUE( 261 OAuth2AccessTokenFetcherImpl::ParseGetAccessTokenFailureResponse( 262 &url_fetcher, &error)); 263 EXPECT_EQ("invalid_grant", error); 264 } 265 } 266