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.
5 // A complete set of unit tests for OAuth2MintTokenFlow.
10 #include "base/json/json_reader.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/values.h"
14 #include "google_apis/gaia/google_service_auth_error.h"
15 #include "google_apis/gaia/oauth2_mint_token_flow.h"
16 #include "net/url_request/test_url_fetcher_factory.h"
17 #include "net/url_request/url_request_status.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/gtest/include/gtest/gtest.h"
21 using net::TestURLFetcher
;
22 using net::URLFetcher
;
23 using net::URLRequestStatus
;
25 using testing::StrictMock
;
29 static const char kValidTokenResponse
[] =
31 " \"token\": \"at1\","
32 " \"issueAdvice\": \"Auto\","
33 " \"expiresIn\": \"3600\""
35 static const char kTokenResponseNoAccessToken
[] =
37 " \"issueAdvice\": \"Auto\""
40 static const char kValidIssueAdviceResponse
[] =
42 " \"issueAdvice\": \"consent\","
45 " \"name\": \"Test app\","
47 " \"developerEmail\": \"munjal@chromium.org\""
51 " \"description\": \"Manage your calendars\","
52 " \"detail\": \"\nView and manage your calendars\n\""
55 " \"description\": \"Manage your documents\","
56 " \"detail\": \"\nView your documents\nUpload new documents\n\""
62 static const char kIssueAdviceResponseNoDescription
[] =
64 " \"issueAdvice\": \"consent\","
67 " \"name\": \"Test app\","
69 " \"developerEmail\": \"munjal@chromium.org\""
73 " \"description\": \"Manage your calendars\","
74 " \"detail\": \"\nView and manage your calendars\n\""
77 " \"detail\": \"\nView your documents\nUpload new documents\n\""
83 static const char kIssueAdviceResponseNoDetail
[] =
85 " \"issueAdvice\": \"consent\","
88 " \"name\": \"Test app\","
90 " \"developerEmail\": \"munjal@chromium.org\""
94 " \"description\": \"Manage your calendars\","
95 " \"detail\": \"\nView and manage your calendars\n\""
98 " \"description\": \"Manage your documents\""
104 std::vector
<std::string
> CreateTestScopes() {
105 std::vector
<std::string
> scopes
;
106 scopes
.push_back("http://scope1");
107 scopes
.push_back("http://scope2");
111 static IssueAdviceInfo
CreateIssueAdvice() {
113 IssueAdviceInfoEntry e1
;
114 e1
.description
= base::ASCIIToUTF16("Manage your calendars");
115 e1
.details
.push_back(base::ASCIIToUTF16("View and manage your calendars"));
117 IssueAdviceInfoEntry e2
;
118 e2
.description
= base::ASCIIToUTF16("Manage your documents");
119 e2
.details
.push_back(base::ASCIIToUTF16("View your documents"));
120 e2
.details
.push_back(base::ASCIIToUTF16("Upload new documents"));
125 class MockDelegate
: public OAuth2MintTokenFlow::Delegate
{
130 MOCK_METHOD2(OnMintTokenSuccess
, void(const std::string
& access_token
,
132 MOCK_METHOD1(OnIssueAdviceSuccess
,
133 void (const IssueAdviceInfo
& issue_advice
));
134 MOCK_METHOD1(OnMintTokenFailure
,
135 void(const GoogleServiceAuthError
& error
));
138 class MockMintTokenFlow
: public OAuth2MintTokenFlow
{
140 explicit MockMintTokenFlow(MockDelegate
* delegate
,
141 const OAuth2MintTokenFlow::Parameters
& parameters
)
142 : OAuth2MintTokenFlow(NULL
, delegate
, parameters
) {}
143 ~MockMintTokenFlow() {}
145 MOCK_METHOD0(CreateAccessTokenFetcher
, OAuth2AccessTokenFetcher
*());
150 class OAuth2MintTokenFlowTest
: public testing::Test
{
152 OAuth2MintTokenFlowTest() {}
153 virtual ~OAuth2MintTokenFlowTest() { }
156 void CreateFlow(OAuth2MintTokenFlow::Mode mode
) {
157 return CreateFlow(&delegate_
, mode
);
160 void CreateFlow(MockDelegate
* delegate
,
161 OAuth2MintTokenFlow::Mode mode
) {
162 std::string rt
= "refresh_token";
163 std::string ext_id
= "ext1";
164 std::string client_id
= "client1";
165 std::vector
<std::string
> scopes(CreateTestScopes());
166 flow_
.reset(new MockMintTokenFlow(
168 OAuth2MintTokenFlow::Parameters(rt
, ext_id
, client_id
, scopes
, mode
)));
171 // Helper to parse the given string to DictionaryValue.
172 static base::DictionaryValue
* ParseJson(const std::string
& str
) {
173 scoped_ptr
<base::Value
> value(base::JSONReader::Read(str
));
174 EXPECT_TRUE(value
.get());
175 EXPECT_EQ(base::Value::TYPE_DICTIONARY
, value
->GetType());
176 return static_cast<base::DictionaryValue
*>(value
.release());
179 scoped_ptr
<MockMintTokenFlow
> flow_
;
180 StrictMock
<MockDelegate
> delegate_
;
183 TEST_F(OAuth2MintTokenFlowTest
, CreateApiCallBody
) {
184 { // Issue advice mode.
185 CreateFlow(OAuth2MintTokenFlow::MODE_ISSUE_ADVICE
);
186 std::string body
= flow_
->CreateApiCallBody();
187 std::string
expected_body(
189 "&response_type=none"
190 "&scope=http://scope1+http://scope2"
193 EXPECT_EQ(expected_body
, body
);
195 { // Record grant mode.
196 CreateFlow(OAuth2MintTokenFlow::MODE_RECORD_GRANT
);
197 std::string body
= flow_
->CreateApiCallBody();
198 std::string
expected_body(
200 "&response_type=none"
201 "&scope=http://scope1+http://scope2"
204 EXPECT_EQ(expected_body
, body
);
206 { // Mint token no force mode.
207 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE
);
208 std::string body
= flow_
->CreateApiCallBody();
209 std::string
expected_body(
211 "&response_type=token"
212 "&scope=http://scope1+http://scope2"
215 EXPECT_EQ(expected_body
, body
);
217 { // Mint token force mode.
218 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_FORCE
);
219 std::string body
= flow_
->CreateApiCallBody();
220 std::string
expected_body(
222 "&response_type=token"
223 "&scope=http://scope1+http://scope2"
226 EXPECT_EQ(expected_body
, body
);
230 TEST_F(OAuth2MintTokenFlowTest
, ParseMintTokenResponse
) {
231 { // Access token missing.
232 scoped_ptr
<base::DictionaryValue
> json(
233 ParseJson(kTokenResponseNoAccessToken
));
236 EXPECT_FALSE(OAuth2MintTokenFlow::ParseMintTokenResponse(json
.get(), &at
,
238 EXPECT_TRUE(at
.empty());
241 scoped_ptr
<base::DictionaryValue
> json(ParseJson(kValidTokenResponse
));
244 EXPECT_TRUE(OAuth2MintTokenFlow::ParseMintTokenResponse(json
.get(), &at
,
246 EXPECT_EQ("at1", at
);
247 EXPECT_EQ(3600, ttl
);
251 TEST_F(OAuth2MintTokenFlowTest
, ParseIssueAdviceResponse
) {
252 { // Description missing.
253 scoped_ptr
<base::DictionaryValue
> json(
254 ParseJson(kIssueAdviceResponseNoDescription
));
256 EXPECT_FALSE(OAuth2MintTokenFlow::ParseIssueAdviceResponse(
258 EXPECT_TRUE(ia
.empty());
261 scoped_ptr
<base::DictionaryValue
> json(
262 ParseJson(kIssueAdviceResponseNoDetail
));
264 EXPECT_FALSE(OAuth2MintTokenFlow::ParseIssueAdviceResponse(
266 EXPECT_TRUE(ia
.empty());
269 scoped_ptr
<base::DictionaryValue
> json(
270 ParseJson(kValidIssueAdviceResponse
));
272 EXPECT_TRUE(OAuth2MintTokenFlow::ParseIssueAdviceResponse(
274 IssueAdviceInfo
ia_expected(CreateIssueAdvice());
275 EXPECT_EQ(ia_expected
, ia
);
279 TEST_F(OAuth2MintTokenFlowTest
, ProcessApiCallSuccess
) {
281 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
282 url_fetcher
.SetResponseString(std::string());
283 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE
);
284 EXPECT_CALL(delegate_
, OnMintTokenFailure(_
));
285 flow_
->ProcessApiCallSuccess(&url_fetcher
);
288 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
289 url_fetcher
.SetResponseString("foo");
290 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE
);
291 EXPECT_CALL(delegate_
, OnMintTokenFailure(_
));
292 flow_
->ProcessApiCallSuccess(&url_fetcher
);
294 { // Valid json: no access token.
295 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
296 url_fetcher
.SetResponseString(kTokenResponseNoAccessToken
);
297 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE
);
298 EXPECT_CALL(delegate_
, OnMintTokenFailure(_
));
299 flow_
->ProcessApiCallSuccess(&url_fetcher
);
301 { // Valid json: good token response.
302 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
303 url_fetcher
.SetResponseString(kValidTokenResponse
);
304 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE
);
305 EXPECT_CALL(delegate_
, OnMintTokenSuccess("at1", 3600));
306 flow_
->ProcessApiCallSuccess(&url_fetcher
);
308 { // Valid json: no description.
309 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
310 url_fetcher
.SetResponseString(kIssueAdviceResponseNoDescription
);
311 CreateFlow(OAuth2MintTokenFlow::MODE_ISSUE_ADVICE
);
312 EXPECT_CALL(delegate_
, OnMintTokenFailure(_
));
313 flow_
->ProcessApiCallSuccess(&url_fetcher
);
315 { // Valid json: no detail.
316 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
317 url_fetcher
.SetResponseString(kIssueAdviceResponseNoDetail
);
318 CreateFlow(OAuth2MintTokenFlow::MODE_ISSUE_ADVICE
);
319 EXPECT_CALL(delegate_
, OnMintTokenFailure(_
));
320 flow_
->ProcessApiCallSuccess(&url_fetcher
);
322 { // Valid json: good issue advice response.
323 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
324 url_fetcher
.SetResponseString(kValidIssueAdviceResponse
);
325 CreateFlow(OAuth2MintTokenFlow::MODE_ISSUE_ADVICE
);
326 IssueAdviceInfo
ia(CreateIssueAdvice());
327 EXPECT_CALL(delegate_
, OnIssueAdviceSuccess(ia
));
328 flow_
->ProcessApiCallSuccess(&url_fetcher
);
332 TEST_F(OAuth2MintTokenFlowTest
, ProcessApiCallFailure
) {
333 { // Null delegate should work fine.
334 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
335 url_fetcher
.set_status(URLRequestStatus(URLRequestStatus::FAILED
, 101));
336 CreateFlow(NULL
, OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE
);
337 flow_
->ProcessApiCallFailure(&url_fetcher
);
340 { // Non-null delegate.
341 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
342 url_fetcher
.set_status(URLRequestStatus(URLRequestStatus::FAILED
, 101));
343 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE
);
344 EXPECT_CALL(delegate_
, OnMintTokenFailure(_
));
345 flow_
->ProcessApiCallFailure(&url_fetcher
);
349 TEST_F(OAuth2MintTokenFlowTest
, ProcessMintAccessTokenFailure
) {
350 { // Null delegate should work fine.
351 GoogleServiceAuthError
error(
352 GoogleServiceAuthError::FromConnectionError(101));
353 CreateFlow(NULL
, OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE
);
354 flow_
->ProcessMintAccessTokenFailure(error
);
357 { // Non-null delegate.
358 GoogleServiceAuthError
error(
359 GoogleServiceAuthError::FromConnectionError(101));
360 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE
);
361 EXPECT_CALL(delegate_
, OnMintTokenFailure(error
));
362 flow_
->ProcessMintAccessTokenFailure(error
);