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(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 CreateFlowWithDeviceId(const std::string
& device_id
) {
161 return CreateFlow(&delegate_
, OAuth2MintTokenFlow::MODE_ISSUE_ADVICE
,
165 void CreateFlow(MockDelegate
* delegate
,
166 OAuth2MintTokenFlow::Mode mode
,
167 const std::string
& device_id
) {
168 std::string ext_id
= "ext1";
169 std::string client_id
= "client1";
170 std::vector
<std::string
> scopes(CreateTestScopes());
171 flow_
.reset(new MockMintTokenFlow(
172 delegate
, OAuth2MintTokenFlow::Parameters(ext_id
, client_id
, scopes
,
176 // Helper to parse the given string to DictionaryValue.
177 static base::DictionaryValue
* ParseJson(const std::string
& str
) {
178 scoped_ptr
<base::Value
> value(base::JSONReader::Read(str
));
179 EXPECT_TRUE(value
.get());
180 EXPECT_EQ(base::Value::TYPE_DICTIONARY
, value
->GetType());
181 return static_cast<base::DictionaryValue
*>(value
.release());
184 scoped_ptr
<MockMintTokenFlow
> flow_
;
185 StrictMock
<MockDelegate
> delegate_
;
188 TEST_F(OAuth2MintTokenFlowTest
, CreateApiCallBody
) {
189 { // Issue advice mode.
190 CreateFlow(OAuth2MintTokenFlow::MODE_ISSUE_ADVICE
);
191 std::string body
= flow_
->CreateApiCallBody();
192 std::string
expected_body(
194 "&response_type=none"
195 "&scope=http://scope1+http://scope2"
198 EXPECT_EQ(expected_body
, body
);
200 { // Record grant mode.
201 CreateFlow(OAuth2MintTokenFlow::MODE_RECORD_GRANT
);
202 std::string body
= flow_
->CreateApiCallBody();
203 std::string
expected_body(
205 "&response_type=none"
206 "&scope=http://scope1+http://scope2"
209 EXPECT_EQ(expected_body
, body
);
211 { // Mint token no force mode.
212 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE
);
213 std::string body
= flow_
->CreateApiCallBody();
214 std::string
expected_body(
216 "&response_type=token"
217 "&scope=http://scope1+http://scope2"
220 EXPECT_EQ(expected_body
, body
);
222 { // Mint token force mode.
223 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_FORCE
);
224 std::string body
= flow_
->CreateApiCallBody();
225 std::string
expected_body(
227 "&response_type=token"
228 "&scope=http://scope1+http://scope2"
231 EXPECT_EQ(expected_body
, body
);
233 { // Mint token with device_id.
234 CreateFlowWithDeviceId("device_id1");
235 std::string body
= flow_
->CreateApiCallBody();
236 std::string
expected_body(
238 "&response_type=none"
239 "&scope=http://scope1+http://scope2"
242 "&device_id=device_id1"
243 "&device_type=chrome");
244 EXPECT_EQ(expected_body
, body
);
248 TEST_F(OAuth2MintTokenFlowTest
, ParseMintTokenResponse
) {
249 { // Access token missing.
250 scoped_ptr
<base::DictionaryValue
> json(
251 ParseJson(kTokenResponseNoAccessToken
));
254 EXPECT_FALSE(OAuth2MintTokenFlow::ParseMintTokenResponse(json
.get(), &at
,
256 EXPECT_TRUE(at
.empty());
259 scoped_ptr
<base::DictionaryValue
> json(ParseJson(kValidTokenResponse
));
262 EXPECT_TRUE(OAuth2MintTokenFlow::ParseMintTokenResponse(json
.get(), &at
,
264 EXPECT_EQ("at1", at
);
265 EXPECT_EQ(3600, ttl
);
269 TEST_F(OAuth2MintTokenFlowTest
, ParseIssueAdviceResponse
) {
270 { // Description missing.
271 scoped_ptr
<base::DictionaryValue
> json(
272 ParseJson(kIssueAdviceResponseNoDescription
));
274 EXPECT_FALSE(OAuth2MintTokenFlow::ParseIssueAdviceResponse(
276 EXPECT_TRUE(ia
.empty());
279 scoped_ptr
<base::DictionaryValue
> json(
280 ParseJson(kIssueAdviceResponseNoDetail
));
282 EXPECT_FALSE(OAuth2MintTokenFlow::ParseIssueAdviceResponse(
284 EXPECT_TRUE(ia
.empty());
287 scoped_ptr
<base::DictionaryValue
> json(
288 ParseJson(kValidIssueAdviceResponse
));
290 EXPECT_TRUE(OAuth2MintTokenFlow::ParseIssueAdviceResponse(
292 IssueAdviceInfo
ia_expected(CreateIssueAdvice());
293 EXPECT_EQ(ia_expected
, ia
);
297 TEST_F(OAuth2MintTokenFlowTest
, ProcessApiCallSuccess
) {
299 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
300 url_fetcher
.SetResponseString(std::string());
301 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE
);
302 EXPECT_CALL(delegate_
, OnMintTokenFailure(_
));
303 flow_
->ProcessApiCallSuccess(&url_fetcher
);
306 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
307 url_fetcher
.SetResponseString("foo");
308 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE
);
309 EXPECT_CALL(delegate_
, OnMintTokenFailure(_
));
310 flow_
->ProcessApiCallSuccess(&url_fetcher
);
312 { // Valid json: no access token.
313 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
314 url_fetcher
.SetResponseString(kTokenResponseNoAccessToken
);
315 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE
);
316 EXPECT_CALL(delegate_
, OnMintTokenFailure(_
));
317 flow_
->ProcessApiCallSuccess(&url_fetcher
);
319 { // Valid json: good token response.
320 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
321 url_fetcher
.SetResponseString(kValidTokenResponse
);
322 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE
);
323 EXPECT_CALL(delegate_
, OnMintTokenSuccess("at1", 3600));
324 flow_
->ProcessApiCallSuccess(&url_fetcher
);
326 { // Valid json: no description.
327 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
328 url_fetcher
.SetResponseString(kIssueAdviceResponseNoDescription
);
329 CreateFlow(OAuth2MintTokenFlow::MODE_ISSUE_ADVICE
);
330 EXPECT_CALL(delegate_
, OnMintTokenFailure(_
));
331 flow_
->ProcessApiCallSuccess(&url_fetcher
);
333 { // Valid json: no detail.
334 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
335 url_fetcher
.SetResponseString(kIssueAdviceResponseNoDetail
);
336 CreateFlow(OAuth2MintTokenFlow::MODE_ISSUE_ADVICE
);
337 EXPECT_CALL(delegate_
, OnMintTokenFailure(_
));
338 flow_
->ProcessApiCallSuccess(&url_fetcher
);
340 { // Valid json: good issue advice response.
341 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
342 url_fetcher
.SetResponseString(kValidIssueAdviceResponse
);
343 CreateFlow(OAuth2MintTokenFlow::MODE_ISSUE_ADVICE
);
344 IssueAdviceInfo
ia(CreateIssueAdvice());
345 EXPECT_CALL(delegate_
, OnIssueAdviceSuccess(ia
));
346 flow_
->ProcessApiCallSuccess(&url_fetcher
);
350 TEST_F(OAuth2MintTokenFlowTest
, ProcessApiCallFailure
) {
351 { // Null delegate should work fine.
352 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
353 url_fetcher
.set_status(URLRequestStatus(URLRequestStatus::FAILED
, 101));
354 CreateFlow(NULL
, OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE
, "");
355 flow_
->ProcessApiCallFailure(&url_fetcher
);
358 { // Non-null delegate.
359 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
360 url_fetcher
.set_status(URLRequestStatus(URLRequestStatus::FAILED
, 101));
361 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE
);
362 EXPECT_CALL(delegate_
, OnMintTokenFailure(_
));
363 flow_
->ProcessApiCallFailure(&url_fetcher
);