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);