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