OLD | NEW |
| (Empty) |
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. | |
4 // | |
5 // A complete set of unit tests for OAuth2MintTokenFlow. | |
6 | |
7 #include <string> | |
8 #include <vector> | |
9 | |
10 #include "base/json/json_reader.h" | |
11 #include "base/memory/scoped_ptr.h" | |
12 #include "base/values.h" | |
13 #include "base/utf_string_conversions.h" | |
14 #include "chrome/common/net/gaia/google_service_auth_error.h" | |
15 #include "chrome/common/net/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" | |
20 | |
21 using net::TestURLFetcher; | |
22 using net::URLFetcher; | |
23 using net::URLRequestStatus; | |
24 using testing::_; | |
25 using testing::StrictMock; | |
26 | |
27 namespace { | |
28 | |
29 static const char kValidTokenResponse[] = | |
30 "{" | |
31 " \"token\": \"at1\"," | |
32 " \"issueAdvice\": \"Auto\"" | |
33 "}"; | |
34 static const char kTokenResponseNoAccessToken[] = | |
35 "{" | |
36 " \"issueAdvice\": \"Auto\"" | |
37 "}"; | |
38 | |
39 static const char kValidIssueAdviceResponse[] = | |
40 "{" | |
41 " \"issueAdvice\": \"consent\"," | |
42 " \"consent\": {" | |
43 " \"oauthClient\": {" | |
44 " \"name\": \"Test app\"," | |
45 " \"iconUri\": \"\"," | |
46 " \"developerEmail\": \"munjal@chromium.org\"" | |
47 " }," | |
48 " \"scopes\": [" | |
49 " {" | |
50 " \"description\": \"Manage your calendars\"," | |
51 " \"detail\": \"\nView and manage your calendars\n\"" | |
52 " }," | |
53 " {" | |
54 " \"description\": \"Manage your documents\"," | |
55 " \"detail\": \"\nView your documents\nUpload new documents\n\"" | |
56 " }" | |
57 " ]" | |
58 " }" | |
59 "}"; | |
60 | |
61 static const char kIssueAdviceResponseNoDescription[] = | |
62 "{" | |
63 " \"issueAdvice\": \"consent\"," | |
64 " \"consent\": {" | |
65 " \"oauthClient\": {" | |
66 " \"name\": \"Test app\"," | |
67 " \"iconUri\": \"\"," | |
68 " \"developerEmail\": \"munjal@chromium.org\"" | |
69 " }," | |
70 " \"scopes\": [" | |
71 " {" | |
72 " \"description\": \"Manage your calendars\"," | |
73 " \"detail\": \"\nView and manage your calendars\n\"" | |
74 " }," | |
75 " {" | |
76 " \"detail\": \"\nView your documents\nUpload new documents\n\"" | |
77 " }" | |
78 " ]" | |
79 " }" | |
80 "}"; | |
81 | |
82 static const char kIssueAdviceResponseNoDetail[] = | |
83 "{" | |
84 " \"issueAdvice\": \"consent\"," | |
85 " \"consent\": {" | |
86 " \"oauthClient\": {" | |
87 " \"name\": \"Test app\"," | |
88 " \"iconUri\": \"\"," | |
89 " \"developerEmail\": \"munjal@chromium.org\"" | |
90 " }," | |
91 " \"scopes\": [" | |
92 " {" | |
93 " \"description\": \"Manage your calendars\"," | |
94 " \"detail\": \"\nView and manage your calendars\n\"" | |
95 " }," | |
96 " {" | |
97 " \"description\": \"Manage your documents\"" | |
98 " }" | |
99 " ]" | |
100 " }" | |
101 "}"; | |
102 | |
103 std::vector<std::string> CreateTestScopes() { | |
104 std::vector<std::string> scopes; | |
105 scopes.push_back("http://scope1"); | |
106 scopes.push_back("http://scope2"); | |
107 return scopes; | |
108 } | |
109 | |
110 static IssueAdviceInfo CreateIssueAdvice() { | |
111 IssueAdviceInfo ia; | |
112 IssueAdviceInfoEntry e1; | |
113 e1.description = ASCIIToUTF16("Manage your calendars"); | |
114 e1.details.push_back(ASCIIToUTF16("View and manage your calendars")); | |
115 ia.push_back(e1); | |
116 IssueAdviceInfoEntry e2; | |
117 e2.description = ASCIIToUTF16("Manage your documents"); | |
118 e2.details.push_back(ASCIIToUTF16("View your documents")); | |
119 e2.details.push_back(ASCIIToUTF16("Upload new documents")); | |
120 ia.push_back(e2); | |
121 return ia; | |
122 } | |
123 | |
124 class MockDelegate : public OAuth2MintTokenFlow::Delegate { | |
125 public: | |
126 MockDelegate() {} | |
127 ~MockDelegate() {} | |
128 | |
129 MOCK_METHOD1(OnMintTokenSuccess, void(const std::string& access_token)); | |
130 MOCK_METHOD1(OnIssueAdviceSuccess, | |
131 void (const IssueAdviceInfo& issue_advice)); | |
132 MOCK_METHOD1(OnMintTokenFailure, | |
133 void(const GoogleServiceAuthError& error)); | |
134 }; | |
135 | |
136 class MockMintTokenFlow : public OAuth2MintTokenFlow { | |
137 public: | |
138 explicit MockMintTokenFlow(MockDelegate* delegate, | |
139 const OAuth2MintTokenFlow::Parameters& parameters ) | |
140 : OAuth2MintTokenFlow(NULL, delegate, parameters) {} | |
141 ~MockMintTokenFlow() {} | |
142 | |
143 MOCK_METHOD0(CreateAccessTokenFetcher, OAuth2AccessTokenFetcher*()); | |
144 MOCK_METHOD0(CreateMintTokenFetcher, OAuth2MintTokenFetcher*()); | |
145 }; | |
146 | |
147 } // namespace | |
148 | |
149 class OAuth2MintTokenFlowTest : public testing::Test { | |
150 public: | |
151 OAuth2MintTokenFlowTest() {} | |
152 virtual ~OAuth2MintTokenFlowTest() { } | |
153 | |
154 protected: | |
155 void CreateFlow(OAuth2MintTokenFlow::Mode mode) { | |
156 return CreateFlow(&delegate_, mode); | |
157 } | |
158 | |
159 void CreateFlow(MockDelegate* delegate, | |
160 OAuth2MintTokenFlow::Mode mode) { | |
161 std::string rt = "refresh_token"; | |
162 std::string ext_id = "ext1"; | |
163 std::string client_id = "client1"; | |
164 std::vector<std::string> scopes(CreateTestScopes()); | |
165 flow_.reset(new MockMintTokenFlow( | |
166 delegate, | |
167 OAuth2MintTokenFlow::Parameters(rt, ext_id, client_id, scopes, mode))); | |
168 } | |
169 | |
170 // Helper to parse the given string to DictionaryValue. | |
171 static base::DictionaryValue* ParseJson(const std::string& str) { | |
172 scoped_ptr<Value> value(base::JSONReader::Read(str)); | |
173 EXPECT_TRUE(value.get()); | |
174 EXPECT_EQ(Value::TYPE_DICTIONARY, value->GetType()); | |
175 return static_cast<base::DictionaryValue*>(value.release()); | |
176 } | |
177 | |
178 scoped_ptr<MockMintTokenFlow> flow_; | |
179 StrictMock<MockDelegate> delegate_; | |
180 }; | |
181 | |
182 TEST_F(OAuth2MintTokenFlowTest, CreateApiCallBody) { | |
183 { // Issue advice mode. | |
184 CreateFlow(OAuth2MintTokenFlow::MODE_ISSUE_ADVICE); | |
185 std::string body = flow_->CreateApiCallBody(); | |
186 std::string expected_body( | |
187 "force=false" | |
188 "&response_type=none" | |
189 "&scope=http://scope1+http://scope2" | |
190 "&client_id=client1" | |
191 "&origin=ext1"); | |
192 EXPECT_EQ(expected_body, body); | |
193 } | |
194 { // Record grant mode. | |
195 CreateFlow(OAuth2MintTokenFlow::MODE_RECORD_GRANT); | |
196 std::string body = flow_->CreateApiCallBody(); | |
197 std::string expected_body( | |
198 "force=true" | |
199 "&response_type=none" | |
200 "&scope=http://scope1+http://scope2" | |
201 "&client_id=client1" | |
202 "&origin=ext1"); | |
203 EXPECT_EQ(expected_body, body); | |
204 } | |
205 { // Mint token no force mode. | |
206 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE); | |
207 std::string body = flow_->CreateApiCallBody(); | |
208 std::string expected_body( | |
209 "force=false" | |
210 "&response_type=token" | |
211 "&scope=http://scope1+http://scope2" | |
212 "&client_id=client1" | |
213 "&origin=ext1"); | |
214 EXPECT_EQ(expected_body, body); | |
215 } | |
216 { // Mint token force mode. | |
217 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_FORCE); | |
218 std::string body = flow_->CreateApiCallBody(); | |
219 std::string expected_body( | |
220 "force=true" | |
221 "&response_type=token" | |
222 "&scope=http://scope1+http://scope2" | |
223 "&client_id=client1" | |
224 "&origin=ext1"); | |
225 EXPECT_EQ(expected_body, body); | |
226 } | |
227 } | |
228 | |
229 TEST_F(OAuth2MintTokenFlowTest, ParseMintTokenResponse) { | |
230 { // Access token missing. | |
231 scoped_ptr<base::DictionaryValue> json( | |
232 ParseJson(kTokenResponseNoAccessToken)); | |
233 std::string at; | |
234 EXPECT_FALSE(OAuth2MintTokenFlow::ParseMintTokenResponse(json.get(), &at)); | |
235 EXPECT_TRUE(at.empty()); | |
236 } | |
237 { // All good. | |
238 scoped_ptr<base::DictionaryValue> json(ParseJson(kValidTokenResponse)); | |
239 std::string at; | |
240 EXPECT_TRUE(OAuth2MintTokenFlow::ParseMintTokenResponse(json.get(), &at)); | |
241 EXPECT_EQ("at1", at); | |
242 } | |
243 } | |
244 | |
245 TEST_F(OAuth2MintTokenFlowTest, ParseIssueAdviceResponse) { | |
246 { // Description missing. | |
247 scoped_ptr<base::DictionaryValue> json( | |
248 ParseJson(kIssueAdviceResponseNoDescription)); | |
249 IssueAdviceInfo ia; | |
250 EXPECT_FALSE(OAuth2MintTokenFlow::ParseIssueAdviceResponse( | |
251 json.get(), &ia)); | |
252 EXPECT_TRUE(ia.empty()); | |
253 } | |
254 { // Detail missing. | |
255 scoped_ptr<base::DictionaryValue> json( | |
256 ParseJson(kIssueAdviceResponseNoDetail)); | |
257 IssueAdviceInfo ia; | |
258 EXPECT_FALSE(OAuth2MintTokenFlow::ParseIssueAdviceResponse( | |
259 json.get(), &ia)); | |
260 EXPECT_TRUE(ia.empty()); | |
261 } | |
262 { // All good. | |
263 scoped_ptr<base::DictionaryValue> json( | |
264 ParseJson(kValidIssueAdviceResponse)); | |
265 IssueAdviceInfo ia; | |
266 EXPECT_TRUE(OAuth2MintTokenFlow::ParseIssueAdviceResponse( | |
267 json.get(), &ia)); | |
268 IssueAdviceInfo ia_expected(CreateIssueAdvice()); | |
269 EXPECT_EQ(ia_expected, ia); | |
270 } | |
271 } | |
272 | |
273 TEST_F(OAuth2MintTokenFlowTest, ProcessApiCallSuccess) { | |
274 { // No body. | |
275 TestURLFetcher url_fetcher(1, GURL("http://www.google.com"), NULL); | |
276 url_fetcher.SetResponseString(""); | |
277 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE); | |
278 EXPECT_CALL(delegate_, OnMintTokenFailure(_)); | |
279 flow_->ProcessApiCallSuccess(&url_fetcher); | |
280 } | |
281 { // Bad json. | |
282 TestURLFetcher url_fetcher(1, GURL("http://www.google.com"), NULL); | |
283 url_fetcher.SetResponseString("foo"); | |
284 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE); | |
285 EXPECT_CALL(delegate_, OnMintTokenFailure(_)); | |
286 flow_->ProcessApiCallSuccess(&url_fetcher); | |
287 } | |
288 { // Valid json: no access token. | |
289 TestURLFetcher url_fetcher(1, GURL("http://www.google.com"), NULL); | |
290 url_fetcher.SetResponseString(kTokenResponseNoAccessToken); | |
291 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE); | |
292 EXPECT_CALL(delegate_, OnMintTokenFailure(_)); | |
293 flow_->ProcessApiCallSuccess(&url_fetcher); | |
294 } | |
295 { // Valid json: good token response. | |
296 TestURLFetcher url_fetcher(1, GURL("http://www.google.com"), NULL); | |
297 url_fetcher.SetResponseString(kValidTokenResponse); | |
298 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE); | |
299 EXPECT_CALL(delegate_, OnMintTokenSuccess("at1")); | |
300 flow_->ProcessApiCallSuccess(&url_fetcher); | |
301 } | |
302 { // Valid json: no description. | |
303 TestURLFetcher url_fetcher(1, GURL("http://www.google.com"), NULL); | |
304 url_fetcher.SetResponseString(kIssueAdviceResponseNoDescription); | |
305 CreateFlow(OAuth2MintTokenFlow::MODE_ISSUE_ADVICE); | |
306 EXPECT_CALL(delegate_, OnMintTokenFailure(_)); | |
307 flow_->ProcessApiCallSuccess(&url_fetcher); | |
308 } | |
309 { // Valid json: no detail. | |
310 TestURLFetcher url_fetcher(1, GURL("http://www.google.com"), NULL); | |
311 url_fetcher.SetResponseString(kIssueAdviceResponseNoDetail); | |
312 CreateFlow(OAuth2MintTokenFlow::MODE_ISSUE_ADVICE); | |
313 EXPECT_CALL(delegate_, OnMintTokenFailure(_)); | |
314 flow_->ProcessApiCallSuccess(&url_fetcher); | |
315 } | |
316 { // Valid json: good issue advice response. | |
317 TestURLFetcher url_fetcher(1, GURL("http://www.google.com"), NULL); | |
318 url_fetcher.SetResponseString(kValidIssueAdviceResponse); | |
319 CreateFlow(OAuth2MintTokenFlow::MODE_ISSUE_ADVICE); | |
320 IssueAdviceInfo ia(CreateIssueAdvice()); | |
321 EXPECT_CALL(delegate_, OnIssueAdviceSuccess(ia)); | |
322 flow_->ProcessApiCallSuccess(&url_fetcher); | |
323 } | |
324 } | |
325 | |
326 TEST_F(OAuth2MintTokenFlowTest, ProcessApiCallFailure) { | |
327 { // Null delegate should work fine. | |
328 TestURLFetcher url_fetcher(1, GURL("http://www.google.com"), NULL); | |
329 url_fetcher.set_status(URLRequestStatus(URLRequestStatus::FAILED, 101)); | |
330 CreateFlow(NULL, OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE); | |
331 flow_->ProcessApiCallFailure(&url_fetcher); | |
332 } | |
333 | |
334 { // Non-null delegate. | |
335 TestURLFetcher url_fetcher(1, GURL("http://www.google.com"), NULL); | |
336 url_fetcher.set_status(URLRequestStatus(URLRequestStatus::FAILED, 101)); | |
337 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE); | |
338 EXPECT_CALL(delegate_, OnMintTokenFailure(_)); | |
339 flow_->ProcessApiCallFailure(&url_fetcher); | |
340 } | |
341 } | |
342 | |
343 TEST_F(OAuth2MintTokenFlowTest, ProcessMintAccessTokenFailure) { | |
344 { // Null delegate should work fine. | |
345 GoogleServiceAuthError error( | |
346 GoogleServiceAuthError::FromConnectionError(101)); | |
347 CreateFlow(NULL, OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE); | |
348 flow_->ProcessMintAccessTokenFailure(error); | |
349 } | |
350 | |
351 { // Non-null delegate. | |
352 GoogleServiceAuthError error( | |
353 GoogleServiceAuthError::FromConnectionError(101)); | |
354 CreateFlow(OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE); | |
355 EXPECT_CALL(delegate_, OnMintTokenFailure(error)); | |
356 flow_->ProcessMintAccessTokenFailure(error); | |
357 } | |
358 } | |
OLD | NEW |