oauth2_api_call_flow_unittest.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
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 OAuth2MintTokenFlow.
6
7#include <string>
8#include <vector>
9
10#include "base/memory/scoped_ptr.h"
11#include "base/time.h"
12#include "chrome/test/base/testing_profile.h"
13#include "google_apis/gaia/gaia_urls.h"
14#include "google_apis/gaia/google_service_auth_error.h"
15#include "google_apis/gaia/oauth2_access_token_consumer.h"
16#include "google_apis/gaia/oauth2_access_token_fetcher.h"
17#include "google_apis/gaia/oauth2_api_call_flow.h"
18#include "net/http/http_request_headers.h"
19#include "net/http/http_status_code.h"
20#include "net/url_request/test_url_fetcher_factory.h"
21#include "net/url_request/url_fetcher.h"
22#include "net/url_request/url_fetcher_delegate.h"
23#include "net/url_request/url_fetcher_factory.h"
24#include "net/url_request/url_request.h"
25#include "net/url_request/url_request_status.h"
26#include "testing/gmock/include/gmock/gmock.h"
27#include "testing/gtest/include/gtest/gtest.h"
28
29using net::HttpRequestHeaders;
30using net::ScopedURLFetcherFactory;
31using net::TestURLFetcher;
32using net::URLFetcher;
33using net::URLFetcherDelegate;
34using net::URLFetcherFactory;
35using net::URLRequestStatus;
36using testing::_;
37using testing::Return;
38
39namespace {
40
41static std::string CreateBody() {
42  return "some body";
43}
44
45static GURL CreateApiUrl() {
46  return GURL("https://www.googleapis.com/someapi");
47}
48
49static std::vector<std::string> CreateTestScopes() {
50  std::vector<std::string> scopes;
51  scopes.push_back("scope1");
52  scopes.push_back("scope2");
53  return scopes;
54}
55
56class MockUrlFetcherFactory : public ScopedURLFetcherFactory,
57                              public URLFetcherFactory {
58 public:
59  MockUrlFetcherFactory()
60      : ScopedURLFetcherFactory(this) {
61  }
62  virtual ~MockUrlFetcherFactory() {}
63
64  MOCK_METHOD4(
65      CreateURLFetcher,
66      URLFetcher* (int id,
67                   const GURL& url,
68                   URLFetcher::RequestType request_type,
69                   URLFetcherDelegate* d));
70};
71
72class MockAccessTokenFetcher : public OAuth2AccessTokenFetcher {
73 public:
74  MockAccessTokenFetcher(OAuth2AccessTokenConsumer* consumer,
75                         net::URLRequestContextGetter* getter)
76      : OAuth2AccessTokenFetcher(consumer, getter) {}
77  ~MockAccessTokenFetcher() {}
78
79  MOCK_METHOD4(Start,
80               void (const std::string& client_id,
81                     const std::string& client_secret,
82                     const std::string& refresh_token,
83                     const std::vector<std::string>& scopes));
84};
85
86class MockApiCallFlow : public OAuth2ApiCallFlow {
87 public:
88  MockApiCallFlow(net::URLRequestContextGetter* context,
89                  const std::string& refresh_token,
90                  const std::string& access_token,
91                  const std::vector<std::string>& scopes)
92      : OAuth2ApiCallFlow(context, refresh_token, access_token, scopes) {}
93  ~MockApiCallFlow() {}
94
95  MOCK_METHOD0(CreateApiCallUrl, GURL ());
96  MOCK_METHOD0(CreateApiCallBody, std::string ());
97  MOCK_METHOD1(ProcessApiCallSuccess,
98      void (const URLFetcher* source));
99  MOCK_METHOD1(ProcessApiCallFailure,
100      void (const URLFetcher* source));
101  MOCK_METHOD1(ProcessNewAccessToken,
102      void (const std::string& access_token));
103  MOCK_METHOD1(ProcessMintAccessTokenFailure,
104      void (const GoogleServiceAuthError& error));
105  MOCK_METHOD0(CreateAccessTokenFetcher, OAuth2AccessTokenFetcher* ());
106};
107
108}  // namespace
109
110class OAuth2ApiCallFlowTest : public testing::Test {
111 public:
112  OAuth2ApiCallFlowTest() {}
113  virtual ~OAuth2ApiCallFlowTest() {}
114
115 protected:
116  void SetupAccessTokenFetcher(
117      const std::string& rt, const std::vector<std::string>& scopes) {
118    EXPECT_CALL(*access_token_fetcher_,
119        Start(GaiaUrls::GetInstance()->oauth2_chrome_client_id(),
120              GaiaUrls::GetInstance()->oauth2_chrome_client_secret(),
121              rt, scopes))
122        .Times(1);
123    EXPECT_CALL(*flow_, CreateAccessTokenFetcher())
124        .WillOnce(Return(access_token_fetcher_.release()));
125  }
126
127  TestURLFetcher* CreateURLFetcher(
128      const GURL& url, bool fetch_succeeds,
129      int response_code, const std::string& body) {
130    TestURLFetcher* url_fetcher = new TestURLFetcher(0, url, flow_.get());
131    URLRequestStatus::Status status =
132        fetch_succeeds ? URLRequestStatus::SUCCESS : URLRequestStatus::FAILED;
133    url_fetcher->set_status(URLRequestStatus(status, 0));
134
135    if (response_code != 0)
136      url_fetcher->set_response_code(response_code);
137
138    if (!body.empty())
139      url_fetcher->SetResponseString(body);
140
141    return url_fetcher;
142  }
143
144  void CreateFlow(const std::string& refresh_token,
145                  const std::string& access_token,
146                  const std::vector<std::string>& scopes) {
147    flow_.reset(new MockApiCallFlow(
148        profile_.GetRequestContext(),
149        refresh_token,
150        access_token,
151        scopes));
152    access_token_fetcher_.reset(new MockAccessTokenFetcher(
153        flow_.get(), profile_.GetRequestContext()));
154  }
155
156  TestURLFetcher* SetupApiCall(bool succeeds, net::HttpStatusCode status) {
157    std::string body(CreateBody());
158    GURL url(CreateApiUrl());
159    EXPECT_CALL(*flow_, CreateApiCallBody()).WillOnce(Return(body));
160    EXPECT_CALL(*flow_, CreateApiCallUrl()).WillOnce(Return(url));
161    TestURLFetcher* url_fetcher =
162        CreateURLFetcher(url, succeeds, status, std::string());
163    EXPECT_CALL(factory_, CreateURLFetcher(_, url, _, _))
164        .WillOnce(Return(url_fetcher));
165    return url_fetcher;
166  }
167
168  MockUrlFetcherFactory factory_;
169  scoped_ptr<MockApiCallFlow> flow_;
170  scoped_ptr<MockAccessTokenFetcher> access_token_fetcher_;
171  TestingProfile profile_;
172};
173
174TEST_F(OAuth2ApiCallFlowTest, FirstApiCallSucceeds) {
175  std::string rt = "refresh_token";
176  std::string at = "access_token";
177  std::vector<std::string> scopes(CreateTestScopes());
178
179  CreateFlow(rt, at, scopes);
180  TestURLFetcher* url_fetcher = SetupApiCall(true, net::HTTP_OK);
181  EXPECT_CALL(*flow_, ProcessApiCallSuccess(url_fetcher));
182  flow_->Start();
183  flow_->OnURLFetchComplete(url_fetcher);
184}
185
186TEST_F(OAuth2ApiCallFlowTest, SecondApiCallSucceeds) {
187  std::string rt = "refresh_token";
188  std::string at = "access_token";
189  std::vector<std::string> scopes(CreateTestScopes());
190
191  CreateFlow(rt, at, scopes);
192  TestURLFetcher* url_fetcher1 = SetupApiCall(true, net::HTTP_UNAUTHORIZED);
193  flow_->Start();
194  SetupAccessTokenFetcher(rt, scopes);
195  flow_->OnURLFetchComplete(url_fetcher1);
196  TestURLFetcher* url_fetcher2 = SetupApiCall(true, net::HTTP_OK);
197  EXPECT_CALL(*flow_, ProcessApiCallSuccess(url_fetcher2));
198  flow_->OnGetTokenSuccess(
199      at,
200      base::Time::Now() + base::TimeDelta::FromMinutes(3600));
201  flow_->OnURLFetchComplete(url_fetcher2);
202}
203
204TEST_F(OAuth2ApiCallFlowTest, SecondApiCallFails) {
205  std::string rt = "refresh_token";
206  std::string at = "access_token";
207  std::vector<std::string> scopes(CreateTestScopes());
208
209  CreateFlow(rt, at, scopes);
210  TestURLFetcher* url_fetcher1 = SetupApiCall(true, net::HTTP_UNAUTHORIZED);
211  flow_->Start();
212  SetupAccessTokenFetcher(rt, scopes);
213  flow_->OnURLFetchComplete(url_fetcher1);
214  TestURLFetcher* url_fetcher2 = SetupApiCall(false, net::HTTP_UNAUTHORIZED);
215  EXPECT_CALL(*flow_, ProcessApiCallFailure(url_fetcher2));
216  flow_->OnGetTokenSuccess(
217      at,
218      base::Time::Now() + base::TimeDelta::FromMinutes(3600));
219  flow_->OnURLFetchComplete(url_fetcher2);
220}
221
222TEST_F(OAuth2ApiCallFlowTest, NewTokenGenerationFails) {
223  std::string rt = "refresh_token";
224  std::string at = "access_token";
225  std::vector<std::string> scopes(CreateTestScopes());
226
227  CreateFlow(rt, at, scopes);
228  TestURLFetcher* url_fetcher = SetupApiCall(true, net::HTTP_UNAUTHORIZED);
229  flow_->Start();
230  SetupAccessTokenFetcher(rt, scopes);
231  flow_->OnURLFetchComplete(url_fetcher);
232  GoogleServiceAuthError error(
233      GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
234  EXPECT_CALL(*flow_, ProcessMintAccessTokenFailure(error));
235  flow_->OnGetTokenFailure(error);
236}
237
238TEST_F(OAuth2ApiCallFlowTest, EmptyAccessTokenFirstApiCallSucceeds) {
239  std::string rt = "refresh_token";
240  std::string at = "access_token";
241  std::vector<std::string> scopes(CreateTestScopes());
242
243  CreateFlow(rt, std::string(), scopes);
244  SetupAccessTokenFetcher(rt, scopes);
245  TestURLFetcher* url_fetcher = SetupApiCall(true, net::HTTP_OK);
246  EXPECT_CALL(*flow_, ProcessApiCallSuccess(url_fetcher));
247  flow_->Start();
248  flow_->OnGetTokenSuccess(
249      at,
250      base::Time::Now() + base::TimeDelta::FromMinutes(3600));
251  flow_->OnURLFetchComplete(url_fetcher);
252}
253
254TEST_F(OAuth2ApiCallFlowTest, EmptyAccessTokenApiCallFails) {
255  std::string rt = "refresh_token";
256  std::string at = "access_token";
257  std::vector<std::string> scopes(CreateTestScopes());
258
259  CreateFlow(rt, std::string(), scopes);
260  SetupAccessTokenFetcher(rt, scopes);
261  TestURLFetcher* url_fetcher = SetupApiCall(false, net::HTTP_BAD_GATEWAY);
262  EXPECT_CALL(*flow_, ProcessApiCallFailure(url_fetcher));
263  flow_->Start();
264  flow_->OnGetTokenSuccess(
265      at,
266      base::Time::Now() + base::TimeDelta::FromMinutes(3600));
267  flow_->OnURLFetchComplete(url_fetcher);
268}
269
270TEST_F(OAuth2ApiCallFlowTest, EmptyAccessTokenNewTokenGenerationFails) {
271  std::string rt = "refresh_token";
272  std::string at = "access_token";
273  std::vector<std::string> scopes(CreateTestScopes());
274
275  CreateFlow(rt, std::string(), scopes);
276  SetupAccessTokenFetcher(rt, scopes);
277  GoogleServiceAuthError error(
278      GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
279  EXPECT_CALL(*flow_, ProcessMintAccessTokenFailure(error));
280  flow_->Start();
281  flow_->OnGetTokenFailure(error);
282}
283
284TEST_F(OAuth2ApiCallFlowTest, CreateURLFetcher) {
285  std::string rt = "refresh_token";
286  std::string at = "access_token";
287  std::vector<std::string> scopes(CreateTestScopes());
288  std::string body = CreateBody();
289  GURL url(CreateApiUrl());
290
291  CreateFlow(rt, at, scopes);
292  scoped_ptr<TestURLFetcher> url_fetcher(SetupApiCall(true, net::HTTP_OK));
293  flow_->CreateURLFetcher();
294  HttpRequestHeaders headers;
295  url_fetcher->GetExtraRequestHeaders(&headers);
296  std::string auth_header;
297  EXPECT_TRUE(headers.GetHeader("Authorization", &auth_header));
298  EXPECT_EQ("Bearer access_token", auth_header);
299  EXPECT_EQ(url, url_fetcher->GetOriginalURL());
300  EXPECT_EQ(body, url_fetcher->upload_data());
301}
302