merge_session_helper_unittest.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
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. 4 5#include <algorithm> 6#include <string> 7#include <vector> 8 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" 20 21namespace { 22 23class MockObserver : public MergeSessionHelper::Observer { 24 public: 25 explicit MockObserver(MergeSessionHelper* helper) : helper_(helper) { 26 helper_->AddObserver(this); 27 } 28 29 ~MockObserver() { 30 helper_->RemoveObserver(this); 31 } 32 33 MOCK_METHOD2(MergeSessionCompleted, 34 void(const std::string&, 35 const GoogleServiceAuthError& )); 36 private: 37 MergeSessionHelper* helper_; 38 39 DISALLOW_COPY_AND_ASSIGN(MockObserver); 40}; 41 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. 45 46int total = 0; 47 48class InstrumentedMergeSessionHelper : public MergeSessionHelper { 49 public: 50 InstrumentedMergeSessionHelper( 51 OAuth2TokenService* token_service, 52 net::URLRequestContextGetter* request_context) : 53 MergeSessionHelper(token_service, request_context, NULL) { 54 total++; 55 } 56 57 virtual ~InstrumentedMergeSessionHelper() { 58 total--; 59 } 60 61 MOCK_METHOD0(StartFetching, void()); 62 MOCK_METHOD0(StartLogOutUrlFetch, void()); 63 64 private: 65 DISALLOW_COPY_AND_ASSIGN(InstrumentedMergeSessionHelper); 66}; 67 68class MergeSessionHelperTest : public testing::Test { 69 public: 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())) {} 76 77 OAuth2TokenService* token_service() { return &token_service_; } 78 net::URLRequestContextGetter* request_context() { 79 return request_context_getter_.get(); 80 } 81 82 void SimulateUbertokenFailure(UbertokenConsumer* consumer, 83 const GoogleServiceAuthError& error) { 84 consumer->OnUbertokenFailure(error); 85 } 86 87 void SimulateMergeSessionSuccess(GaiaAuthConsumer* consumer, 88 const std::string& data) { 89 consumer->OnMergeSessionSuccess(data); 90 } 91 92 void SimulateMergeSessionFailure(GaiaAuthConsumer* consumer, 93 const GoogleServiceAuthError& error) { 94 consumer->OnMergeSessionFailure(error); 95 } 96 97 void SimulateLogoutSuccess(net::URLFetcherDelegate* consumer) { 98 consumer->OnURLFetchComplete(NULL); 99 } 100 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); 108 } 109 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); 119 } 120 121 const GoogleServiceAuthError& no_error() { return no_error_; } 122 const GoogleServiceAuthError& error() { return error_; } 123 const GoogleServiceAuthError& canceled() { return canceled_; } 124 125 net::TestURLFetcherFactory* factory() { return &factory_; } 126 127 private: 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_; 135}; 136 137} // namespace 138 139using ::testing::_; 140 141TEST_F(MergeSessionHelperTest, Success) { 142 InstrumentedMergeSessionHelper helper(token_service(), request_context()); 143 MockObserver observer(&helper); 144 145 EXPECT_CALL(helper, StartFetching()); 146 EXPECT_CALL(observer, MergeSessionCompleted("acc1@gmail.com", no_error())); 147 148 helper.LogIn("acc1@gmail.com"); 149 SimulateMergeSessionSuccess(&helper, "token"); 150} 151 152TEST_F(MergeSessionHelperTest, FailedMergeSession) { 153 InstrumentedMergeSessionHelper helper(token_service(), request_context()); 154 MockObserver observer(&helper); 155 156 EXPECT_CALL(helper, StartFetching()); 157 EXPECT_CALL(observer, MergeSessionCompleted("acc1@gmail.com", error())); 158 159 helper.LogIn("acc1@gmail.com"); 160 SimulateMergeSessionFailure(&helper, error()); 161} 162 163TEST_F(MergeSessionHelperTest, FailedUbertoken) { 164 InstrumentedMergeSessionHelper helper(token_service(), request_context()); 165 MockObserver observer(&helper); 166 167 EXPECT_CALL(helper, StartFetching()); 168 EXPECT_CALL(observer, MergeSessionCompleted("acc1@gmail.com", error())); 169 170 helper.LogIn("acc1@gmail.com"); 171 SimulateUbertokenFailure(&helper, error()); 172} 173 174TEST_F(MergeSessionHelperTest, ContinueAfterSuccess) { 175 InstrumentedMergeSessionHelper helper(token_service(), request_context()); 176 MockObserver observer(&helper); 177 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())); 181 182 helper.LogIn("acc1@gmail.com"); 183 helper.LogIn("acc2@gmail.com"); 184 SimulateMergeSessionSuccess(&helper, "token1"); 185 SimulateMergeSessionSuccess(&helper, "token2"); 186} 187 188TEST_F(MergeSessionHelperTest, ContinueAfterFailure1) { 189 InstrumentedMergeSessionHelper helper(token_service(), request_context()); 190 MockObserver observer(&helper); 191 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())); 195 196 helper.LogIn("acc1@gmail.com"); 197 helper.LogIn("acc2@gmail.com"); 198 SimulateMergeSessionFailure(&helper, error()); 199 SimulateMergeSessionSuccess(&helper, "token2"); 200} 201 202TEST_F(MergeSessionHelperTest, ContinueAfterFailure2) { 203 InstrumentedMergeSessionHelper helper(token_service(), request_context()); 204 MockObserver observer(&helper); 205 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())); 209 210 helper.LogIn("acc1@gmail.com"); 211 helper.LogIn("acc2@gmail.com"); 212 SimulateUbertokenFailure(&helper, error()); 213 SimulateMergeSessionSuccess(&helper, "token2"); 214} 215 216TEST_F(MergeSessionHelperTest, AllRequestsInMultipleGoes) { 217 InstrumentedMergeSessionHelper helper(token_service(), request_context()); 218 MockObserver observer(&helper); 219 220 EXPECT_CALL(helper, StartFetching()).Times(4); 221 EXPECT_CALL(observer, MergeSessionCompleted(_, no_error())).Times(4); 222 223 helper.LogIn("acc1@gmail.com"); 224 helper.LogIn("acc2@gmail.com"); 225 226 SimulateMergeSessionSuccess(&helper, "token1"); 227 228 helper.LogIn("acc3@gmail.com"); 229 230 SimulateMergeSessionSuccess(&helper, "token2"); 231 SimulateMergeSessionSuccess(&helper, "token3"); 232 233 helper.LogIn("acc4@gmail.com"); 234 235 SimulateMergeSessionSuccess(&helper, "token4"); 236} 237 238TEST_F(MergeSessionHelperTest, LogOut) { 239 InstrumentedMergeSessionHelper helper(token_service(), request_context()); 240 MockObserver observer(&helper); 241 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"); 246 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())); 251 252 helper.LogOut("acc2@gmail.com", current_accounts); 253 SimulateLogoutSuccess(&helper); 254 SimulateMergeSessionSuccess(&helper, "token1"); 255 SimulateMergeSessionSuccess(&helper, "token3"); 256} 257 258TEST_F(MergeSessionHelperTest, PendingSigninThenSignout) { 259 InstrumentedMergeSessionHelper helper(token_service(), request_context()); 260 MockObserver observer(&helper); 261 262 std::vector<std::string> current_accounts; 263 current_accounts.push_back("acc2@gmail.com"); 264 current_accounts.push_back("acc3@gmail.com"); 265 266 // From the first Signin. 267 EXPECT_CALL(observer, MergeSessionCompleted("acc1@gmail.com", no_error())); 268 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())); 272 273 // Total sign in 2 times, not enforcing ordered sequences. 274 EXPECT_CALL(helper, StartFetching()).Times(2); 275 276 helper.LogIn("acc1@gmail.com"); 277 helper.LogOut("acc2@gmail.com", current_accounts); 278 279 SimulateMergeSessionSuccess(&helper, "token1"); 280 SimulateLogoutSuccess(&helper); 281 SimulateMergeSessionSuccess(&helper, "token3"); 282} 283 284TEST_F(MergeSessionHelperTest, CancelSignIn) { 285 InstrumentedMergeSessionHelper helper(token_service(), request_context()); 286 MockObserver observer(&helper); 287 288 std::vector<std::string> current_accounts; 289 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()); 294 295 helper.LogIn("acc1@gmail.com"); 296 helper.LogIn("acc2@gmail.com"); 297 helper.LogOut("acc2@gmail.com", current_accounts); 298 299 SimulateMergeSessionSuccess(&helper, "token1"); 300 SimulateLogoutSuccess(&helper); 301} 302 303TEST_F(MergeSessionHelperTest, DoubleSignout) { 304 InstrumentedMergeSessionHelper helper(token_service(), request_context()); 305 MockObserver observer(&helper); 306 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"); 311 312 std::vector<std::string> current_accounts2; 313 current_accounts2.push_back("acc1@gmail.com"); 314 current_accounts2.push_back("acc3@gmail.com"); 315 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()); 321 322 helper.LogIn("acc1@gmail.com"); 323 helper.LogOut("acc2@gmail.com", current_accounts1); 324 helper.LogOut("acc3@gmail.com", current_accounts2); 325 326 SimulateMergeSessionSuccess(&helper, "token1"); 327 SimulateLogoutSuccess(&helper); 328 SimulateMergeSessionSuccess(&helper, "token1"); 329} 330 331TEST_F(MergeSessionHelperTest, ExternalCcResultFetcher) { 332 InstrumentedMergeSessionHelper helper(token_service(), request_context()); 333 MergeSessionHelper::ExternalCcResultFetcher result_fetcher(&helper); 334 result_fetcher.Start(); 335 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\"}]"); 342 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"))); 349 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()); 357} 358 359TEST_F(MergeSessionHelperTest, ExternalCcResultFetcherTimeout) { 360 InstrumentedMergeSessionHelper helper(token_service(), request_context()); 361 MergeSessionHelper::ExternalCcResultFetcher result_fetcher(&helper); 362 result_fetcher.Start(); 363 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\"}]"); 370 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"))); 376 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()); 382 383 // Now timeout. 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()); 388} 389 390TEST_F(MergeSessionHelperTest, ExternalCcResultFetcherTruncate) { 391 InstrumentedMergeSessionHelper helper(token_service(), request_context()); 392 MergeSessionHelper::ExternalCcResultFetcher result_fetcher(&helper); 393 result_fetcher.Start(); 394 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\"}]"); 400 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"))); 405 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()); 410} 411