oauth2_access_token_fetcher_impl_unittest.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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
27using net::ResponseCookies;
28using net::ScopedURLFetcherFactory;
29using net::TestURLFetcher;
30using net::URLFetcher;
31using net::URLFetcherDelegate;
32using net::URLFetcherFactory;
33using net::URLRequestStatus;
34using testing::_;
35using testing::Return;
36
37namespace {
38
39typedef std::vector<std::string> ScopeList;
40
41static const char kValidTokenResponse[] =
42    "{"
43    "  \"access_token\": \"at1\","
44    "  \"expires_in\": 3600,"
45    "  \"token_type\": \"Bearer\""
46    "}";
47static const char kTokenResponseNoAccessToken[] =
48    "{"
49    "  \"expires_in\": 3600,"
50    "  \"token_type\": \"Bearer\""
51    "}";
52
53static const char kValidFailureTokenResponse[] =
54    "{"
55    "  \"error\": \"invalid_grant\""
56    "}";
57
58class 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
71class 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
84class 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.
124TEST_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
132TEST_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
141TEST_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
149TEST_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)
200TEST_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