1 // Copyright (c) 2012 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 OAuth2AccessTokenFetcher. 6 7 #include <string> 8 9 #include "base/memory/scoped_ptr.h" 10 #include "content/public/test/test_browser_thread_bundle.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.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 class MockUrlFetcherFactory : public ScopedURLFetcherFactory, 54 public URLFetcherFactory { 55 public: 56 MockUrlFetcherFactory() 57 : ScopedURLFetcherFactory(this) { 58 } 59 virtual ~MockUrlFetcherFactory() {} 60 61 MOCK_METHOD4( 62 CreateURLFetcher, 63 URLFetcher* (int id, 64 const GURL& url, 65 URLFetcher::RequestType request_type, 66 URLFetcherDelegate* d)); 67 }; 68 69 class MockOAuth2AccessTokenConsumer : public OAuth2AccessTokenConsumer { 70 public: 71 MockOAuth2AccessTokenConsumer() {} 72 ~MockOAuth2AccessTokenConsumer() {} 73 74 MOCK_METHOD2(OnGetTokenSuccess, void(const std::string& access_token, 75 const base::Time& expiration_time)); 76 MOCK_METHOD1(OnGetTokenFailure, 77 void(const GoogleServiceAuthError& error)); 78 }; 79 80 } // namespace 81 82 class OAuth2AccessTokenFetcherTest : public testing::Test { 83 public: 84 OAuth2AccessTokenFetcherTest() 85 : request_context_getter_(new net::TestURLRequestContextGetter( 86 base::MessageLoopProxy::current())), 87 fetcher_(&consumer_, request_context_getter_) { 88 } 89 90 virtual ~OAuth2AccessTokenFetcherTest() {} 91 92 virtual TestURLFetcher* SetupGetAccessToken( 93 bool fetch_succeeds, int response_code, const std::string& body) { 94 GURL url(GaiaUrls::GetInstance()->oauth2_token_url()); 95 TestURLFetcher* url_fetcher = new TestURLFetcher(0, url, &fetcher_); 96 URLRequestStatus::Status status = 97 fetch_succeeds ? URLRequestStatus::SUCCESS : URLRequestStatus::FAILED; 98 url_fetcher->set_status(URLRequestStatus(status, 0)); 99 100 if (response_code != 0) 101 url_fetcher->set_response_code(response_code); 102 103 if (!body.empty()) 104 url_fetcher->SetResponseString(body); 105 106 EXPECT_CALL(factory_, CreateURLFetcher(_, url, _, _)) 107 .WillOnce(Return(url_fetcher)); 108 return url_fetcher; 109 } 110 111 protected: 112 content::TestBrowserThreadBundle thread_bundle_; 113 MockUrlFetcherFactory factory_; 114 MockOAuth2AccessTokenConsumer consumer_; 115 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_; 116 OAuth2AccessTokenFetcher fetcher_; 117 }; 118 119 // These four tests time out, see http://crbug.com/113446. 120 TEST_F(OAuth2AccessTokenFetcherTest, DISABLED_GetAccessTokenRequestFailure) { 121 TestURLFetcher* url_fetcher = SetupGetAccessToken(false, 0, std::string()); 122 EXPECT_CALL(consumer_, OnGetTokenFailure(_)).Times(1); 123 fetcher_.Start("client_id", "client_secret", "refresh_token", ScopeList()); 124 fetcher_.OnURLFetchComplete(url_fetcher); 125 } 126 127 TEST_F(OAuth2AccessTokenFetcherTest, 128 DISABLED_GetAccessTokenResponseCodeFailure) { 129 TestURLFetcher* url_fetcher = 130 SetupGetAccessToken(true, net::HTTP_FORBIDDEN, std::string()); 131 EXPECT_CALL(consumer_, OnGetTokenFailure(_)).Times(1); 132 fetcher_.Start("client_id", "client_secret", "refresh_token", ScopeList()); 133 fetcher_.OnURLFetchComplete(url_fetcher); 134 } 135 136 TEST_F(OAuth2AccessTokenFetcherTest, DISABLED_Success) { 137 TestURLFetcher* url_fetcher = SetupGetAccessToken( 138 true, net::HTTP_OK, kValidTokenResponse); 139 EXPECT_CALL(consumer_, OnGetTokenSuccess("at1", _)).Times(1); 140 fetcher_.Start("client_id", "client_secret", "refresh_token", ScopeList()); 141 fetcher_.OnURLFetchComplete(url_fetcher); 142 } 143 144 TEST_F(OAuth2AccessTokenFetcherTest, DISABLED_MakeGetAccessTokenBody) { 145 { // No scope. 146 std::string body = 147 "client_id=cid1&" 148 "client_secret=cs1&" 149 "grant_type=refresh_token&" 150 "refresh_token=rt1"; 151 EXPECT_EQ(body, OAuth2AccessTokenFetcher::MakeGetAccessTokenBody( 152 "cid1", "cs1", "rt1", ScopeList())); 153 } 154 155 { // One scope. 156 std::string body = 157 "client_id=cid1&" 158 "client_secret=cs1&" 159 "grant_type=refresh_token&" 160 "refresh_token=rt1&" 161 "scope=https://www.googleapis.com/foo"; 162 ScopeList scopes; 163 scopes.push_back("https://www.googleapis.com/foo"); 164 EXPECT_EQ(body, OAuth2AccessTokenFetcher::MakeGetAccessTokenBody( 165 "cid1", "cs1", "rt1", scopes)); 166 } 167 168 { // Multiple scopes. 169 std::string body = 170 "client_id=cid1&" 171 "client_secret=cs1&" 172 "grant_type=refresh_token&" 173 "refresh_token=rt1&" 174 "scope=https://www.googleapis.com/foo+" 175 "https://www.googleapis.com/bar+" 176 "https://www.googleapis.com/baz"; 177 ScopeList scopes; 178 scopes.push_back("https://www.googleapis.com/foo"); 179 scopes.push_back("https://www.googleapis.com/bar"); 180 scopes.push_back("https://www.googleapis.com/baz"); 181 EXPECT_EQ(body, OAuth2AccessTokenFetcher::MakeGetAccessTokenBody( 182 "cid1", "cs1", "rt1", scopes)); 183 } 184 } 185 186 // http://crbug.com/114215 187 #if defined(OS_WIN) 188 #define MAYBE_ParseGetAccessTokenResponse DISABLED_ParseGetAccessTokenResponse 189 #else 190 #define MAYBE_ParseGetAccessTokenResponse ParseGetAccessTokenResponse 191 #endif // defined(OS_WIN) 192 TEST_F(OAuth2AccessTokenFetcherTest, MAYBE_ParseGetAccessTokenResponse) { 193 { // No body. 194 TestURLFetcher url_fetcher(0, GURL("www.google.com"), NULL); 195 196 std::string at; 197 int expires_in; 198 EXPECT_FALSE(OAuth2AccessTokenFetcher::ParseGetAccessTokenResponse( 199 &url_fetcher, &at, &expires_in)); 200 EXPECT_TRUE(at.empty()); 201 } 202 { // Bad json. 203 TestURLFetcher url_fetcher(0, GURL("www.google.com"), NULL); 204 url_fetcher.SetResponseString("foo"); 205 206 std::string at; 207 int expires_in; 208 EXPECT_FALSE(OAuth2AccessTokenFetcher::ParseGetAccessTokenResponse( 209 &url_fetcher, &at, &expires_in)); 210 EXPECT_TRUE(at.empty()); 211 } 212 { // Valid json: access token missing. 213 TestURLFetcher url_fetcher(0, GURL("www.google.com"), NULL); 214 url_fetcher.SetResponseString(kTokenResponseNoAccessToken); 215 216 std::string at; 217 int expires_in; 218 EXPECT_FALSE(OAuth2AccessTokenFetcher::ParseGetAccessTokenResponse( 219 &url_fetcher, &at, &expires_in)); 220 EXPECT_TRUE(at.empty()); 221 } 222 { // Valid json: all good. 223 TestURLFetcher url_fetcher(0, GURL("www.google.com"), NULL); 224 url_fetcher.SetResponseString(kValidTokenResponse); 225 226 std::string at; 227 int expires_in; 228 EXPECT_TRUE(OAuth2AccessTokenFetcher::ParseGetAccessTokenResponse( 229 &url_fetcher, &at, &expires_in)); 230 EXPECT_EQ("at1", at); 231 EXPECT_EQ(3600, expires_in); 232 } 233 } 234