Upstream version 7.36.149.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/strings/string_number_conversions.h"
11 #include "base/values.h"
12 #include "google_apis/gaia/gaia_oauth_client.h"
13 #include "net/base/net_errors.h"
14 #include "net/http/http_status_code.h"
15 #include "net/url_request/test_url_fetcher_factory.h"
16 #include "net/url_request/url_fetcher_delegate.h"
17 #include "net/url_request/url_request_status.h"
18 #include "net/url_request/url_request_test_util.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 #include "url/gurl.h"
22
23 using ::testing::_;
24 using ::testing::Eq;
25 using ::testing::HasSubstr;
26 using ::testing::Pointee;
27 using ::testing::SaveArg;
28
29 namespace {
30
31 // Responds as though OAuth returned from the server.
32 class MockOAuthFetcher : public net::TestURLFetcher {
33  public:
34   MockOAuthFetcher(int response_code,
35                    int max_failure_count,
36                    bool complete_immediately,
37                    const GURL& url,
38                    const std::string& results,
39                    net::URLFetcher::RequestType request_type,
40                    net::URLFetcherDelegate* d)
41       : net::TestURLFetcher(0, url, d),
42         max_failure_count_(max_failure_count),
43         current_failure_count_(0),
44         complete_immediately_(complete_immediately) {
45     set_url(url);
46     set_response_code(response_code);
47     SetResponseString(results);
48   }
49
50   virtual ~MockOAuthFetcher() { }
51
52   virtual void Start() OVERRIDE {
53     if ((GetResponseCode() != net::HTTP_OK) && (max_failure_count_ != -1) &&
54         (current_failure_count_ == max_failure_count_)) {
55       set_response_code(net::HTTP_OK);
56     }
57
58     net::URLRequestStatus::Status code = net::URLRequestStatus::SUCCESS;
59     if (GetResponseCode() != net::HTTP_OK) {
60       code = net::URLRequestStatus::FAILED;
61       current_failure_count_++;
62     }
63     set_status(net::URLRequestStatus(code, 0));
64
65     if (complete_immediately_)
66       delegate()->OnURLFetchComplete(this);
67   }
68
69   void Finish() {
70     ASSERT_FALSE(complete_immediately_);
71     delegate()->OnURLFetchComplete(this);
72   }
73
74  private:
75   int max_failure_count_;
76   int current_failure_count_;
77   bool complete_immediately_;
78   DISALLOW_COPY_AND_ASSIGN(MockOAuthFetcher);
79 };
80
81 class MockOAuthFetcherFactory : public net::URLFetcherFactory,
82                                 public net::ScopedURLFetcherFactory {
83  public:
84   MockOAuthFetcherFactory()
85       : net::ScopedURLFetcherFactory(this),
86         response_code_(net::HTTP_OK),
87         complete_immediately_(true) {
88   }
89   virtual ~MockOAuthFetcherFactory() {}
90   virtual net::URLFetcher* CreateURLFetcher(
91       int id,
92       const GURL& url,
93       net::URLFetcher::RequestType request_type,
94       net::URLFetcherDelegate* d) OVERRIDE {
95     url_fetcher_ = new MockOAuthFetcher(
96         response_code_,
97         max_failure_count_,
98         complete_immediately_,
99         url,
100         results_,
101         request_type,
102         d);
103     return url_fetcher_;
104   }
105   void set_response_code(int response_code) {
106     response_code_ = response_code;
107   }
108   void set_max_failure_count(int count) {
109     max_failure_count_ = count;
110   }
111   void set_results(const std::string& results) {
112     results_ = results;
113   }
114   MockOAuthFetcher* get_url_fetcher() {
115     return url_fetcher_;
116   }
117   void set_complete_immediately(bool complete_immediately) {
118     complete_immediately_ = complete_immediately;
119   }
120  private:
121   MockOAuthFetcher* url_fetcher_;
122   int response_code_;
123   bool complete_immediately_;
124   int max_failure_count_;
125   std::string results_;
126   DISALLOW_COPY_AND_ASSIGN(MockOAuthFetcherFactory);
127 };
128
129 const std::string kTestAccessToken = "1/fFAGRNJru1FTz70BzhT3Zg";
130 const std::string kTestRefreshToken =
131     "1/6BMfW9j53gdGImsixUH6kU5RsR4zwI9lUVX-tqf8JXQ";
132 const std::string kTestUserEmail = "a_user@gmail.com";
133 const std::string kTestUserId = "8675309";
134 const int kTestExpiresIn = 3920;
135
136 const std::string kDummyGetTokensResult =
137     "{\"access_token\":\"" + kTestAccessToken + "\","
138     "\"expires_in\":" + base::IntToString(kTestExpiresIn) + ","
139     "\"refresh_token\":\"" + kTestRefreshToken + "\"}";
140
141 const std::string kDummyRefreshTokenResult =
142     "{\"access_token\":\"" + kTestAccessToken + "\","
143     "\"expires_in\":" + base::IntToString(kTestExpiresIn) + "}";
144
145 const std::string kDummyUserIdResult =
146     "{\"id\":\"" + kTestUserId + "\"}";
147
148 const std::string kDummyTokenInfoResult =
149     "{\"issued_to\": \"1234567890.apps.googleusercontent.com\","
150     "\"audience\": \"1234567890.apps.googleusercontent.com\","
151     "\"scope\": \"https://googleapis.com/oauth2/v2/tokeninfo\","
152     "\"expires_in\":" + base::IntToString(kTestExpiresIn) + "}";
153 }
154
155 namespace gaia {
156
157 class GaiaOAuthClientTest : public testing::Test {
158  protected:
159   virtual void SetUp() OVERRIDE {
160     client_info_.client_id = "test_client_id";
161     client_info_.client_secret = "test_client_secret";
162     client_info_.redirect_uri = "test_redirect_uri";
163   };
164
165  protected:
166   net::TestURLRequestContextGetter* GetRequestContext() {
167     if (!request_context_getter_) {
168       request_context_getter_ = new net::TestURLRequestContextGetter(
169           message_loop_.message_loop_proxy());
170     }
171     return request_context_getter_;
172   }
173
174   base::MessageLoop message_loop_;
175   scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
176   OAuthClientInfo client_info_;
177 };
178
179 class MockGaiaOAuthClientDelegate : public gaia::GaiaOAuthClient::Delegate {
180  public:
181   MockGaiaOAuthClientDelegate() {}
182   ~MockGaiaOAuthClientDelegate() {}
183
184   MOCK_METHOD3(OnGetTokensResponse, void(const std::string& refresh_token,
185                                          const std::string& access_token,
186                                          int expires_in_seconds));
187   MOCK_METHOD2(OnRefreshTokenResponse, void(const std::string& access_token,
188                                             int expires_in_seconds));
189   MOCK_METHOD1(OnGetUserEmailResponse, void(const std::string& user_email));
190   MOCK_METHOD1(OnGetUserIdResponse, void(const std::string& user_id));
191   MOCK_METHOD0(OnOAuthError, void());
192   MOCK_METHOD1(OnNetworkError, void(int response_code));
193
194   // gMock doesn't like methods that take or return scoped_ptr.  A
195   // work-around is to create a mock method that takes a raw ptr, and
196   // override the problematic method to call through to it.
197   // https://groups.google.com/a/chromium.org/d/msg/chromium-dev/01sDxsJ1OYw/I_S0xCBRF2oJ
198   MOCK_METHOD1(OnGetTokenInfoResponsePtr,
199                void(const base::DictionaryValue* token_info));
200   virtual void OnGetTokenInfoResponse(
201       scoped_ptr<base::DictionaryValue> token_info) OVERRIDE {
202     token_info_.reset(token_info.release());
203     OnGetTokenInfoResponsePtr(token_info_.get());
204   }
205
206  private:
207   scoped_ptr<base::DictionaryValue> token_info_;
208   DISALLOW_COPY_AND_ASSIGN(MockGaiaOAuthClientDelegate);
209 };
210
211 TEST_F(GaiaOAuthClientTest, NetworkFailure) {
212   int response_code = net::HTTP_INTERNAL_SERVER_ERROR;
213
214   MockGaiaOAuthClientDelegate delegate;
215   EXPECT_CALL(delegate, OnNetworkError(response_code))
216       .Times(1);
217
218   MockOAuthFetcherFactory factory;
219   factory.set_response_code(response_code);
220   factory.set_max_failure_count(4);
221
222   GaiaOAuthClient auth(GetRequestContext());
223   auth.GetTokensFromAuthCode(client_info_, "auth_code", 2, &delegate);
224 }
225
226 TEST_F(GaiaOAuthClientTest, NetworkFailureRecover) {
227   int response_code = net::HTTP_INTERNAL_SERVER_ERROR;
228
229   MockGaiaOAuthClientDelegate delegate;
230   EXPECT_CALL(delegate, OnGetTokensResponse(kTestRefreshToken, kTestAccessToken,
231       kTestExpiresIn)).Times(1);
232
233   MockOAuthFetcherFactory factory;
234   factory.set_response_code(response_code);
235   factory.set_max_failure_count(4);
236   factory.set_results(kDummyGetTokensResult);
237
238   GaiaOAuthClient auth(GetRequestContext());
239   auth.GetTokensFromAuthCode(client_info_, "auth_code", -1, &delegate);
240 }
241
242 TEST_F(GaiaOAuthClientTest, OAuthFailure) {
243   int response_code = net::HTTP_BAD_REQUEST;
244
245   MockGaiaOAuthClientDelegate delegate;
246   EXPECT_CALL(delegate, OnOAuthError()).Times(1);
247
248   MockOAuthFetcherFactory factory;
249   factory.set_response_code(response_code);
250   factory.set_max_failure_count(-1);
251   factory.set_results(kDummyGetTokensResult);
252
253   GaiaOAuthClient auth(GetRequestContext());
254   auth.GetTokensFromAuthCode(client_info_, "auth_code", -1, &delegate);
255 }
256
257
258 TEST_F(GaiaOAuthClientTest, GetTokensSuccess) {
259   MockGaiaOAuthClientDelegate delegate;
260   EXPECT_CALL(delegate, OnGetTokensResponse(kTestRefreshToken, kTestAccessToken,
261       kTestExpiresIn)).Times(1);
262
263   MockOAuthFetcherFactory factory;
264   factory.set_results(kDummyGetTokensResult);
265
266   GaiaOAuthClient auth(GetRequestContext());
267   auth.GetTokensFromAuthCode(client_info_, "auth_code", -1, &delegate);
268 }
269
270 TEST_F(GaiaOAuthClientTest, RefreshTokenSuccess) {
271   MockGaiaOAuthClientDelegate delegate;
272   EXPECT_CALL(delegate, OnRefreshTokenResponse(kTestAccessToken,
273       kTestExpiresIn)).Times(1);
274
275   MockOAuthFetcherFactory factory;
276   factory.set_results(kDummyRefreshTokenResult);
277   factory.set_complete_immediately(false);
278
279   GaiaOAuthClient auth(GetRequestContext());
280   auth.RefreshToken(client_info_, "refresh_token", std::vector<std::string>(),
281                     -1, &delegate);
282   EXPECT_THAT(factory.get_url_fetcher()->upload_data(),
283               Not(HasSubstr("scope")));
284   factory.get_url_fetcher()->Finish();
285 }
286
287 TEST_F(GaiaOAuthClientTest, RefreshTokenDownscopingSuccess) {
288   MockGaiaOAuthClientDelegate delegate;
289   EXPECT_CALL(delegate, OnRefreshTokenResponse(kTestAccessToken,
290       kTestExpiresIn)).Times(1);
291
292   MockOAuthFetcherFactory factory;
293   factory.set_results(kDummyRefreshTokenResult);
294   factory.set_complete_immediately(false);
295
296   GaiaOAuthClient auth(GetRequestContext());
297   auth.RefreshToken(client_info_, "refresh_token",
298                     std::vector<std::string>(1, "scope4test"), -1, &delegate);
299   EXPECT_THAT(factory.get_url_fetcher()->upload_data(),
300               HasSubstr("&scope=scope4test"));
301   factory.get_url_fetcher()->Finish();
302 }
303
304 TEST_F(GaiaOAuthClientTest, GetUserEmail) {
305   MockGaiaOAuthClientDelegate delegate;
306   EXPECT_CALL(delegate, OnGetUserEmailResponse(kTestUserEmail)).Times(1);
307
308   const std::string kDummyUserInfoResult =
309       "{\"emails\": [{\"value\":\"" + kTestUserEmail +
310       "\", \"type\":\"account\"}]}";
311
312   MockOAuthFetcherFactory factory;
313   factory.set_results(kDummyUserInfoResult);
314
315   GaiaOAuthClient auth(GetRequestContext());
316   auth.GetUserEmail("access_token", 1, &delegate);
317 }
318
319 TEST_F(GaiaOAuthClientTest, GetUserEmailSecondItemValid) {
320   MockGaiaOAuthClientDelegate delegate;
321   EXPECT_CALL(delegate, OnGetUserEmailResponse(kTestUserEmail)).Times(1);
322
323   const std::string kDummyUserInfoResult =
324       "{\"emails\": [{\"value\":\"foo\"},"
325       "{\"value\":\"" + kTestUserEmail +
326       "\", \"type\":\"account\"}]}";
327
328   MockOAuthFetcherFactory factory;
329   factory.set_results(kDummyUserInfoResult);
330
331   GaiaOAuthClient auth(GetRequestContext());
332   auth.GetUserEmail("access_token", 1, &delegate);
333 }
334
335 TEST_F(GaiaOAuthClientTest, GetUserEmailNoValidItems) {
336   MockGaiaOAuthClientDelegate delegate;
337   EXPECT_CALL(delegate, OnNetworkError(_)).Times(1);
338
339   const std::string kDummyUserInfoResult =
340       "{\"emails\": [{\"value\":\"" + kTestUserEmail +
341       "\", \"type\":\"foo\"}]}";
342
343   MockOAuthFetcherFactory factory;
344   factory.set_results(kDummyUserInfoResult);
345
346   GaiaOAuthClient auth(GetRequestContext());
347   auth.GetUserEmail("access_token", 1, &delegate);
348 }
349
350 TEST_F(GaiaOAuthClientTest, GetUserId) {
351   MockGaiaOAuthClientDelegate delegate;
352   EXPECT_CALL(delegate, OnGetUserIdResponse(kTestUserId)).Times(1);
353
354   MockOAuthFetcherFactory factory;
355   factory.set_results(kDummyUserIdResult);
356
357   GaiaOAuthClient auth(GetRequestContext());
358   auth.GetUserId("access_token", 1, &delegate);
359 }
360
361 TEST_F(GaiaOAuthClientTest, GetTokenInfo) {
362   const base::DictionaryValue* captured_result;
363
364   MockGaiaOAuthClientDelegate delegate;
365   EXPECT_CALL(delegate, OnGetTokenInfoResponsePtr(_))
366       .WillOnce(SaveArg<0>(&captured_result));
367
368   MockOAuthFetcherFactory factory;
369   factory.set_results(kDummyTokenInfoResult);
370
371   GaiaOAuthClient auth(GetRequestContext());
372   auth.GetTokenInfo("access_token", 1, &delegate);
373
374   std::string issued_to;
375   ASSERT_TRUE(captured_result->GetString("issued_to",  &issued_to));
376   ASSERT_EQ("1234567890.apps.googleusercontent.com", issued_to);
377 }
378
379 }  // namespace gaia