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_access_token_fetcher.h"
16 #include "google_apis/gaia/oauth2_mint_token_flow.h"
17 #include "net/url_request/test_url_fetcher_factory.h"
18 #include "net/url_request/url_request_status.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
22 using net::TestURLFetcher
;
23 using net::URLFetcher
;
24 using net::URLRequestStatus
;
26 using testing::StrictMock
;
30 static const char kValidTokenResponse
[] =
32 " \"token\": \"at1\","
33 " \"issueAdvice\": \"Auto\","
34 " \"expiresIn\": \"3600\""
36 static const char kTokenResponseNoAccessToken
[] =
38 " \"issueAdvice\": \"Auto\""
41 static const char kValidIssueAdviceResponse
[] =
43 " \"issueAdvice\": \"consent\","
46 " \"name\": \"Test app\","
48 " \"developerEmail\": \"munjal@chromium.org\""
52 " \"description\": \"Manage your calendars\","
53 " \"detail\": \"\nView and manage your calendars\n\""
56 " \"description\": \"Manage your documents\","
57 " \"detail\": \"\nView your documents\nUpload new documents\n\""
63 static const char kIssueAdviceResponseNoDescription
[] =
65 " \"issueAdvice\": \"consent\","
68 " \"name\": \"Test app\","
70 " \"developerEmail\": \"munjal@chromium.org\""
74 " \"description\": \"Manage your calendars\","
75 " \"detail\": \"\nView and manage your calendars\n\""
78 " \"detail\": \"\nView your documents\nUpload new documents\n\""
84 static const char kIssueAdviceResponseNoDetail
[] =
86 " \"issueAdvice\": \"consent\","
89 " \"name\": \"Test app\","
91 " \"developerEmail\": \"munjal@chromium.org\""
95 " \"description\": \"Manage your calendars\","
96 " \"detail\": \"\nView and manage your calendars\n\""
99 " \"description\": \"Manage your documents\""
105 std::vector
<std::string
> CreateTestScopes() {
106 std::vector
<std::string
> scopes
;
107 scopes
.push_back("http://scope1");
108 scopes
.push_back("http://scope2");
112 static IssueAdviceInfo
CreateIssueAdvice() {
114 IssueAdviceInfoEntry e1
;
115 e1
.description
= base::ASCIIToUTF16("Manage your calendars");
116 e1
.details
.push_back(base::ASCIIToUTF16("View and manage your calendars"));
118 IssueAdviceInfoEntry e2
;
119 e2
.description
= base::ASCIIToUTF16("Manage your documents");
120 e2
.details
.push_back(base::ASCIIToUTF16("View your documents"));
121 e2
.details
.push_back(base::ASCIIToUTF16("Upload new documents"));
126 class MockDelegate
: public OAuth2MintTokenFlow::Delegate
{
131 MOCK_METHOD2(OnMintTokenSuccess
, void(const std::string
& access_token
,
133 MOCK_METHOD1(OnIssueAdviceSuccess
,
134 void (const IssueAdviceInfo
& issue_advice
));
135 MOCK_METHOD1(OnMintTokenFailure
,
136 void(const GoogleServiceAuthError
& error
));
139 class MockMintTokenFlow
: public OAuth2MintTokenFlow
{
141 explicit MockMintTokenFlow(MockDelegate
* delegate
,
142 const OAuth2MintTokenFlow::Parameters
& parameters
)
143 : OAuth2MintTokenFlow(delegate
, parameters
) {}
144 ~MockMintTokenFlow() {}
146 MOCK_METHOD0(CreateAccessTokenFetcher
, OAuth2AccessTokenFetcher
*());
151 class OAuth2MintTokenFlowTest
: public testing::Test
{
153 OAuth2MintTokenFlowTest() {}
154 virtual ~OAuth2MintTokenFlowTest() { }
157 void CreateFlow(OAuth2MintTokenFlow::Mode mode
) {
158 return CreateFlow(&delegate_
, mode
, "");
161 void CreateFlowWithDeviceId(const std::string
& device_id
) {
162 return CreateFlow(&delegate_
, OAuth2MintTokenFlow::MODE_ISSUE_ADVICE
,
166 void CreateFlow(MockDelegate
* delegate
,
167 OAuth2MintTokenFlow::Mode mode
,
168 const std::string
& device_id
) {
169 std::string ext_id
= "ext1";
170 std::string client_id
= "client1";
171 std::vector
<std::string
> scopes(CreateTestScopes());
172 flow_
.reset(new MockMintTokenFlow(
173 delegate
, OAuth2MintTokenFlow::Parameters(ext_id
, client_id
, scopes
,
177 // Helper to parse the given string to DictionaryValue.
178 static base::DictionaryValue
* ParseJson(const std::string
& str
) {
179 scoped_ptr
<base::Value
> value
= base::JSONReader::Read(str
);
180 EXPECT_TRUE(value
.get());
181 EXPECT_EQ(base::Value::TYPE_DICTIONARY
, value
->GetType());
182 return static_cast<base::DictionaryValue
*>(value
.release());
185 scoped_ptr
<MockMintTokenFlow
> flow_
;
186 StrictMock
<MockDelegate
> delegate_
;
189 TEST_F(OAuth2MintTokenFlowTest
, CreateApiCallBody
) {
190 { // Issue advice mode.
191 CreateFlow(OAuth2MintTokenFlow::MODE_ISSUE_ADVICE
);
192 std::string body
= flow_
->CreateApiCallBody();
193 std::string
expected_body(
195 "&response_type=none"
196 "&scope=http://scope1+http://scope2"
199 EXPECT_EQ(expected_body
, body
);
201 { // Record grant mode.
202 CreateFlow(OAuth2MintTokenFlow::MODE_RECORD_GRANT
);
203 std::string body
= flow_
->CreateApiCallBody();
204 std::string
expected_body(
206 "&response_type=none"
207 "&scope=http://scope1+http://scope2"
210 EXPECT_EQ(expected_body
, body
);
212 { // Mint token no force mode.
213 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE
);
214 std::string body
= flow_
->CreateApiCallBody();
215 std::string
expected_body(
217 "&response_type=token"
218 "&scope=http://scope1+http://scope2"
221 EXPECT_EQ(expected_body
, body
);
223 { // Mint token force mode.
224 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_FORCE
);
225 std::string body
= flow_
->CreateApiCallBody();
226 std::string
expected_body(
228 "&response_type=token"
229 "&scope=http://scope1+http://scope2"
232 EXPECT_EQ(expected_body
, body
);
234 { // Mint token with device_id.
235 CreateFlowWithDeviceId("device_id1");
236 std::string body
= flow_
->CreateApiCallBody();
237 std::string
expected_body(
239 "&response_type=none"
240 "&scope=http://scope1+http://scope2"
243 "&device_id=device_id1"
244 "&device_type=chrome"
245 "&lib_ver=extension");
246 EXPECT_EQ(expected_body
, body
);
250 TEST_F(OAuth2MintTokenFlowTest
, ParseMintTokenResponse
) {
251 { // Access token missing.
252 scoped_ptr
<base::DictionaryValue
> json(
253 ParseJson(kTokenResponseNoAccessToken
));
256 EXPECT_FALSE(OAuth2MintTokenFlow::ParseMintTokenResponse(json
.get(), &at
,
258 EXPECT_TRUE(at
.empty());
261 scoped_ptr
<base::DictionaryValue
> json(ParseJson(kValidTokenResponse
));
264 EXPECT_TRUE(OAuth2MintTokenFlow::ParseMintTokenResponse(json
.get(), &at
,
266 EXPECT_EQ("at1", at
);
267 EXPECT_EQ(3600, ttl
);
271 TEST_F(OAuth2MintTokenFlowTest
, ParseIssueAdviceResponse
) {
272 { // Description missing.
273 scoped_ptr
<base::DictionaryValue
> json(
274 ParseJson(kIssueAdviceResponseNoDescription
));
276 EXPECT_FALSE(OAuth2MintTokenFlow::ParseIssueAdviceResponse(
278 EXPECT_TRUE(ia
.empty());
281 scoped_ptr
<base::DictionaryValue
> json(
282 ParseJson(kIssueAdviceResponseNoDetail
));
284 EXPECT_FALSE(OAuth2MintTokenFlow::ParseIssueAdviceResponse(
286 EXPECT_TRUE(ia
.empty());
289 scoped_ptr
<base::DictionaryValue
> json(
290 ParseJson(kValidIssueAdviceResponse
));
292 EXPECT_TRUE(OAuth2MintTokenFlow::ParseIssueAdviceResponse(
294 IssueAdviceInfo
ia_expected(CreateIssueAdvice());
295 EXPECT_EQ(ia_expected
, ia
);
299 TEST_F(OAuth2MintTokenFlowTest
, ProcessApiCallSuccess
) {
301 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
302 url_fetcher
.SetResponseString(std::string());
303 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE
);
304 EXPECT_CALL(delegate_
, OnMintTokenFailure(_
));
305 flow_
->ProcessApiCallSuccess(&url_fetcher
);
308 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
309 url_fetcher
.SetResponseString("foo");
310 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE
);
311 EXPECT_CALL(delegate_
, OnMintTokenFailure(_
));
312 flow_
->ProcessApiCallSuccess(&url_fetcher
);
314 { // Valid json: no access token.
315 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
316 url_fetcher
.SetResponseString(kTokenResponseNoAccessToken
);
317 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE
);
318 EXPECT_CALL(delegate_
, OnMintTokenFailure(_
));
319 flow_
->ProcessApiCallSuccess(&url_fetcher
);
321 { // Valid json: good token response.
322 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
323 url_fetcher
.SetResponseString(kValidTokenResponse
);
324 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE
);
325 EXPECT_CALL(delegate_
, OnMintTokenSuccess("at1", 3600));
326 flow_
->ProcessApiCallSuccess(&url_fetcher
);
328 { // Valid json: no description.
329 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
330 url_fetcher
.SetResponseString(kIssueAdviceResponseNoDescription
);
331 CreateFlow(OAuth2MintTokenFlow::MODE_ISSUE_ADVICE
);
332 EXPECT_CALL(delegate_
, OnMintTokenFailure(_
));
333 flow_
->ProcessApiCallSuccess(&url_fetcher
);
335 { // Valid json: no detail.
336 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
337 url_fetcher
.SetResponseString(kIssueAdviceResponseNoDetail
);
338 CreateFlow(OAuth2MintTokenFlow::MODE_ISSUE_ADVICE
);
339 EXPECT_CALL(delegate_
, OnMintTokenFailure(_
));
340 flow_
->ProcessApiCallSuccess(&url_fetcher
);
342 { // Valid json: good issue advice response.
343 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
344 url_fetcher
.SetResponseString(kValidIssueAdviceResponse
);
345 CreateFlow(OAuth2MintTokenFlow::MODE_ISSUE_ADVICE
);
346 IssueAdviceInfo
ia(CreateIssueAdvice());
347 EXPECT_CALL(delegate_
, OnIssueAdviceSuccess(ia
));
348 flow_
->ProcessApiCallSuccess(&url_fetcher
);
352 TEST_F(OAuth2MintTokenFlowTest
, ProcessApiCallFailure
) {
353 { // Null delegate should work fine.
354 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
355 url_fetcher
.set_status(URLRequestStatus(URLRequestStatus::FAILED
, 101));
356 CreateFlow(NULL
, OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE
, "");
357 flow_
->ProcessApiCallFailure(&url_fetcher
);
360 { // Non-null delegate.
361 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
362 url_fetcher
.set_status(URLRequestStatus(URLRequestStatus::FAILED
, 101));
363 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE
);
364 EXPECT_CALL(delegate_
, OnMintTokenFailure(_
));
365 flow_
->ProcessApiCallFailure(&url_fetcher
);