Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / google_apis / gaia / gaia_oauth_client_unittest.cc
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.
6
7 #include <string>
8 #include <vector>
9
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"
23
24 using ::testing::_;
25 using ::testing::Eq;
26 using ::testing::HasSubstr;
27 using ::testing::Pointee;
28 using ::testing::SaveArg;
29
30 namespace {
31
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);
49   }
50
51   virtual ~MockOAuthFetcher() { }
52
53   virtual 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);
57     }
58
59     net::URLRequestStatus::Status code = net::URLRequestStatus::SUCCESS;
60     if (GetResponseCode() != net::HTTP_OK) {
61       code = net::URLRequestStatus::FAILED;
62       current_failure_count_++;
63     }
64     set_status(net::URLRequestStatus(code, 0));
65
66     if (complete_immediately_)
67       delegate()->OnURLFetchComplete(this);
68   }
69
70   void Finish() {
71     ASSERT_FALSE(complete_immediately_);
72     delegate()->OnURLFetchComplete(this);
73   }
74
75  private:
76   int max_failure_count_;
77   int current_failure_count_;
78   bool complete_immediately_;
79   DISALLOW_COPY_AND_ASSIGN(MockOAuthFetcher);
80 };
81
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) {
89   }
90   virtual ~MockOAuthFetcherFactory() {}
91   virtual 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,
103         d);
104     return url_fetcher_;
105   }
106   void set_response_code(int response_code) {
107     response_code_ = response_code;
108   }
109   void set_max_failure_count(int count) {
110     max_failure_count_ = count;
111   }
112   void set_results(const std::string& results) {
113     results_ = results;
114   }
115   MockOAuthFetcher* get_url_fetcher() {
116     return url_fetcher_;
117   }
118   void set_complete_immediately(bool complete_immediately) {
119     complete_immediately_ = complete_immediately;
120   }
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);
128 };
129
130 const std::string kTestAccessToken = "1/fFAGRNJru1FTz70BzhT3Zg";
131 const std::string kTestRefreshToken =
132     "1/6BMfW9j53gdGImsixUH6kU5RsR4zwI9lUVX-tqf8JXQ";
133 const std::string kTestUserEmail = "a_user@gmail.com";
134 const std::string kTestUserId = "8675309";
135 const int kTestExpiresIn = 3920;
136
137 const std::string kDummyGetTokensResult =
138     "{\"access_token\":\"" + kTestAccessToken + "\","
139     "\"expires_in\":" + base::IntToString(kTestExpiresIn) + ","
140     "\"refresh_token\":\"" + kTestRefreshToken + "\"}";
141
142 const std::string kDummyRefreshTokenResult =
143     "{\"access_token\":\"" + kTestAccessToken + "\","
144     "\"expires_in\":" + base::IntToString(kTestExpiresIn) + "}";
145
146 const std::string kDummyUserInfoResult =
147     "{\"email\":\"" + kTestUserEmail + "\"}";
148
149 const std::string kDummyUserIdResult =
150     "{\"id\":\"" + kTestUserId + "\"}";
151
152 const std::string kDummyFullUserInfoResult =
153     "{"
154       "\"family_name\": \"Bar\", "
155       "\"name\": \"Foo Bar\", "
156       "\"picture\": \"https://lh4.googleusercontent.com/hash/photo.jpg\", "
157       "\"locale\": \"en\", "
158       "\"gender\": \"male\", "
159       "\"link\": \"https://plus.google.com/+FooBar\", "
160       "\"given_name\": \"Foo\", "
161       "\"id\": \"12345678901234567890\""
162     "}";
163
164 const std::string kDummyTokenInfoResult =
165   "{\"issued_to\": \"1234567890.apps.googleusercontent.com\","
166   "\"audience\": \"1234567890.apps.googleusercontent.com\","
167   "\"scope\": \"https://googleapis.com/oauth2/v2/tokeninfo\","
168   "\"expires_in\":" + base::IntToString(kTestExpiresIn) + "}";
169 }
170
171 namespace gaia {
172
173 class GaiaOAuthClientTest : public testing::Test {
174  protected:
175   virtual void SetUp() OVERRIDE {
176     client_info_.client_id = "test_client_id";
177     client_info_.client_secret = "test_client_secret";
178     client_info_.redirect_uri = "test_redirect_uri";
179   };
180
181  protected:
182   net::TestURLRequestContextGetter* GetRequestContext() {
183     if (!request_context_getter_) {
184       request_context_getter_ = new net::TestURLRequestContextGetter(
185           message_loop_.message_loop_proxy());
186     }
187     return request_context_getter_;
188   }
189
190   base::MessageLoop message_loop_;
191   scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
192   OAuthClientInfo client_info_;
193 };
194
195 class MockGaiaOAuthClientDelegate : public gaia::GaiaOAuthClient::Delegate {
196  public:
197   MockGaiaOAuthClientDelegate() {}
198   ~MockGaiaOAuthClientDelegate() {}
199
200   MOCK_METHOD3(OnGetTokensResponse, void(const std::string& refresh_token,
201                                          const std::string& access_token,
202                                          int expires_in_seconds));
203   MOCK_METHOD2(OnRefreshTokenResponse, void(const std::string& access_token,
204                                             int expires_in_seconds));
205   MOCK_METHOD1(OnGetUserEmailResponse, void(const std::string& user_email));
206   MOCK_METHOD1(OnGetUserIdResponse, void(const std::string& user_id));
207   MOCK_METHOD0(OnOAuthError, void());
208   MOCK_METHOD1(OnNetworkError, void(int response_code));
209
210   // gMock doesn't like methods that take or return scoped_ptr.  A
211   // work-around is to create a mock method that takes a raw ptr, and
212   // override the problematic method to call through to it.
213   // https://groups.google.com/a/chromium.org/d/msg/chromium-dev/01sDxsJ1OYw/I_S0xCBRF2oJ
214   MOCK_METHOD1(OnGetUserInfoResponsePtr,
215                void(const base::DictionaryValue* user_info));
216   virtual void OnGetUserInfoResponse(
217       scoped_ptr<base::DictionaryValue> user_info) OVERRIDE {
218     user_info_.reset(user_info.release());
219     OnGetUserInfoResponsePtr(user_info_.get());
220   }
221   MOCK_METHOD1(OnGetTokenInfoResponsePtr,
222                void(const base::DictionaryValue* token_info));
223   virtual void OnGetTokenInfoResponse(
224       scoped_ptr<base::DictionaryValue> token_info) OVERRIDE {
225     token_info_.reset(token_info.release());
226     OnGetTokenInfoResponsePtr(token_info_.get());
227   }
228
229  private:
230   scoped_ptr<base::DictionaryValue> user_info_;
231   scoped_ptr<base::DictionaryValue> token_info_;
232   DISALLOW_COPY_AND_ASSIGN(MockGaiaOAuthClientDelegate);
233 };
234
235 TEST_F(GaiaOAuthClientTest, NetworkFailure) {
236   int response_code = net::HTTP_INTERNAL_SERVER_ERROR;
237
238   MockGaiaOAuthClientDelegate delegate;
239   EXPECT_CALL(delegate, OnNetworkError(response_code))
240       .Times(1);
241
242   MockOAuthFetcherFactory factory;
243   factory.set_response_code(response_code);
244   factory.set_max_failure_count(4);
245
246   GaiaOAuthClient auth(GetRequestContext());
247   auth.GetTokensFromAuthCode(client_info_, "auth_code", 2, &delegate);
248 }
249
250 TEST_F(GaiaOAuthClientTest, NetworkFailureRecover) {
251   int response_code = net::HTTP_INTERNAL_SERVER_ERROR;
252
253   MockGaiaOAuthClientDelegate delegate;
254   EXPECT_CALL(delegate, OnGetTokensResponse(kTestRefreshToken, kTestAccessToken,
255       kTestExpiresIn)).Times(1);
256
257   MockOAuthFetcherFactory factory;
258   factory.set_response_code(response_code);
259   factory.set_max_failure_count(4);
260   factory.set_results(kDummyGetTokensResult);
261
262   GaiaOAuthClient auth(GetRequestContext());
263   auth.GetTokensFromAuthCode(client_info_, "auth_code", -1, &delegate);
264 }
265
266 TEST_F(GaiaOAuthClientTest, OAuthFailure) {
267   int response_code = net::HTTP_BAD_REQUEST;
268
269   MockGaiaOAuthClientDelegate delegate;
270   EXPECT_CALL(delegate, OnOAuthError()).Times(1);
271
272   MockOAuthFetcherFactory factory;
273   factory.set_response_code(response_code);
274   factory.set_max_failure_count(-1);
275   factory.set_results(kDummyGetTokensResult);
276
277   GaiaOAuthClient auth(GetRequestContext());
278   auth.GetTokensFromAuthCode(client_info_, "auth_code", -1, &delegate);
279 }
280
281
282 TEST_F(GaiaOAuthClientTest, GetTokensSuccess) {
283   MockGaiaOAuthClientDelegate delegate;
284   EXPECT_CALL(delegate, OnGetTokensResponse(kTestRefreshToken, kTestAccessToken,
285       kTestExpiresIn)).Times(1);
286
287   MockOAuthFetcherFactory factory;
288   factory.set_results(kDummyGetTokensResult);
289
290   GaiaOAuthClient auth(GetRequestContext());
291   auth.GetTokensFromAuthCode(client_info_, "auth_code", -1, &delegate);
292 }
293
294 TEST_F(GaiaOAuthClientTest, RefreshTokenSuccess) {
295   MockGaiaOAuthClientDelegate delegate;
296   EXPECT_CALL(delegate, OnRefreshTokenResponse(kTestAccessToken,
297       kTestExpiresIn)).Times(1);
298
299   MockOAuthFetcherFactory factory;
300   factory.set_results(kDummyRefreshTokenResult);
301   factory.set_complete_immediately(false);
302
303   GaiaOAuthClient auth(GetRequestContext());
304   auth.RefreshToken(client_info_, "refresh_token", std::vector<std::string>(),
305                     -1, &delegate);
306   EXPECT_THAT(factory.get_url_fetcher()->upload_data(),
307               Not(HasSubstr("scope")));
308   factory.get_url_fetcher()->Finish();
309 }
310
311 TEST_F(GaiaOAuthClientTest, RefreshTokenDownscopingSuccess) {
312   MockGaiaOAuthClientDelegate delegate;
313   EXPECT_CALL(delegate, OnRefreshTokenResponse(kTestAccessToken,
314       kTestExpiresIn)).Times(1);
315
316   MockOAuthFetcherFactory factory;
317   factory.set_results(kDummyRefreshTokenResult);
318   factory.set_complete_immediately(false);
319
320   GaiaOAuthClient auth(GetRequestContext());
321   auth.RefreshToken(client_info_, "refresh_token",
322                     std::vector<std::string>(1, "scope4test"), -1, &delegate);
323   EXPECT_THAT(factory.get_url_fetcher()->upload_data(),
324               HasSubstr("&scope=scope4test"));
325   factory.get_url_fetcher()->Finish();
326 }
327
328
329 TEST_F(GaiaOAuthClientTest, GetUserEmail) {
330   MockGaiaOAuthClientDelegate delegate;
331   EXPECT_CALL(delegate, OnGetUserEmailResponse(kTestUserEmail)).Times(1);
332
333   MockOAuthFetcherFactory factory;
334   factory.set_results(kDummyUserInfoResult);
335
336   GaiaOAuthClient auth(GetRequestContext());
337   auth.GetUserEmail("access_token", 1, &delegate);
338 }
339
340 TEST_F(GaiaOAuthClientTest, GetUserId) {
341   MockGaiaOAuthClientDelegate delegate;
342   EXPECT_CALL(delegate, OnGetUserIdResponse(kTestUserId)).Times(1);
343
344   MockOAuthFetcherFactory factory;
345   factory.set_results(kDummyUserIdResult);
346
347   GaiaOAuthClient auth(GetRequestContext());
348   auth.GetUserId("access_token", 1, &delegate);
349 }
350
351 TEST_F(GaiaOAuthClientTest, GetUserInfo) {
352   const base::DictionaryValue* captured_result;
353
354   MockGaiaOAuthClientDelegate delegate;
355   EXPECT_CALL(delegate, OnGetUserInfoResponsePtr(_))
356       .WillOnce(SaveArg<0>(&captured_result));
357
358   MockOAuthFetcherFactory factory;
359   factory.set_results(kDummyFullUserInfoResult);
360
361   GaiaOAuthClient auth(GetRequestContext());
362   auth.GetUserInfo("access_token", 1, &delegate);
363
364   scoped_ptr<base::Value> value(
365       base::JSONReader::Read(kDummyFullUserInfoResult));
366   DCHECK(value);
367   ASSERT_TRUE(value->IsType(base::Value::TYPE_DICTIONARY));
368   base::DictionaryValue* expected_result;
369   value->GetAsDictionary(&expected_result);
370
371   ASSERT_TRUE(expected_result->Equals(captured_result));
372 }
373
374 TEST_F(GaiaOAuthClientTest, GetTokenInfo) {
375   const base::DictionaryValue* captured_result;
376
377   MockGaiaOAuthClientDelegate delegate;
378   EXPECT_CALL(delegate, OnGetTokenInfoResponsePtr(_))
379       .WillOnce(SaveArg<0>(&captured_result));
380
381   MockOAuthFetcherFactory factory;
382   factory.set_results(kDummyTokenInfoResult);
383
384   GaiaOAuthClient auth(GetRequestContext());
385   auth.GetTokenInfo("access_token", 1, &delegate);
386
387   std::string issued_to;
388   ASSERT_TRUE(captured_result->GetString("issued_to",  &issued_to));
389   ASSERT_EQ("1234567890.apps.googleusercontent.com", issued_to);
390 }
391
392 }  // namespace gaia