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
& ));
36 MOCK_METHOD1(GetCheckConnectionInfoCompleted
, void(bool));
39 MergeSessionHelper
* helper_
;
41 DISALLOW_COPY_AND_ASSIGN(MockObserver
);
44 // Counts number of InstrumentedMergeSessionHelper created.
45 // We can EXPECT_* to be zero at the end of our unit tests
46 // to make sure everything is properly deleted.
50 class InstrumentedMergeSessionHelper
: public MergeSessionHelper
{
52 InstrumentedMergeSessionHelper(
53 OAuth2TokenService
* token_service
,
54 net::URLRequestContextGetter
* request_context
) :
55 MergeSessionHelper(token_service
, GaiaConstants::kChromeSource
,
56 request_context
, NULL
) {
60 virtual ~InstrumentedMergeSessionHelper() {
64 MOCK_METHOD0(StartFetching
, void());
65 MOCK_METHOD0(StartLogOutUrlFetch
, void());
68 DISALLOW_COPY_AND_ASSIGN(InstrumentedMergeSessionHelper
);
71 class MergeSessionHelperTest
: public testing::Test
{
73 MergeSessionHelperTest()
74 : no_error_(GoogleServiceAuthError::NONE
),
75 error_(GoogleServiceAuthError::SERVICE_ERROR
),
76 canceled_(GoogleServiceAuthError::REQUEST_CANCELED
),
77 request_context_getter_(new net::TestURLRequestContextGetter(
78 base::MessageLoopProxy::current())) {}
80 OAuth2TokenService
* token_service() { return &token_service_
; }
81 net::URLRequestContextGetter
* request_context() {
82 return request_context_getter_
.get();
85 void SimulateUbertokenFailure(UbertokenConsumer
* consumer
,
86 const GoogleServiceAuthError
& error
) {
87 consumer
->OnUbertokenFailure(error
);
90 void SimulateMergeSessionSuccess(GaiaAuthConsumer
* consumer
,
91 const std::string
& data
) {
92 consumer
->OnMergeSessionSuccess(data
);
95 void SimulateMergeSessionFailure(GaiaAuthConsumer
* consumer
,
96 const GoogleServiceAuthError
& error
) {
97 consumer
->OnMergeSessionFailure(error
);
100 void SimulateLogoutSuccess(net::URLFetcherDelegate
* consumer
) {
101 consumer
->OnURLFetchComplete(NULL
);
104 void SimulateGetCheckConnctionInfoSuccess(
105 net::TestURLFetcher
* fetcher
,
106 const std::string
& data
) {
107 fetcher
->set_status(net::URLRequestStatus());
108 fetcher
->set_response_code(200);
109 fetcher
->SetResponseString(data
);
110 fetcher
->delegate()->OnURLFetchComplete(fetcher
);
113 void SimulateGetCheckConnctionInfoResult(
114 net::URLFetcher
* fetcher
,
115 const std::string
& result
) {
116 net::TestURLFetcher
* test_fetcher
=
117 static_cast<net::TestURLFetcher
*>(fetcher
);
118 test_fetcher
->set_status(net::URLRequestStatus());
119 test_fetcher
->set_response_code(200);
120 test_fetcher
->SetResponseString(result
);
121 test_fetcher
->delegate()->OnURLFetchComplete(fetcher
);
124 const GoogleServiceAuthError
& no_error() { return no_error_
; }
125 const GoogleServiceAuthError
& error() { return error_
; }
126 const GoogleServiceAuthError
& canceled() { return canceled_
; }
128 net::TestURLFetcherFactory
* factory() { return &factory_
; }
131 base::MessageLoop message_loop_
;
132 net::TestURLFetcherFactory factory_
;
133 FakeOAuth2TokenService token_service_
;
134 GoogleServiceAuthError no_error_
;
135 GoogleServiceAuthError error_
;
136 GoogleServiceAuthError canceled_
;
137 scoped_refptr
<net::URLRequestContextGetter
> request_context_getter_
;
144 TEST_F(MergeSessionHelperTest
, Success
) {
145 InstrumentedMergeSessionHelper
helper(token_service(), request_context());
146 MockObserver
observer(&helper
);
148 EXPECT_CALL(helper
, StartFetching());
149 EXPECT_CALL(observer
, MergeSessionCompleted("acc1@gmail.com", no_error()));
151 helper
.LogIn("acc1@gmail.com");
152 SimulateMergeSessionSuccess(&helper
, "token");
155 TEST_F(MergeSessionHelperTest
, FailedMergeSession
) {
156 InstrumentedMergeSessionHelper
helper(token_service(), request_context());
157 MockObserver
observer(&helper
);
159 EXPECT_CALL(helper
, StartFetching());
160 EXPECT_CALL(observer
, MergeSessionCompleted("acc1@gmail.com", error()));
162 helper
.LogIn("acc1@gmail.com");
163 SimulateMergeSessionFailure(&helper
, error());
166 TEST_F(MergeSessionHelperTest
, FailedUbertoken
) {
167 InstrumentedMergeSessionHelper
helper(token_service(), request_context());
168 MockObserver
observer(&helper
);
170 EXPECT_CALL(helper
, StartFetching());
171 EXPECT_CALL(observer
, MergeSessionCompleted("acc1@gmail.com", error()));
173 helper
.LogIn("acc1@gmail.com");
174 SimulateUbertokenFailure(&helper
, error());
177 TEST_F(MergeSessionHelperTest
, ContinueAfterSuccess
) {
178 InstrumentedMergeSessionHelper
helper(token_service(), request_context());
179 MockObserver
observer(&helper
);
181 EXPECT_CALL(helper
, StartFetching()).Times(2);
182 EXPECT_CALL(observer
, MergeSessionCompleted("acc1@gmail.com", no_error()));
183 EXPECT_CALL(observer
, MergeSessionCompleted("acc2@gmail.com", no_error()));
185 helper
.LogIn("acc1@gmail.com");
186 helper
.LogIn("acc2@gmail.com");
187 SimulateMergeSessionSuccess(&helper
, "token1");
188 SimulateMergeSessionSuccess(&helper
, "token2");
191 TEST_F(MergeSessionHelperTest
, ContinueAfterFailure1
) {
192 InstrumentedMergeSessionHelper
helper(token_service(), request_context());
193 MockObserver
observer(&helper
);
195 EXPECT_CALL(helper
, StartFetching()).Times(2);
196 EXPECT_CALL(observer
, MergeSessionCompleted("acc1@gmail.com", error()));
197 EXPECT_CALL(observer
, MergeSessionCompleted("acc2@gmail.com", no_error()));
199 helper
.LogIn("acc1@gmail.com");
200 helper
.LogIn("acc2@gmail.com");
201 SimulateMergeSessionFailure(&helper
, error());
202 SimulateMergeSessionSuccess(&helper
, "token2");
205 TEST_F(MergeSessionHelperTest
, ContinueAfterFailure2
) {
206 InstrumentedMergeSessionHelper
helper(token_service(), request_context());
207 MockObserver
observer(&helper
);
209 EXPECT_CALL(helper
, StartFetching()).Times(2);
210 EXPECT_CALL(observer
, MergeSessionCompleted("acc1@gmail.com", error()));
211 EXPECT_CALL(observer
, MergeSessionCompleted("acc2@gmail.com", no_error()));
213 helper
.LogIn("acc1@gmail.com");
214 helper
.LogIn("acc2@gmail.com");
215 SimulateUbertokenFailure(&helper
, error());
216 SimulateMergeSessionSuccess(&helper
, "token2");
219 TEST_F(MergeSessionHelperTest
, AllRequestsInMultipleGoes
) {
220 InstrumentedMergeSessionHelper
helper(token_service(), request_context());
221 MockObserver
observer(&helper
);
223 EXPECT_CALL(helper
, StartFetching()).Times(4);
224 EXPECT_CALL(observer
, MergeSessionCompleted(_
, no_error())).Times(4);
226 helper
.LogIn("acc1@gmail.com");
227 helper
.LogIn("acc2@gmail.com");
229 SimulateMergeSessionSuccess(&helper
, "token1");
231 helper
.LogIn("acc3@gmail.com");
233 SimulateMergeSessionSuccess(&helper
, "token2");
234 SimulateMergeSessionSuccess(&helper
, "token3");
236 helper
.LogIn("acc4@gmail.com");
238 SimulateMergeSessionSuccess(&helper
, "token4");
241 TEST_F(MergeSessionHelperTest
, LogOut
) {
242 InstrumentedMergeSessionHelper
helper(token_service(), request_context());
243 MockObserver
observer(&helper
);
245 std::vector
<std::string
> current_accounts
;
246 current_accounts
.push_back("acc1@gmail.com");
247 current_accounts
.push_back("acc2@gmail.com");
248 current_accounts
.push_back("acc3@gmail.com");
250 EXPECT_CALL(helper
, StartLogOutUrlFetch());
251 EXPECT_CALL(helper
, StartFetching()).Times(2);
252 EXPECT_CALL(observer
, MergeSessionCompleted("acc1@gmail.com", no_error()));
253 EXPECT_CALL(observer
, MergeSessionCompleted("acc3@gmail.com", no_error()));
255 helper
.LogOut("acc2@gmail.com", current_accounts
);
256 SimulateLogoutSuccess(&helper
);
257 SimulateMergeSessionSuccess(&helper
, "token1");
258 SimulateMergeSessionSuccess(&helper
, "token3");
261 TEST_F(MergeSessionHelperTest
, PendingSigninThenSignout
) {
262 InstrumentedMergeSessionHelper
helper(token_service(), request_context());
263 MockObserver
observer(&helper
);
265 std::vector
<std::string
> current_accounts
;
266 current_accounts
.push_back("acc2@gmail.com");
267 current_accounts
.push_back("acc3@gmail.com");
269 // From the first Signin.
270 EXPECT_CALL(observer
, MergeSessionCompleted("acc1@gmail.com", no_error()));
272 // From the sign out and then re-sign in.
273 EXPECT_CALL(helper
, StartLogOutUrlFetch());
274 EXPECT_CALL(observer
, MergeSessionCompleted("acc3@gmail.com", no_error()));
276 // Total sign in 2 times, not enforcing ordered sequences.
277 EXPECT_CALL(helper
, StartFetching()).Times(2);
279 helper
.LogIn("acc1@gmail.com");
280 helper
.LogOut("acc2@gmail.com", current_accounts
);
282 SimulateMergeSessionSuccess(&helper
, "token1");
283 SimulateLogoutSuccess(&helper
);
284 SimulateMergeSessionSuccess(&helper
, "token3");
287 TEST_F(MergeSessionHelperTest
, CancelSignIn
) {
288 InstrumentedMergeSessionHelper
helper(token_service(), request_context());
289 MockObserver
observer(&helper
);
291 std::vector
<std::string
> current_accounts
;
293 EXPECT_CALL(helper
, StartFetching());
294 EXPECT_CALL(observer
, MergeSessionCompleted("acc2@gmail.com", canceled()));
295 EXPECT_CALL(observer
, MergeSessionCompleted("acc1@gmail.com", no_error()));
296 EXPECT_CALL(helper
, StartLogOutUrlFetch());
298 helper
.LogIn("acc1@gmail.com");
299 helper
.LogIn("acc2@gmail.com");
300 helper
.LogOut("acc2@gmail.com", current_accounts
);
302 SimulateMergeSessionSuccess(&helper
, "token1");
303 SimulateLogoutSuccess(&helper
);
306 TEST_F(MergeSessionHelperTest
, DoubleSignout
) {
307 InstrumentedMergeSessionHelper
helper(token_service(), request_context());
308 MockObserver
observer(&helper
);
310 std::vector
<std::string
> current_accounts1
;
311 current_accounts1
.push_back("acc1@gmail.com");
312 current_accounts1
.push_back("acc2@gmail.com");
313 current_accounts1
.push_back("acc3@gmail.com");
315 std::vector
<std::string
> current_accounts2
;
316 current_accounts2
.push_back("acc1@gmail.com");
317 current_accounts2
.push_back("acc3@gmail.com");
319 EXPECT_CALL(helper
, StartFetching()).Times(2);
320 EXPECT_CALL(observer
, MergeSessionCompleted("acc3@gmail.com", canceled()));
321 EXPECT_CALL(observer
,
322 MergeSessionCompleted("acc1@gmail.com", no_error())).Times(2);
323 EXPECT_CALL(helper
, StartLogOutUrlFetch());
325 helper
.LogIn("acc1@gmail.com");
326 helper
.LogOut("acc2@gmail.com", current_accounts1
);
327 helper
.LogOut("acc3@gmail.com", current_accounts2
);
329 SimulateMergeSessionSuccess(&helper
, "token1");
330 SimulateLogoutSuccess(&helper
);
331 SimulateMergeSessionSuccess(&helper
, "token1");
334 TEST_F(MergeSessionHelperTest
, ExternalCcResultFetcher
) {
335 InstrumentedMergeSessionHelper
helper(token_service(), request_context());
336 MergeSessionHelper::ExternalCcResultFetcher
result_fetcher(&helper
);
337 MockObserver
observer(&helper
);
338 EXPECT_CALL(observer
, GetCheckConnectionInfoCompleted(true));
339 result_fetcher
.Start();
341 // Simulate a successful completion of GetCheckConnctionInfo.
342 net::TestURLFetcher
* fetcher
= factory()->GetFetcherByID(0);
343 ASSERT_TRUE(NULL
!= fetcher
);
344 SimulateGetCheckConnctionInfoSuccess(fetcher
,
345 "[{\"carryBackToken\": \"yt\", \"url\": \"http://www.yt.com\"},"
346 " {\"carryBackToken\": \"bl\", \"url\": \"http://www.bl.com\"}]");
348 // Simulate responses for the two connection URLs.
349 MergeSessionHelper::ExternalCcResultFetcher::URLToTokenAndFetcher fetchers
=
350 result_fetcher
.get_fetcher_map_for_testing();
351 ASSERT_EQ(2u, fetchers
.size());
352 ASSERT_EQ(1u, fetchers
.count(GURL("http://www.yt.com")));
353 ASSERT_EQ(1u, fetchers
.count(GURL("http://www.bl.com")));
355 ASSERT_EQ("bl:null,yt:null", result_fetcher
.GetExternalCcResult());
356 SimulateGetCheckConnctionInfoResult(
357 fetchers
[GURL("http://www.yt.com")].second
, "yt_result");
358 ASSERT_EQ("bl:null,yt:yt_result", result_fetcher
.GetExternalCcResult());
359 SimulateGetCheckConnctionInfoResult(
360 fetchers
[GURL("http://www.bl.com")].second
, "bl_result");
361 ASSERT_EQ("bl:bl_result,yt:yt_result", result_fetcher
.GetExternalCcResult());
364 TEST_F(MergeSessionHelperTest
, ExternalCcResultFetcherTimeout
) {
365 InstrumentedMergeSessionHelper
helper(token_service(), request_context());
366 MergeSessionHelper::ExternalCcResultFetcher
result_fetcher(&helper
);
367 MockObserver
observer(&helper
);
368 EXPECT_CALL(observer
, GetCheckConnectionInfoCompleted(false));
369 result_fetcher
.Start();
371 // Simulate a successful completion of GetCheckConnctionInfo.
372 net::TestURLFetcher
* fetcher
= factory()->GetFetcherByID(0);
373 ASSERT_TRUE(NULL
!= fetcher
);
374 SimulateGetCheckConnctionInfoSuccess(fetcher
,
375 "[{\"carryBackToken\": \"yt\", \"url\": \"http://www.yt.com\"},"
376 " {\"carryBackToken\": \"bl\", \"url\": \"http://www.bl.com\"}]");
378 MergeSessionHelper::ExternalCcResultFetcher::URLToTokenAndFetcher fetchers
=
379 result_fetcher
.get_fetcher_map_for_testing();
380 ASSERT_EQ(2u, fetchers
.size());
381 ASSERT_EQ(1u, fetchers
.count(GURL("http://www.yt.com")));
382 ASSERT_EQ(1u, fetchers
.count(GURL("http://www.bl.com")));
384 // Simulate response only for "yt".
385 ASSERT_EQ("bl:null,yt:null", result_fetcher
.GetExternalCcResult());
386 SimulateGetCheckConnctionInfoResult(
387 fetchers
[GURL("http://www.yt.com")].second
, "yt_result");
388 ASSERT_EQ("bl:null,yt:yt_result", result_fetcher
.GetExternalCcResult());
391 result_fetcher
.TimeoutForTests();
392 ASSERT_EQ("bl:null,yt:yt_result", result_fetcher
.GetExternalCcResult());
393 fetchers
= result_fetcher
.get_fetcher_map_for_testing();
394 ASSERT_EQ(0u, fetchers
.size());
397 TEST_F(MergeSessionHelperTest
, ExternalCcResultFetcherTruncate
) {
398 InstrumentedMergeSessionHelper
helper(token_service(), request_context());
399 MergeSessionHelper::ExternalCcResultFetcher
result_fetcher(&helper
);
400 result_fetcher
.Start();
402 // Simulate a successful completion of GetCheckConnctionInfo.
403 net::TestURLFetcher
* fetcher
= factory()->GetFetcherByID(0);
404 ASSERT_TRUE(NULL
!= fetcher
);
405 SimulateGetCheckConnctionInfoSuccess(fetcher
,
406 "[{\"carryBackToken\": \"yt\", \"url\": \"http://www.yt.com\"}]");
408 MergeSessionHelper::ExternalCcResultFetcher::URLToTokenAndFetcher fetchers
=
409 result_fetcher
.get_fetcher_map_for_testing();
410 ASSERT_EQ(1u, fetchers
.size());
411 ASSERT_EQ(1u, fetchers
.count(GURL("http://www.yt.com")));
413 // Simulate response for "yt" with a string that is too long.
414 SimulateGetCheckConnctionInfoResult(
415 fetchers
[GURL("http://www.yt.com")].second
, "1234567890123456trunc");
416 ASSERT_EQ("yt:1234567890123456", result_fetcher
.GetExternalCcResult());