Roll src/third_party/WebKit d26421b:4b1dbe3 (svn 194839:194840)
[chromium-blink-merge.git] / google_apis / gaia / gaia_oauth_client_unittest.cc
blob530baef06a76d712447aa720ea2f52718b52be0e
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 GaiaOAuthClient.
7 #include <string>
8 #include <vector>
10 #include "base/json/json_reader.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/values.h"
13 #include "google_apis/gaia/gaia_oauth_client.h"
14 #include "net/base/net_errors.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_delegate.h"
18 #include "net/url_request/url_request_status.h"
19 #include "net/url_request/url_request_test_util.h"
20 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22 #include "url/gurl.h"
24 using ::testing::_;
25 using ::testing::Eq;
26 using ::testing::HasSubstr;
27 using ::testing::Pointee;
28 using ::testing::SaveArg;
30 namespace {
32 // Responds as though OAuth returned from the server.
33 class MockOAuthFetcher : public net::TestURLFetcher {
34 public:
35 MockOAuthFetcher(int response_code,
36 int max_failure_count,
37 bool complete_immediately,
38 const GURL& url,
39 const std::string& results,
40 net::URLFetcher::RequestType request_type,
41 net::URLFetcherDelegate* d)
42 : net::TestURLFetcher(0, url, d),
43 max_failure_count_(max_failure_count),
44 current_failure_count_(0),
45 complete_immediately_(complete_immediately) {
46 set_url(url);
47 set_response_code(response_code);
48 SetResponseString(results);
51 ~MockOAuthFetcher() override {}
53 void Start() override {
54 if ((GetResponseCode() != net::HTTP_OK) && (max_failure_count_ != -1) &&
55 (current_failure_count_ == max_failure_count_)) {
56 set_response_code(net::HTTP_OK);
59 net::URLRequestStatus::Status code = net::URLRequestStatus::SUCCESS;
60 if (GetResponseCode() != net::HTTP_OK) {
61 code = net::URLRequestStatus::FAILED;
62 current_failure_count_++;
64 set_status(net::URLRequestStatus(code, 0));
66 if (complete_immediately_)
67 delegate()->OnURLFetchComplete(this);
70 void Finish() {
71 ASSERT_FALSE(complete_immediately_);
72 delegate()->OnURLFetchComplete(this);
75 private:
76 int max_failure_count_;
77 int current_failure_count_;
78 bool complete_immediately_;
79 DISALLOW_COPY_AND_ASSIGN(MockOAuthFetcher);
82 class MockOAuthFetcherFactory : public net::URLFetcherFactory,
83 public net::ScopedURLFetcherFactory {
84 public:
85 MockOAuthFetcherFactory()
86 : net::ScopedURLFetcherFactory(this),
87 response_code_(net::HTTP_OK),
88 complete_immediately_(true) {
90 ~MockOAuthFetcherFactory() override {}
91 scoped_ptr<net::URLFetcher> CreateURLFetcher(
92 int id,
93 const GURL& url,
94 net::URLFetcher::RequestType request_type,
95 net::URLFetcherDelegate* d) override {
96 url_fetcher_ = new MockOAuthFetcher(
97 response_code_,
98 max_failure_count_,
99 complete_immediately_,
100 url,
101 results_,
102 request_type,
104 return scoped_ptr<net::URLFetcher>(url_fetcher_);
106 void set_response_code(int response_code) {
107 response_code_ = response_code;
109 void set_max_failure_count(int count) {
110 max_failure_count_ = count;
112 void set_results(const std::string& results) {
113 results_ = results;
115 MockOAuthFetcher* get_url_fetcher() {
116 return url_fetcher_;
118 void set_complete_immediately(bool complete_immediately) {
119 complete_immediately_ = complete_immediately;
121 private:
122 MockOAuthFetcher* url_fetcher_;
123 int response_code_;
124 bool complete_immediately_;
125 int max_failure_count_;
126 std::string results_;
127 DISALLOW_COPY_AND_ASSIGN(MockOAuthFetcherFactory);
130 const std::string kTestAccessToken = "1/fFAGRNJru1FTz70BzhT3Zg";
131 const std::string kTestAccessTokenHandle = "1/kjhH87dfgkj87Hhj5KJkjZ";
132 const std::string kTestRefreshToken =
133 "1/6BMfW9j53gdGImsixUH6kU5RsR4zwI9lUVX-tqf8JXQ";
134 const std::string kTestUserEmail = "a_user@gmail.com";
135 const std::string kTestUserId = "8675309";
136 const int kTestExpiresIn = 3920;
138 const std::string kDummyGetTokensResult =
139 "{\"access_token\":\"" + kTestAccessToken + "\","
140 "\"expires_in\":" + base::IntToString(kTestExpiresIn) + ","
141 "\"refresh_token\":\"" + kTestRefreshToken + "\"}";
143 const std::string kDummyRefreshTokenResult =
144 "{\"access_token\":\"" + kTestAccessToken + "\","
145 "\"expires_in\":" + base::IntToString(kTestExpiresIn) + "}";
147 const std::string kDummyUserInfoResult =
148 "{\"email\":\"" + kTestUserEmail + "\"}";
150 const std::string kDummyUserIdResult =
151 "{\"id\":\"" + kTestUserId + "\"}";
153 const std::string kDummyFullUserInfoResult =
155 "\"family_name\": \"Bar\", "
156 "\"name\": \"Foo Bar\", "
157 "\"picture\": \"https://lh4.googleusercontent.com/hash/photo.jpg\", "
158 "\"locale\": \"en\", "
159 "\"gender\": \"male\", "
160 "\"link\": \"https://plus.google.com/+FooBar\", "
161 "\"given_name\": \"Foo\", "
162 "\"id\": \"12345678901234567890\""
163 "}";
165 const std::string kDummyTokenInfoResult =
166 "{\"issued_to\": \"1234567890.apps.googleusercontent.com\","
167 "\"audience\": \"1234567890.apps.googleusercontent.com\","
168 "\"scope\": \"https://googleapis.com/oauth2/v2/tokeninfo\","
169 "\"expires_in\":" + base::IntToString(kTestExpiresIn) + "}";
171 const std::string kDummyTokenHandleInfoResult =
172 "{\"audience\": \"1234567890.apps.googleusercontent.com\","
173 "\"expires_in\":" + base::IntToString(kTestExpiresIn) + "}";
175 } // namespace
177 namespace gaia {
179 class GaiaOAuthClientTest : public testing::Test {
180 protected:
181 void SetUp() override {
182 client_info_.client_id = "test_client_id";
183 client_info_.client_secret = "test_client_secret";
184 client_info_.redirect_uri = "test_redirect_uri";
187 protected:
188 net::TestURLRequestContextGetter* GetRequestContext() {
189 if (!request_context_getter_.get()) {
190 request_context_getter_ = new net::TestURLRequestContextGetter(
191 message_loop_.message_loop_proxy());
193 return request_context_getter_.get();
196 base::MessageLoop message_loop_;
197 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
198 OAuthClientInfo client_info_;
201 class MockGaiaOAuthClientDelegate : public gaia::GaiaOAuthClient::Delegate {
202 public:
203 MockGaiaOAuthClientDelegate() {}
204 ~MockGaiaOAuthClientDelegate() {}
206 MOCK_METHOD3(OnGetTokensResponse, void(const std::string& refresh_token,
207 const std::string& access_token,
208 int expires_in_seconds));
209 MOCK_METHOD2(OnRefreshTokenResponse, void(const std::string& access_token,
210 int expires_in_seconds));
211 MOCK_METHOD1(OnGetUserEmailResponse, void(const std::string& user_email));
212 MOCK_METHOD1(OnGetUserIdResponse, void(const std::string& user_id));
213 MOCK_METHOD0(OnOAuthError, void());
214 MOCK_METHOD1(OnNetworkError, void(int response_code));
216 // gMock doesn't like methods that take or return scoped_ptr. A
217 // work-around is to create a mock method that takes a raw ptr, and
218 // override the problematic method to call through to it.
219 // https://groups.google.com/a/chromium.org/d/msg/chromium-dev/01sDxsJ1OYw/I_S0xCBRF2oJ
220 MOCK_METHOD1(OnGetUserInfoResponsePtr,
221 void(const base::DictionaryValue* user_info));
222 void OnGetUserInfoResponse(
223 scoped_ptr<base::DictionaryValue> user_info) override {
224 user_info_.reset(user_info.release());
225 OnGetUserInfoResponsePtr(user_info_.get());
227 MOCK_METHOD1(OnGetTokenInfoResponsePtr,
228 void(const base::DictionaryValue* token_info));
229 void OnGetTokenInfoResponse(
230 scoped_ptr<base::DictionaryValue> token_info) override {
231 token_info_.reset(token_info.release());
232 OnGetTokenInfoResponsePtr(token_info_.get());
235 private:
236 scoped_ptr<base::DictionaryValue> user_info_;
237 scoped_ptr<base::DictionaryValue> token_info_;
238 DISALLOW_COPY_AND_ASSIGN(MockGaiaOAuthClientDelegate);
241 TEST_F(GaiaOAuthClientTest, NetworkFailure) {
242 int response_code = net::HTTP_INTERNAL_SERVER_ERROR;
244 MockGaiaOAuthClientDelegate delegate;
245 EXPECT_CALL(delegate, OnNetworkError(response_code))
246 .Times(1);
248 MockOAuthFetcherFactory factory;
249 factory.set_response_code(response_code);
250 factory.set_max_failure_count(4);
252 GaiaOAuthClient auth(GetRequestContext());
253 auth.GetTokensFromAuthCode(client_info_, "auth_code", 2, &delegate);
256 TEST_F(GaiaOAuthClientTest, NetworkFailureRecover) {
257 int response_code = net::HTTP_INTERNAL_SERVER_ERROR;
259 MockGaiaOAuthClientDelegate delegate;
260 EXPECT_CALL(delegate, OnGetTokensResponse(kTestRefreshToken, kTestAccessToken,
261 kTestExpiresIn)).Times(1);
263 MockOAuthFetcherFactory factory;
264 factory.set_response_code(response_code);
265 factory.set_max_failure_count(4);
266 factory.set_results(kDummyGetTokensResult);
268 GaiaOAuthClient auth(GetRequestContext());
269 auth.GetTokensFromAuthCode(client_info_, "auth_code", -1, &delegate);
272 TEST_F(GaiaOAuthClientTest, OAuthFailure) {
273 int response_code = net::HTTP_BAD_REQUEST;
275 MockGaiaOAuthClientDelegate delegate;
276 EXPECT_CALL(delegate, OnOAuthError()).Times(1);
278 MockOAuthFetcherFactory factory;
279 factory.set_response_code(response_code);
280 factory.set_max_failure_count(-1);
281 factory.set_results(kDummyGetTokensResult);
283 GaiaOAuthClient auth(GetRequestContext());
284 auth.GetTokensFromAuthCode(client_info_, "auth_code", -1, &delegate);
288 TEST_F(GaiaOAuthClientTest, GetTokensSuccess) {
289 MockGaiaOAuthClientDelegate delegate;
290 EXPECT_CALL(delegate, OnGetTokensResponse(kTestRefreshToken, kTestAccessToken,
291 kTestExpiresIn)).Times(1);
293 MockOAuthFetcherFactory factory;
294 factory.set_results(kDummyGetTokensResult);
296 GaiaOAuthClient auth(GetRequestContext());
297 auth.GetTokensFromAuthCode(client_info_, "auth_code", -1, &delegate);
300 TEST_F(GaiaOAuthClientTest, RefreshTokenSuccess) {
301 MockGaiaOAuthClientDelegate delegate;
302 EXPECT_CALL(delegate, OnRefreshTokenResponse(kTestAccessToken,
303 kTestExpiresIn)).Times(1);
305 MockOAuthFetcherFactory factory;
306 factory.set_results(kDummyRefreshTokenResult);
307 factory.set_complete_immediately(false);
309 GaiaOAuthClient auth(GetRequestContext());
310 auth.RefreshToken(client_info_, "refresh_token", std::vector<std::string>(),
311 -1, &delegate);
312 EXPECT_THAT(factory.get_url_fetcher()->upload_data(),
313 Not(HasSubstr("scope")));
314 factory.get_url_fetcher()->Finish();
317 TEST_F(GaiaOAuthClientTest, RefreshTokenDownscopingSuccess) {
318 MockGaiaOAuthClientDelegate delegate;
319 EXPECT_CALL(delegate, OnRefreshTokenResponse(kTestAccessToken,
320 kTestExpiresIn)).Times(1);
322 MockOAuthFetcherFactory factory;
323 factory.set_results(kDummyRefreshTokenResult);
324 factory.set_complete_immediately(false);
326 GaiaOAuthClient auth(GetRequestContext());
327 auth.RefreshToken(client_info_, "refresh_token",
328 std::vector<std::string>(1, "scope4test"), -1, &delegate);
329 EXPECT_THAT(factory.get_url_fetcher()->upload_data(),
330 HasSubstr("&scope=scope4test"));
331 factory.get_url_fetcher()->Finish();
335 TEST_F(GaiaOAuthClientTest, GetUserEmail) {
336 MockGaiaOAuthClientDelegate delegate;
337 EXPECT_CALL(delegate, OnGetUserEmailResponse(kTestUserEmail)).Times(1);
339 MockOAuthFetcherFactory factory;
340 factory.set_results(kDummyUserInfoResult);
342 GaiaOAuthClient auth(GetRequestContext());
343 auth.GetUserEmail("access_token", 1, &delegate);
346 TEST_F(GaiaOAuthClientTest, GetUserId) {
347 MockGaiaOAuthClientDelegate delegate;
348 EXPECT_CALL(delegate, OnGetUserIdResponse(kTestUserId)).Times(1);
350 MockOAuthFetcherFactory factory;
351 factory.set_results(kDummyUserIdResult);
353 GaiaOAuthClient auth(GetRequestContext());
354 auth.GetUserId("access_token", 1, &delegate);
357 TEST_F(GaiaOAuthClientTest, GetUserInfo) {
358 const base::DictionaryValue* captured_result;
360 MockGaiaOAuthClientDelegate delegate;
361 EXPECT_CALL(delegate, OnGetUserInfoResponsePtr(_))
362 .WillOnce(SaveArg<0>(&captured_result));
364 MockOAuthFetcherFactory factory;
365 factory.set_results(kDummyFullUserInfoResult);
367 GaiaOAuthClient auth(GetRequestContext());
368 auth.GetUserInfo("access_token", 1, &delegate);
370 scoped_ptr<base::Value> value(
371 base::JSONReader::Read(kDummyFullUserInfoResult));
372 DCHECK(value);
373 ASSERT_TRUE(value->IsType(base::Value::TYPE_DICTIONARY));
374 base::DictionaryValue* expected_result;
375 value->GetAsDictionary(&expected_result);
377 ASSERT_TRUE(expected_result->Equals(captured_result));
380 TEST_F(GaiaOAuthClientTest, GetTokenInfo) {
381 const base::DictionaryValue* captured_result;
383 MockGaiaOAuthClientDelegate delegate;
384 EXPECT_CALL(delegate, OnGetTokenInfoResponsePtr(_))
385 .WillOnce(SaveArg<0>(&captured_result));
387 MockOAuthFetcherFactory factory;
388 factory.set_results(kDummyTokenInfoResult);
390 GaiaOAuthClient auth(GetRequestContext());
391 auth.GetTokenInfo("some_token", 1, &delegate);
393 std::string issued_to;
394 ASSERT_TRUE(captured_result->GetString("issued_to", &issued_to));
395 ASSERT_EQ("1234567890.apps.googleusercontent.com", issued_to);
398 TEST_F(GaiaOAuthClientTest, GetTokenHandleInfo) {
399 const base::DictionaryValue* captured_result;
401 MockGaiaOAuthClientDelegate delegate;
402 EXPECT_CALL(delegate, OnGetTokenInfoResponsePtr(_))
403 .WillOnce(SaveArg<0>(&captured_result));
405 MockOAuthFetcherFactory factory;
406 factory.set_results(kDummyTokenHandleInfoResult);
408 GaiaOAuthClient auth(GetRequestContext());
409 auth.GetTokenHandleInfo("some_handle", 1, &delegate);
411 std::string audience;
412 ASSERT_TRUE(captured_result->GetString("audience", &audience));
413 ASSERT_EQ("1234567890.apps.googleusercontent.com", audience);
416 } // namespace gaia