1 // Copyright 2014 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.
9 #include "base/memory/ref_counted.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/strings/stringprintf.h"
13 #include "google_apis/gaia/fake_oauth2_token_service.h"
14 #include "google_apis/gaia/gaia_constants.h"
15 #include "google_apis/gaia/merge_session_helper.h"
16 #include "net/url_request/test_url_fetcher_factory.h"
17 #include "net/url_request/url_request_test_util.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/gtest/include/gtest/gtest.h"
23 class MockObserver
: public MergeSessionHelper::Observer
{
25 explicit MockObserver(MergeSessionHelper
* helper
) : helper_(helper
) {
26 helper_
->AddObserver(this);
30 helper_
->RemoveObserver(this);
33 MOCK_METHOD2(MergeSessionCompleted
,
34 void(const std::string
&,
35 const GoogleServiceAuthError
& ));
37 MergeSessionHelper
* helper_
;
39 DISALLOW_COPY_AND_ASSIGN(MockObserver
);
42 // Counts number of InstrumentedMergeSessionHelper created.
43 // We can EXPECT_* to be zero at the end of our unit tests
44 // to make sure everything is properly deleted.
48 class InstrumentedMergeSessionHelper
: public MergeSessionHelper
{
50 InstrumentedMergeSessionHelper(
51 OAuth2TokenService
* token_service
,
52 net::URLRequestContextGetter
* request_context
) :
53 MergeSessionHelper(token_service
, request_context
, NULL
) {
57 virtual ~InstrumentedMergeSessionHelper() {
61 MOCK_METHOD0(StartFetching
, void());
62 MOCK_METHOD0(StartLogOutUrlFetch
, void());
65 DISALLOW_COPY_AND_ASSIGN(InstrumentedMergeSessionHelper
);
68 class MergeSessionHelperTest
: public testing::Test
{
70 MergeSessionHelperTest()
71 : no_error_(GoogleServiceAuthError::NONE
),
72 error_(GoogleServiceAuthError::SERVICE_ERROR
),
73 canceled_(GoogleServiceAuthError::REQUEST_CANCELED
),
74 request_context_getter_(new net::TestURLRequestContextGetter(
75 base::MessageLoopProxy::current())) {}
77 OAuth2TokenService
* token_service() { return &token_service_
; }
78 net::URLRequestContextGetter
* request_context() {
79 return request_context_getter_
;
82 void SimulateUbertokenFailure(UbertokenConsumer
* consumer
,
83 const GoogleServiceAuthError
& error
) {
84 consumer
->OnUbertokenFailure(error
);
87 void SimulateMergeSessionSuccess(GaiaAuthConsumer
* consumer
,
88 const std::string
& data
) {
89 consumer
->OnMergeSessionSuccess(data
);
92 void SimulateMergeSessionFailure(GaiaAuthConsumer
* consumer
,
93 const GoogleServiceAuthError
& error
) {
94 consumer
->OnMergeSessionFailure(error
);
97 void SimulateLogoutSuccess(net::URLFetcherDelegate
* consumer
) {
98 consumer
->OnURLFetchComplete(NULL
);
101 void SimulateGetCheckConnctionInfoSuccess(
102 net::TestURLFetcher
* fetcher
,
103 const std::string
& data
) {
104 fetcher
->set_status(net::URLRequestStatus());
105 fetcher
->set_response_code(200);
106 fetcher
->SetResponseString(data
);
107 fetcher
->delegate()->OnURLFetchComplete(fetcher
);
110 void SimulateGetCheckConnctionInfoResult(
111 net::URLFetcher
* fetcher
,
112 const std::string
& result
) {
113 net::TestURLFetcher
* test_fetcher
=
114 static_cast<net::TestURLFetcher
*>(fetcher
);
115 test_fetcher
->set_status(net::URLRequestStatus());
116 test_fetcher
->set_response_code(200);
117 test_fetcher
->SetResponseString(result
);
118 test_fetcher
->delegate()->OnURLFetchComplete(fetcher
);
121 const GoogleServiceAuthError
& no_error() { return no_error_
; }
122 const GoogleServiceAuthError
& error() { return error_
; }
123 const GoogleServiceAuthError
& canceled() { return canceled_
; }
125 net::TestURLFetcherFactory
* factory() { return &factory_
; }
128 base::MessageLoop message_loop_
;
129 net::TestURLFetcherFactory factory_
;
130 FakeOAuth2TokenService token_service_
;
131 GoogleServiceAuthError no_error_
;
132 GoogleServiceAuthError error_
;
133 GoogleServiceAuthError canceled_
;
134 scoped_refptr
<net::URLRequestContextGetter
> request_context_getter_
;
141 TEST_F(MergeSessionHelperTest
, Success
) {
142 InstrumentedMergeSessionHelper
helper(token_service(), request_context());
143 MockObserver
observer(&helper
);
145 EXPECT_CALL(helper
, StartFetching());
146 EXPECT_CALL(observer
, MergeSessionCompleted("acc1@gmail.com", no_error()));
148 helper
.LogIn("acc1@gmail.com");
149 SimulateMergeSessionSuccess(&helper
, "token");
152 TEST_F(MergeSessionHelperTest
, FailedMergeSession
) {
153 InstrumentedMergeSessionHelper
helper(token_service(), request_context());
154 MockObserver
observer(&helper
);
156 EXPECT_CALL(helper
, StartFetching());
157 EXPECT_CALL(observer
, MergeSessionCompleted("acc1@gmail.com", error()));
159 helper
.LogIn("acc1@gmail.com");
160 SimulateMergeSessionFailure(&helper
, error());
163 TEST_F(MergeSessionHelperTest
, FailedUbertoken
) {
164 InstrumentedMergeSessionHelper
helper(token_service(), request_context());
165 MockObserver
observer(&helper
);
167 EXPECT_CALL(helper
, StartFetching());
168 EXPECT_CALL(observer
, MergeSessionCompleted("acc1@gmail.com", error()));
170 helper
.LogIn("acc1@gmail.com");
171 SimulateUbertokenFailure(&helper
, error());
174 TEST_F(MergeSessionHelperTest
, ContinueAfterSuccess
) {
175 InstrumentedMergeSessionHelper
helper(token_service(), request_context());
176 MockObserver
observer(&helper
);
178 EXPECT_CALL(helper
, StartFetching()).Times(2);
179 EXPECT_CALL(observer
, MergeSessionCompleted("acc1@gmail.com", no_error()));
180 EXPECT_CALL(observer
, MergeSessionCompleted("acc2@gmail.com", no_error()));
182 helper
.LogIn("acc1@gmail.com");
183 helper
.LogIn("acc2@gmail.com");
184 SimulateMergeSessionSuccess(&helper
, "token1");
185 SimulateMergeSessionSuccess(&helper
, "token2");
188 TEST_F(MergeSessionHelperTest
, ContinueAfterFailure1
) {
189 InstrumentedMergeSessionHelper
helper(token_service(), request_context());
190 MockObserver
observer(&helper
);
192 EXPECT_CALL(helper
, StartFetching()).Times(2);
193 EXPECT_CALL(observer
, MergeSessionCompleted("acc1@gmail.com", error()));
194 EXPECT_CALL(observer
, MergeSessionCompleted("acc2@gmail.com", no_error()));
196 helper
.LogIn("acc1@gmail.com");
197 helper
.LogIn("acc2@gmail.com");
198 SimulateMergeSessionFailure(&helper
, error());
199 SimulateMergeSessionSuccess(&helper
, "token2");
202 TEST_F(MergeSessionHelperTest
, ContinueAfterFailure2
) {
203 InstrumentedMergeSessionHelper
helper(token_service(), request_context());
204 MockObserver
observer(&helper
);
206 EXPECT_CALL(helper
, StartFetching()).Times(2);
207 EXPECT_CALL(observer
, MergeSessionCompleted("acc1@gmail.com", error()));
208 EXPECT_CALL(observer
, MergeSessionCompleted("acc2@gmail.com", no_error()));
210 helper
.LogIn("acc1@gmail.com");
211 helper
.LogIn("acc2@gmail.com");
212 SimulateUbertokenFailure(&helper
, error());
213 SimulateMergeSessionSuccess(&helper
, "token2");
216 TEST_F(MergeSessionHelperTest
, AllRequestsInMultipleGoes
) {
217 InstrumentedMergeSessionHelper
helper(token_service(), request_context());
218 MockObserver
observer(&helper
);
220 EXPECT_CALL(helper
, StartFetching()).Times(4);
221 EXPECT_CALL(observer
, MergeSessionCompleted(_
, no_error())).Times(4);
223 helper
.LogIn("acc1@gmail.com");
224 helper
.LogIn("acc2@gmail.com");
226 SimulateMergeSessionSuccess(&helper
, "token1");
228 helper
.LogIn("acc3@gmail.com");
230 SimulateMergeSessionSuccess(&helper
, "token2");
231 SimulateMergeSessionSuccess(&helper
, "token3");
233 helper
.LogIn("acc4@gmail.com");
235 SimulateMergeSessionSuccess(&helper
, "token4");
238 TEST_F(MergeSessionHelperTest
, LogOut
) {
239 InstrumentedMergeSessionHelper
helper(token_service(), request_context());
240 MockObserver
observer(&helper
);
242 std::vector
<std::string
> current_accounts
;
243 current_accounts
.push_back("acc1@gmail.com");
244 current_accounts
.push_back("acc2@gmail.com");
245 current_accounts
.push_back("acc3@gmail.com");
247 EXPECT_CALL(helper
, StartLogOutUrlFetch());
248 EXPECT_CALL(helper
, StartFetching()).Times(2);
249 EXPECT_CALL(observer
, MergeSessionCompleted("acc1@gmail.com", no_error()));
250 EXPECT_CALL(observer
, MergeSessionCompleted("acc3@gmail.com", no_error()));
252 helper
.LogOut("acc2@gmail.com", current_accounts
);
253 SimulateLogoutSuccess(&helper
);
254 SimulateMergeSessionSuccess(&helper
, "token1");
255 SimulateMergeSessionSuccess(&helper
, "token3");
258 TEST_F(MergeSessionHelperTest
, PendingSigninThenSignout
) {
259 InstrumentedMergeSessionHelper
helper(token_service(), request_context());
260 MockObserver
observer(&helper
);
262 std::vector
<std::string
> current_accounts
;
263 current_accounts
.push_back("acc2@gmail.com");
264 current_accounts
.push_back("acc3@gmail.com");
266 // From the first Signin.
267 EXPECT_CALL(observer
, MergeSessionCompleted("acc1@gmail.com", no_error()));
269 // From the sign out and then re-sign in.
270 EXPECT_CALL(helper
, StartLogOutUrlFetch());
271 EXPECT_CALL(observer
, MergeSessionCompleted("acc3@gmail.com", no_error()));
273 // Total sign in 2 times, not enforcing ordered sequences.
274 EXPECT_CALL(helper
, StartFetching()).Times(2);
276 helper
.LogIn("acc1@gmail.com");
277 helper
.LogOut("acc2@gmail.com", current_accounts
);
279 SimulateMergeSessionSuccess(&helper
, "token1");
280 SimulateLogoutSuccess(&helper
);
281 SimulateMergeSessionSuccess(&helper
, "token3");
284 TEST_F(MergeSessionHelperTest
, CancelSignIn
) {
285 InstrumentedMergeSessionHelper
helper(token_service(), request_context());
286 MockObserver
observer(&helper
);
288 std::vector
<std::string
> current_accounts
;
290 EXPECT_CALL(helper
, StartFetching());
291 EXPECT_CALL(observer
, MergeSessionCompleted("acc2@gmail.com", canceled()));
292 EXPECT_CALL(observer
, MergeSessionCompleted("acc1@gmail.com", no_error()));
293 EXPECT_CALL(helper
, StartLogOutUrlFetch());
295 helper
.LogIn("acc1@gmail.com");
296 helper
.LogIn("acc2@gmail.com");
297 helper
.LogOut("acc2@gmail.com", current_accounts
);
299 SimulateMergeSessionSuccess(&helper
, "token1");
300 SimulateLogoutSuccess(&helper
);
303 TEST_F(MergeSessionHelperTest
, DoubleSignout
) {
304 InstrumentedMergeSessionHelper
helper(token_service(), request_context());
305 MockObserver
observer(&helper
);
307 std::vector
<std::string
> current_accounts1
;
308 current_accounts1
.push_back("acc1@gmail.com");
309 current_accounts1
.push_back("acc2@gmail.com");
310 current_accounts1
.push_back("acc3@gmail.com");
312 std::vector
<std::string
> current_accounts2
;
313 current_accounts2
.push_back("acc1@gmail.com");
314 current_accounts2
.push_back("acc3@gmail.com");
316 EXPECT_CALL(helper
, StartFetching()).Times(2);
317 EXPECT_CALL(observer
, MergeSessionCompleted("acc3@gmail.com", canceled()));
318 EXPECT_CALL(observer
,
319 MergeSessionCompleted("acc1@gmail.com", no_error())).Times(2);
320 EXPECT_CALL(helper
, StartLogOutUrlFetch());
322 helper
.LogIn("acc1@gmail.com");
323 helper
.LogOut("acc2@gmail.com", current_accounts1
);
324 helper
.LogOut("acc3@gmail.com", current_accounts2
);
326 SimulateMergeSessionSuccess(&helper
, "token1");
327 SimulateLogoutSuccess(&helper
);
328 SimulateMergeSessionSuccess(&helper
, "token1");
331 TEST_F(MergeSessionHelperTest
, ExternalCcResultFetcher
) {
332 InstrumentedMergeSessionHelper
helper(token_service(), request_context());
333 MergeSessionHelper::ExternalCcResultFetcher
result_fetcher(&helper
);
334 result_fetcher
.Start();
336 // Simulate a successful completion of GetCheckConnctionInfo.
337 net::TestURLFetcher
* fetcher
= factory()->GetFetcherByID(0);
338 ASSERT_TRUE(NULL
!= fetcher
);
339 SimulateGetCheckConnctionInfoSuccess(fetcher
,
340 "[{\"carryBackToken\": \"yt\", \"url\": \"http://www.yt.com\"},"
341 " {\"carryBackToken\": \"bl\", \"url\": \"http://www.bl.com\"}]");
343 // Simulate responses for the two connection URLs.
344 MergeSessionHelper::ExternalCcResultFetcher::URLToTokenAndFetcher fetchers
=
345 result_fetcher
.get_fetcher_map_for_testing();
346 ASSERT_EQ(2u, fetchers
.size());
347 ASSERT_EQ(1u, fetchers
.count(GURL("http://www.yt.com")));
348 ASSERT_EQ(1u, fetchers
.count(GURL("http://www.bl.com")));
350 ASSERT_EQ("bl:null,yt:null", result_fetcher
.GetExternalCcResult());
351 SimulateGetCheckConnctionInfoResult(
352 fetchers
[GURL("http://www.yt.com")].second
, "yt_result");
353 ASSERT_EQ("bl:null,yt:yt_result", result_fetcher
.GetExternalCcResult());
354 SimulateGetCheckConnctionInfoResult(
355 fetchers
[GURL("http://www.bl.com")].second
, "bl_result");
356 ASSERT_EQ("bl:bl_result,yt:yt_result", result_fetcher
.GetExternalCcResult());
359 TEST_F(MergeSessionHelperTest
, ExternalCcResultFetcherTimeout
) {
360 InstrumentedMergeSessionHelper
helper(token_service(), request_context());
361 MergeSessionHelper::ExternalCcResultFetcher
result_fetcher(&helper
);
362 result_fetcher
.Start();
364 // Simulate a successful completion of GetCheckConnctionInfo.
365 net::TestURLFetcher
* fetcher
= factory()->GetFetcherByID(0);
366 ASSERT_TRUE(NULL
!= fetcher
);
367 SimulateGetCheckConnctionInfoSuccess(fetcher
,
368 "[{\"carryBackToken\": \"yt\", \"url\": \"http://www.yt.com\"},"
369 " {\"carryBackToken\": \"bl\", \"url\": \"http://www.bl.com\"}]");
371 MergeSessionHelper::ExternalCcResultFetcher::URLToTokenAndFetcher fetchers
=
372 result_fetcher
.get_fetcher_map_for_testing();
373 ASSERT_EQ(2u, fetchers
.size());
374 ASSERT_EQ(1u, fetchers
.count(GURL("http://www.yt.com")));
375 ASSERT_EQ(1u, fetchers
.count(GURL("http://www.bl.com")));
377 // Simulate response only for "yt".
378 ASSERT_EQ("bl:null,yt:null", result_fetcher
.GetExternalCcResult());
379 SimulateGetCheckConnctionInfoResult(
380 fetchers
[GURL("http://www.yt.com")].second
, "yt_result");
381 ASSERT_EQ("bl:null,yt:yt_result", result_fetcher
.GetExternalCcResult());
384 result_fetcher
.TimeoutForTests();
385 ASSERT_EQ("bl:null,yt:yt_result", result_fetcher
.GetExternalCcResult());
386 fetchers
= result_fetcher
.get_fetcher_map_for_testing();
387 ASSERT_EQ(0u, fetchers
.size());
390 TEST_F(MergeSessionHelperTest
, ExternalCcResultFetcherTruncate
) {
391 InstrumentedMergeSessionHelper
helper(token_service(), request_context());
392 MergeSessionHelper::ExternalCcResultFetcher
result_fetcher(&helper
);
393 result_fetcher
.Start();
395 // Simulate a successful completion of GetCheckConnctionInfo.
396 net::TestURLFetcher
* fetcher
= factory()->GetFetcherByID(0);
397 ASSERT_TRUE(NULL
!= fetcher
);
398 SimulateGetCheckConnctionInfoSuccess(fetcher
,
399 "[{\"carryBackToken\": \"yt\", \"url\": \"http://www.yt.com\"}]");
401 MergeSessionHelper::ExternalCcResultFetcher::URLToTokenAndFetcher fetchers
=
402 result_fetcher
.get_fetcher_map_for_testing();
403 ASSERT_EQ(1u, fetchers
.size());
404 ASSERT_EQ(1u, fetchers
.count(GURL("http://www.yt.com")));
406 // Simulate response for "yt" with a string that is too long.
407 SimulateGetCheckConnctionInfoResult(
408 fetchers
[GURL("http://www.yt.com")].second
, "1234567890123456trunc");
409 ASSERT_EQ("yt:1234567890123456", result_fetcher
.GetExternalCcResult());