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/base/net_errors.h"
18 #include "net/url_request/test_url_fetcher_factory.h"
19 #include "net/url_request/url_request_status.h"
20 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gtest/include/gtest/gtest.h"
23 using net::TestURLFetcher
;
24 using net::URLFetcher
;
25 using net::URLRequestStatus
;
27 using testing::StrictMock
;
31 static const char kValidTokenResponse
[] =
33 " \"token\": \"at1\","
34 " \"issueAdvice\": \"Auto\","
35 " \"expiresIn\": \"3600\""
37 static const char kTokenResponseNoAccessToken
[] =
39 " \"issueAdvice\": \"Auto\""
42 static const char kValidIssueAdviceResponse
[] =
44 " \"issueAdvice\": \"consent\","
47 " \"name\": \"Test app\","
49 " \"developerEmail\": \"munjal@chromium.org\""
53 " \"description\": \"Manage your calendars\","
54 " \"detail\": \"\nView and manage your calendars\n\""
57 " \"description\": \"Manage your documents\","
58 " \"detail\": \"\nView your documents\nUpload new documents\n\""
64 static const char kIssueAdviceResponseNoDescription
[] =
66 " \"issueAdvice\": \"consent\","
69 " \"name\": \"Test app\","
71 " \"developerEmail\": \"munjal@chromium.org\""
75 " \"description\": \"Manage your calendars\","
76 " \"detail\": \"\nView and manage your calendars\n\""
79 " \"detail\": \"\nView your documents\nUpload new documents\n\""
85 static const char kIssueAdviceResponseNoDetail
[] =
87 " \"issueAdvice\": \"consent\","
90 " \"name\": \"Test app\","
92 " \"developerEmail\": \"munjal@chromium.org\""
96 " \"description\": \"Manage your calendars\","
97 " \"detail\": \"\nView and manage your calendars\n\""
100 " \"description\": \"Manage your documents\""
106 std::vector
<std::string
> CreateTestScopes() {
107 std::vector
<std::string
> scopes
;
108 scopes
.push_back("http://scope1");
109 scopes
.push_back("http://scope2");
113 static IssueAdviceInfo
CreateIssueAdvice() {
115 IssueAdviceInfoEntry e1
;
116 e1
.description
= base::ASCIIToUTF16("Manage your calendars");
117 e1
.details
.push_back(base::ASCIIToUTF16("View and manage your calendars"));
119 IssueAdviceInfoEntry e2
;
120 e2
.description
= base::ASCIIToUTF16("Manage your documents");
121 e2
.details
.push_back(base::ASCIIToUTF16("View your documents"));
122 e2
.details
.push_back(base::ASCIIToUTF16("Upload new documents"));
127 class MockDelegate
: public OAuth2MintTokenFlow::Delegate
{
132 MOCK_METHOD2(OnMintTokenSuccess
, void(const std::string
& access_token
,
134 MOCK_METHOD1(OnIssueAdviceSuccess
,
135 void (const IssueAdviceInfo
& issue_advice
));
136 MOCK_METHOD1(OnMintTokenFailure
,
137 void(const GoogleServiceAuthError
& error
));
140 class MockMintTokenFlow
: public OAuth2MintTokenFlow
{
142 explicit MockMintTokenFlow(MockDelegate
* delegate
,
143 const OAuth2MintTokenFlow::Parameters
& parameters
)
144 : OAuth2MintTokenFlow(delegate
, parameters
) {}
145 ~MockMintTokenFlow() {}
147 MOCK_METHOD0(CreateAccessTokenFetcher
, OAuth2AccessTokenFetcher
*());
152 class OAuth2MintTokenFlowTest
: public testing::Test
{
154 OAuth2MintTokenFlowTest() {}
155 virtual ~OAuth2MintTokenFlowTest() { }
158 void CreateFlow(OAuth2MintTokenFlow::Mode mode
) {
159 return CreateFlow(&delegate_
, mode
, "");
162 void CreateFlowWithDeviceId(const std::string
& device_id
) {
163 return CreateFlow(&delegate_
, OAuth2MintTokenFlow::MODE_ISSUE_ADVICE
,
167 void CreateFlow(MockDelegate
* delegate
,
168 OAuth2MintTokenFlow::Mode mode
,
169 const std::string
& device_id
) {
170 std::string ext_id
= "ext1";
171 std::string client_id
= "client1";
172 std::vector
<std::string
> scopes(CreateTestScopes());
173 flow_
.reset(new MockMintTokenFlow(
174 delegate
, OAuth2MintTokenFlow::Parameters(ext_id
, client_id
, scopes
,
178 // Helper to parse the given string to DictionaryValue.
179 static base::DictionaryValue
* ParseJson(const std::string
& str
) {
180 scoped_ptr
<base::Value
> value
= base::JSONReader::Read(str
);
181 EXPECT_TRUE(value
.get());
182 EXPECT_EQ(base::Value::TYPE_DICTIONARY
, value
->GetType());
183 return static_cast<base::DictionaryValue
*>(value
.release());
186 scoped_ptr
<MockMintTokenFlow
> flow_
;
187 StrictMock
<MockDelegate
> delegate_
;
190 TEST_F(OAuth2MintTokenFlowTest
, CreateApiCallBody
) {
191 { // Issue advice mode.
192 CreateFlow(OAuth2MintTokenFlow::MODE_ISSUE_ADVICE
);
193 std::string body
= flow_
->CreateApiCallBody();
194 std::string
expected_body(
196 "&response_type=none"
197 "&scope=http://scope1+http://scope2"
200 EXPECT_EQ(expected_body
, body
);
202 { // Record grant mode.
203 CreateFlow(OAuth2MintTokenFlow::MODE_RECORD_GRANT
);
204 std::string body
= flow_
->CreateApiCallBody();
205 std::string
expected_body(
207 "&response_type=none"
208 "&scope=http://scope1+http://scope2"
211 EXPECT_EQ(expected_body
, body
);
213 { // Mint token no force mode.
214 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE
);
215 std::string body
= flow_
->CreateApiCallBody();
216 std::string
expected_body(
218 "&response_type=token"
219 "&scope=http://scope1+http://scope2"
222 EXPECT_EQ(expected_body
, body
);
224 { // Mint token force mode.
225 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_FORCE
);
226 std::string body
= flow_
->CreateApiCallBody();
227 std::string
expected_body(
229 "&response_type=token"
230 "&scope=http://scope1+http://scope2"
233 EXPECT_EQ(expected_body
, body
);
235 { // Mint token with device_id.
236 CreateFlowWithDeviceId("device_id1");
237 std::string body
= flow_
->CreateApiCallBody();
238 std::string
expected_body(
240 "&response_type=none"
241 "&scope=http://scope1+http://scope2"
244 "&device_id=device_id1"
245 "&device_type=chrome"
246 "&lib_ver=extension");
247 EXPECT_EQ(expected_body
, body
);
251 TEST_F(OAuth2MintTokenFlowTest
, ParseMintTokenResponse
) {
252 { // Access token missing.
253 scoped_ptr
<base::DictionaryValue
> json(
254 ParseJson(kTokenResponseNoAccessToken
));
257 EXPECT_FALSE(OAuth2MintTokenFlow::ParseMintTokenResponse(json
.get(), &at
,
259 EXPECT_TRUE(at
.empty());
262 scoped_ptr
<base::DictionaryValue
> json(ParseJson(kValidTokenResponse
));
265 EXPECT_TRUE(OAuth2MintTokenFlow::ParseMintTokenResponse(json
.get(), &at
,
267 EXPECT_EQ("at1", at
);
268 EXPECT_EQ(3600, ttl
);
272 TEST_F(OAuth2MintTokenFlowTest
, ParseIssueAdviceResponse
) {
273 { // Description missing.
274 scoped_ptr
<base::DictionaryValue
> json(
275 ParseJson(kIssueAdviceResponseNoDescription
));
277 EXPECT_FALSE(OAuth2MintTokenFlow::ParseIssueAdviceResponse(
279 EXPECT_TRUE(ia
.empty());
282 scoped_ptr
<base::DictionaryValue
> json(
283 ParseJson(kIssueAdviceResponseNoDetail
));
285 EXPECT_FALSE(OAuth2MintTokenFlow::ParseIssueAdviceResponse(
287 EXPECT_TRUE(ia
.empty());
290 scoped_ptr
<base::DictionaryValue
> json(
291 ParseJson(kValidIssueAdviceResponse
));
293 EXPECT_TRUE(OAuth2MintTokenFlow::ParseIssueAdviceResponse(
295 IssueAdviceInfo
ia_expected(CreateIssueAdvice());
296 EXPECT_EQ(ia_expected
, ia
);
300 TEST_F(OAuth2MintTokenFlowTest
, ProcessApiCallSuccess
) {
302 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
303 url_fetcher
.SetResponseString(std::string());
304 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE
);
305 EXPECT_CALL(delegate_
, OnMintTokenFailure(_
));
306 flow_
->ProcessApiCallSuccess(&url_fetcher
);
309 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
310 url_fetcher
.SetResponseString("foo");
311 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE
);
312 EXPECT_CALL(delegate_
, OnMintTokenFailure(_
));
313 flow_
->ProcessApiCallSuccess(&url_fetcher
);
315 { // Valid json: no access token.
316 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
317 url_fetcher
.SetResponseString(kTokenResponseNoAccessToken
);
318 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE
);
319 EXPECT_CALL(delegate_
, OnMintTokenFailure(_
));
320 flow_
->ProcessApiCallSuccess(&url_fetcher
);
322 { // Valid json: good token response.
323 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
324 url_fetcher
.SetResponseString(kValidTokenResponse
);
325 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE
);
326 EXPECT_CALL(delegate_
, OnMintTokenSuccess("at1", 3600));
327 flow_
->ProcessApiCallSuccess(&url_fetcher
);
329 { // Valid json: no description.
330 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
331 url_fetcher
.SetResponseString(kIssueAdviceResponseNoDescription
);
332 CreateFlow(OAuth2MintTokenFlow::MODE_ISSUE_ADVICE
);
333 EXPECT_CALL(delegate_
, OnMintTokenFailure(_
));
334 flow_
->ProcessApiCallSuccess(&url_fetcher
);
336 { // Valid json: no detail.
337 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
338 url_fetcher
.SetResponseString(kIssueAdviceResponseNoDetail
);
339 CreateFlow(OAuth2MintTokenFlow::MODE_ISSUE_ADVICE
);
340 EXPECT_CALL(delegate_
, OnMintTokenFailure(_
));
341 flow_
->ProcessApiCallSuccess(&url_fetcher
);
343 { // Valid json: good issue advice response.
344 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
345 url_fetcher
.SetResponseString(kValidIssueAdviceResponse
);
346 CreateFlow(OAuth2MintTokenFlow::MODE_ISSUE_ADVICE
);
347 IssueAdviceInfo
ia(CreateIssueAdvice());
348 EXPECT_CALL(delegate_
, OnIssueAdviceSuccess(ia
));
349 flow_
->ProcessApiCallSuccess(&url_fetcher
);
353 TEST_F(OAuth2MintTokenFlowTest
, ProcessApiCallFailure
) {
354 { // Null delegate should work fine.
355 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
356 url_fetcher
.set_status(URLRequestStatus::FromError(net::ERR_FAILED
));
357 CreateFlow(NULL
, OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE
, "");
358 flow_
->ProcessApiCallFailure(&url_fetcher
);
361 { // Non-null delegate.
362 TestURLFetcher
url_fetcher(1, GURL("http://www.google.com"), NULL
);
363 url_fetcher
.set_status(URLRequestStatus::FromError(net::ERR_FAILED
));
364 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE
);
365 EXPECT_CALL(delegate_
, OnMintTokenFailure(_
));
366 flow_
->ProcessApiCallFailure(&url_fetcher
);