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 "components/gcm_driver/gcm_client_impl.h" 6 7#include "base/command_line.h" 8#include "base/files/scoped_temp_dir.h" 9#include "base/message_loop/message_loop.h" 10#include "base/run_loop.h" 11#include "base/strings/string_number_conversions.h" 12#include "base/time/clock.h" 13#include "google_apis/gcm/base/fake_encryptor.h" 14#include "google_apis/gcm/base/mcs_message.h" 15#include "google_apis/gcm/base/mcs_util.h" 16#include "google_apis/gcm/engine/fake_connection_factory.h" 17#include "google_apis/gcm/engine/fake_connection_handler.h" 18#include "google_apis/gcm/engine/gservices_settings.h" 19#include "google_apis/gcm/monitoring/gcm_stats_recorder.h" 20#include "google_apis/gcm/protocol/android_checkin.pb.h" 21#include "google_apis/gcm/protocol/checkin.pb.h" 22#include "google_apis/gcm/protocol/mcs.pb.h" 23#include "net/url_request/test_url_fetcher_factory.h" 24#include "net/url_request/url_fetcher_delegate.h" 25#include "net/url_request/url_request_test_util.h" 26#include "testing/gtest/include/gtest/gtest.h" 27 28namespace gcm { 29 30namespace { 31 32enum LastEvent { 33 NONE, 34 LOADING_COMPLETED, 35 REGISTRATION_COMPLETED, 36 UNREGISTRATION_COMPLETED, 37 MESSAGE_SEND_ERROR, 38 MESSAGE_SEND_ACK, 39 MESSAGE_RECEIVED, 40 MESSAGES_DELETED, 41}; 42 43const uint64 kDeviceAndroidId = 54321; 44const uint64 kDeviceSecurityToken = 12345; 45const int64 kSettingsCheckinInterval = 16 * 60 * 60; 46const char kAppId[] = "app_id"; 47const char kSender[] = "project_id"; 48const char kSender2[] = "project_id2"; 49const char kSender3[] = "project_id3"; 50const char kRegistrationResponsePrefix[] = "token="; 51const char kUnregistrationResponsePrefix[] = "deleted="; 52 53// Helper for building arbitrary data messages. 54MCSMessage BuildDownstreamMessage( 55 const std::string& project_id, 56 const std::string& app_id, 57 const std::map<std::string, std::string>& data) { 58 mcs_proto::DataMessageStanza data_message; 59 data_message.set_from(project_id); 60 data_message.set_category(app_id); 61 for (std::map<std::string, std::string>::const_iterator iter = data.begin(); 62 iter != data.end(); 63 ++iter) { 64 mcs_proto::AppData* app_data = data_message.add_app_data(); 65 app_data->set_key(iter->first); 66 app_data->set_value(iter->second); 67 } 68 return MCSMessage(kDataMessageStanzaTag, data_message); 69} 70 71class FakeMCSClient : public MCSClient { 72 public: 73 FakeMCSClient(base::Clock* clock, 74 ConnectionFactory* connection_factory, 75 GCMStore* gcm_store, 76 GCMStatsRecorder* recorder); 77 virtual ~FakeMCSClient(); 78 virtual void Login(uint64 android_id, uint64 security_token) OVERRIDE; 79 virtual void SendMessage(const MCSMessage& message) OVERRIDE; 80 81 uint64 last_android_id() const { return last_android_id_; } 82 uint64 last_security_token() const { return last_security_token_; } 83 uint8 last_message_tag() const { return last_message_tag_; } 84 const mcs_proto::DataMessageStanza& last_data_message_stanza() const { 85 return last_data_message_stanza_; 86 } 87 88 private: 89 uint64 last_android_id_; 90 uint64 last_security_token_; 91 uint8 last_message_tag_; 92 mcs_proto::DataMessageStanza last_data_message_stanza_; 93}; 94 95FakeMCSClient::FakeMCSClient(base::Clock* clock, 96 ConnectionFactory* connection_factory, 97 GCMStore* gcm_store, 98 GCMStatsRecorder* recorder) 99 : MCSClient("", clock, connection_factory, gcm_store, recorder), 100 last_android_id_(0u), 101 last_security_token_(0u), 102 last_message_tag_(kNumProtoTypes) { 103} 104 105FakeMCSClient::~FakeMCSClient() { 106} 107 108void FakeMCSClient::Login(uint64 android_id, uint64 security_token) { 109 last_android_id_ = android_id; 110 last_security_token_ = security_token; 111} 112 113void FakeMCSClient::SendMessage(const MCSMessage& message) { 114 last_message_tag_ = message.tag(); 115 if (last_message_tag_ == kDataMessageStanzaTag) { 116 last_data_message_stanza_.CopyFrom( 117 reinterpret_cast<const mcs_proto::DataMessageStanza&>( 118 message.GetProtobuf())); 119 } 120} 121 122class AutoAdvancingTestClock : public base::Clock { 123 public: 124 explicit AutoAdvancingTestClock(base::TimeDelta auto_increment_time_delta); 125 virtual ~AutoAdvancingTestClock(); 126 127 virtual base::Time Now() OVERRIDE; 128 void Advance(TimeDelta delta); 129 int call_count() const { return call_count_; } 130 131 private: 132 int call_count_; 133 base::TimeDelta auto_increment_time_delta_; 134 base::Time now_; 135 136 DISALLOW_COPY_AND_ASSIGN(AutoAdvancingTestClock); 137}; 138 139AutoAdvancingTestClock::AutoAdvancingTestClock( 140 base::TimeDelta auto_increment_time_delta) 141 : call_count_(0), auto_increment_time_delta_(auto_increment_time_delta) { 142} 143 144AutoAdvancingTestClock::~AutoAdvancingTestClock() { 145} 146 147base::Time AutoAdvancingTestClock::Now() { 148 call_count_++; 149 now_ += auto_increment_time_delta_; 150 return now_; 151} 152 153void AutoAdvancingTestClock::Advance(base::TimeDelta delta) { 154 now_ += delta; 155} 156 157class FakeGCMInternalsBuilder : public GCMInternalsBuilder { 158 public: 159 FakeGCMInternalsBuilder(base::TimeDelta clock_step); 160 virtual ~FakeGCMInternalsBuilder(); 161 162 virtual scoped_ptr<base::Clock> BuildClock() OVERRIDE; 163 virtual scoped_ptr<MCSClient> BuildMCSClient( 164 const std::string& version, 165 base::Clock* clock, 166 ConnectionFactory* connection_factory, 167 GCMStore* gcm_store, 168 GCMStatsRecorder* recorder) OVERRIDE; 169 virtual scoped_ptr<ConnectionFactory> BuildConnectionFactory( 170 const std::vector<GURL>& endpoints, 171 const net::BackoffEntry::Policy& backoff_policy, 172 const scoped_refptr<net::HttpNetworkSession>& gcm_network_session, 173 const scoped_refptr<net::HttpNetworkSession>& http_network_session, 174 net::NetLog* net_log, 175 GCMStatsRecorder* recorder) OVERRIDE; 176 177 private: 178 base::TimeDelta clock_step_; 179}; 180 181FakeGCMInternalsBuilder::FakeGCMInternalsBuilder(base::TimeDelta clock_step) 182 : clock_step_(clock_step) { 183} 184 185FakeGCMInternalsBuilder::~FakeGCMInternalsBuilder() {} 186 187scoped_ptr<base::Clock> FakeGCMInternalsBuilder::BuildClock() { 188 return make_scoped_ptr<base::Clock>(new AutoAdvancingTestClock(clock_step_)); 189} 190 191scoped_ptr<MCSClient> FakeGCMInternalsBuilder::BuildMCSClient( 192 const std::string& version, 193 base::Clock* clock, 194 ConnectionFactory* connection_factory, 195 GCMStore* gcm_store, 196 GCMStatsRecorder* recorder) { 197 return make_scoped_ptr<MCSClient>(new FakeMCSClient(clock, 198 connection_factory, 199 gcm_store, 200 recorder)); 201} 202 203scoped_ptr<ConnectionFactory> FakeGCMInternalsBuilder::BuildConnectionFactory( 204 const std::vector<GURL>& endpoints, 205 const net::BackoffEntry::Policy& backoff_policy, 206 const scoped_refptr<net::HttpNetworkSession>& gcm_network_session, 207 const scoped_refptr<net::HttpNetworkSession>& http_network_session, 208 net::NetLog* net_log, 209 GCMStatsRecorder* recorder) { 210 return make_scoped_ptr<ConnectionFactory>(new FakeConnectionFactory()); 211} 212 213} // namespace 214 215class GCMClientImplTest : public testing::Test, 216 public GCMClient::Delegate { 217 public: 218 GCMClientImplTest(); 219 virtual ~GCMClientImplTest(); 220 221 virtual void SetUp() OVERRIDE; 222 223 void BuildGCMClient(base::TimeDelta clock_step); 224 void InitializeGCMClient(); 225 void StartGCMClient(); 226 void ReceiveMessageFromMCS(const MCSMessage& message); 227 void ReceiveOnMessageSentToMCS( 228 const std::string& app_id, 229 const std::string& message_id, 230 const MCSClient::MessageSendStatus status); 231 void CompleteCheckin(uint64 android_id, 232 uint64 security_token, 233 const std::string& digest, 234 const std::map<std::string, std::string>& settings); 235 void CompleteRegistration(const std::string& registration_id); 236 void CompleteUnregistration(const std::string& app_id); 237 238 bool ExistsRegistration(const std::string& app_id) const; 239 void AddRegistration(const std::string& app_id, 240 const std::vector<std::string>& sender_ids, 241 const std::string& registration_id); 242 243 // GCMClient::Delegate overrides (for verification). 244 virtual void OnRegisterFinished(const std::string& app_id, 245 const std::string& registration_id, 246 GCMClient::Result result) OVERRIDE; 247 virtual void OnUnregisterFinished(const std::string& app_id, 248 GCMClient::Result result) OVERRIDE; 249 virtual void OnSendFinished(const std::string& app_id, 250 const std::string& message_id, 251 GCMClient::Result result) OVERRIDE {} 252 virtual void OnMessageReceived(const std::string& registration_id, 253 const GCMClient::IncomingMessage& message) 254 OVERRIDE; 255 virtual void OnMessagesDeleted(const std::string& app_id) OVERRIDE; 256 virtual void OnMessageSendError( 257 const std::string& app_id, 258 const gcm::GCMClient::SendErrorDetails& send_error_details) OVERRIDE; 259 virtual void OnSendAcknowledged(const std::string& app_id, 260 const std::string& message_id) OVERRIDE; 261 virtual void OnGCMReady( 262 const std::vector<AccountMapping>& account_mappings) OVERRIDE; 263 virtual void OnActivityRecorded() OVERRIDE {} 264 virtual void OnConnected(const net::IPEndPoint& ip_endpoint) OVERRIDE {} 265 virtual void OnDisconnected() OVERRIDE {} 266 267 GCMClientImpl* gcm_client() const { return gcm_client_.get(); } 268 FakeMCSClient* mcs_client() const { 269 return reinterpret_cast<FakeMCSClient*>(gcm_client_->mcs_client_.get()); 270 } 271 ConnectionFactory* connection_factory() const { 272 return gcm_client_->connection_factory_.get(); 273 } 274 275 const GCMClientImpl::CheckinInfo& device_checkin_info() const { 276 return gcm_client_->device_checkin_info_; 277 } 278 279 void reset_last_event() { 280 last_event_ = NONE; 281 last_app_id_.clear(); 282 last_registration_id_.clear(); 283 last_message_id_.clear(); 284 last_result_ = GCMClient::UNKNOWN_ERROR; 285 } 286 287 LastEvent last_event() const { return last_event_; } 288 const std::string& last_app_id() const { return last_app_id_; } 289 const std::string& last_registration_id() const { 290 return last_registration_id_; 291 } 292 const std::string& last_message_id() const { return last_message_id_; } 293 GCMClient::Result last_result() const { return last_result_; } 294 const GCMClient::IncomingMessage& last_message() const { 295 return last_message_; 296 } 297 const GCMClient::SendErrorDetails& last_error_details() const { 298 return last_error_details_; 299 } 300 301 const GServicesSettings& gservices_settings() const { 302 return gcm_client_->gservices_settings_; 303 } 304 305 int64 CurrentTime(); 306 307 // Tooling. 308 void PumpLoop(); 309 void PumpLoopUntilIdle(); 310 void QuitLoop(); 311 void InitializeLoop(); 312 bool CreateUniqueTempDir(); 313 AutoAdvancingTestClock* clock() const { 314 return reinterpret_cast<AutoAdvancingTestClock*>(gcm_client_->clock_.get()); 315 } 316 317 private: 318 // Variables used for verification. 319 LastEvent last_event_; 320 std::string last_app_id_; 321 std::string last_registration_id_; 322 std::string last_message_id_; 323 GCMClient::Result last_result_; 324 GCMClient::IncomingMessage last_message_; 325 GCMClient::SendErrorDetails last_error_details_; 326 327 scoped_ptr<GCMClientImpl> gcm_client_; 328 329 base::MessageLoop message_loop_; 330 scoped_ptr<base::RunLoop> run_loop_; 331 net::TestURLFetcherFactory url_fetcher_factory_; 332 333 // Injected to GCM client: 334 base::ScopedTempDir temp_directory_; 335 scoped_refptr<net::TestURLRequestContextGetter> url_request_context_getter_; 336}; 337 338GCMClientImplTest::GCMClientImplTest() 339 : last_event_(NONE), 340 last_result_(GCMClient::UNKNOWN_ERROR), 341 url_request_context_getter_(new net::TestURLRequestContextGetter( 342 message_loop_.message_loop_proxy())) { 343} 344 345GCMClientImplTest::~GCMClientImplTest() {} 346 347void GCMClientImplTest::SetUp() { 348 testing::Test::SetUp(); 349 ASSERT_TRUE(CreateUniqueTempDir()); 350 InitializeLoop(); 351 BuildGCMClient(base::TimeDelta()); 352 InitializeGCMClient(); 353 StartGCMClient(); 354 CompleteCheckin(kDeviceAndroidId, 355 kDeviceSecurityToken, 356 std::string(), 357 std::map<std::string, std::string>()); 358} 359 360void GCMClientImplTest::PumpLoop() { 361 run_loop_->Run(); 362 run_loop_.reset(new base::RunLoop()); 363} 364 365void GCMClientImplTest::PumpLoopUntilIdle() { 366 run_loop_->RunUntilIdle(); 367 run_loop_.reset(new base::RunLoop()); 368} 369 370void GCMClientImplTest::QuitLoop() { 371 if (run_loop_ && run_loop_->running()) 372 run_loop_->Quit(); 373} 374 375void GCMClientImplTest::InitializeLoop() { 376 run_loop_.reset(new base::RunLoop); 377} 378 379bool GCMClientImplTest::CreateUniqueTempDir() { 380 return temp_directory_.CreateUniqueTempDir(); 381} 382 383void GCMClientImplTest::BuildGCMClient(base::TimeDelta clock_step) { 384 gcm_client_.reset(new GCMClientImpl(make_scoped_ptr<GCMInternalsBuilder>( 385 new FakeGCMInternalsBuilder(clock_step)))); 386} 387 388void GCMClientImplTest::CompleteCheckin( 389 uint64 android_id, 390 uint64 security_token, 391 const std::string& digest, 392 const std::map<std::string, std::string>& settings) { 393 checkin_proto::AndroidCheckinResponse response; 394 response.set_stats_ok(true); 395 response.set_android_id(android_id); 396 response.set_security_token(security_token); 397 398 // For testing G-services settings. 399 if (!digest.empty()) { 400 response.set_digest(digest); 401 for (std::map<std::string, std::string>::const_iterator it = 402 settings.begin(); 403 it != settings.end(); 404 ++it) { 405 checkin_proto::GservicesSetting* setting = response.add_setting(); 406 setting->set_name(it->first); 407 setting->set_value(it->second); 408 } 409 response.set_settings_diff(false); 410 } 411 412 std::string response_string; 413 response.SerializeToString(&response_string); 414 415 net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0); 416 ASSERT_TRUE(fetcher); 417 fetcher->set_response_code(net::HTTP_OK); 418 fetcher->SetResponseString(response_string); 419 fetcher->delegate()->OnURLFetchComplete(fetcher); 420 url_fetcher_factory_.RemoveFetcherFromMap(0); 421} 422 423void GCMClientImplTest::CompleteRegistration( 424 const std::string& registration_id) { 425 std::string response(kRegistrationResponsePrefix); 426 response.append(registration_id); 427 net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0); 428 ASSERT_TRUE(fetcher); 429 fetcher->set_response_code(net::HTTP_OK); 430 fetcher->SetResponseString(response); 431 fetcher->delegate()->OnURLFetchComplete(fetcher); 432 url_fetcher_factory_.RemoveFetcherFromMap(0); 433} 434 435void GCMClientImplTest::CompleteUnregistration( 436 const std::string& app_id) { 437 std::string response(kUnregistrationResponsePrefix); 438 response.append(app_id); 439 net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0); 440 ASSERT_TRUE(fetcher); 441 fetcher->set_response_code(net::HTTP_OK); 442 fetcher->SetResponseString(response); 443 fetcher->delegate()->OnURLFetchComplete(fetcher); 444 url_fetcher_factory_.RemoveFetcherFromMap(0); 445} 446 447bool GCMClientImplTest::ExistsRegistration(const std::string& app_id) const { 448 return gcm_client_->registrations_.count(app_id) > 0; 449} 450 451void GCMClientImplTest::AddRegistration( 452 const std::string& app_id, 453 const std::vector<std::string>& sender_ids, 454 const std::string& registration_id) { 455 linked_ptr<RegistrationInfo> registration(new RegistrationInfo); 456 registration->sender_ids = sender_ids; 457 registration->registration_id = registration_id; 458 gcm_client_->registrations_[app_id] = registration; 459} 460 461void GCMClientImplTest::InitializeGCMClient() { 462 clock()->Advance(base::TimeDelta::FromMilliseconds(1)); 463 464 // Actual initialization. 465 GCMClient::ChromeBuildInfo chrome_build_info; 466 gcm_client_->Initialize(chrome_build_info, 467 temp_directory_.path(), 468 message_loop_.message_loop_proxy(), 469 url_request_context_getter_, 470 make_scoped_ptr<Encryptor>(new FakeEncryptor), 471 this); 472} 473 474void GCMClientImplTest::StartGCMClient() { 475 // Start loading and check-in. 476 gcm_client_->Start(); 477 478 PumpLoopUntilIdle(); 479} 480 481void GCMClientImplTest::ReceiveMessageFromMCS(const MCSMessage& message) { 482 gcm_client_->recorder_.RecordConnectionInitiated(std::string()); 483 gcm_client_->recorder_.RecordConnectionSuccess(); 484 gcm_client_->OnMessageReceivedFromMCS(message); 485} 486 487void GCMClientImplTest::ReceiveOnMessageSentToMCS( 488 const std::string& app_id, 489 const std::string& message_id, 490 const MCSClient::MessageSendStatus status) { 491 gcm_client_->OnMessageSentToMCS(0LL, app_id, message_id, status); 492} 493 494void GCMClientImplTest::OnGCMReady( 495 const std::vector<AccountMapping>& account_mappings) { 496 last_event_ = LOADING_COMPLETED; 497 QuitLoop(); 498 // TODO(fgorski): Add scenario verifying contents of account_mappings, when 499 // the list is not empty. 500} 501 502void GCMClientImplTest::OnMessageReceived( 503 const std::string& registration_id, 504 const GCMClient::IncomingMessage& message) { 505 last_event_ = MESSAGE_RECEIVED; 506 last_app_id_ = registration_id; 507 last_message_ = message; 508 QuitLoop(); 509} 510 511void GCMClientImplTest::OnRegisterFinished(const std::string& app_id, 512 const std::string& registration_id, 513 GCMClient::Result result) { 514 last_event_ = REGISTRATION_COMPLETED; 515 last_app_id_ = app_id; 516 last_registration_id_ = registration_id; 517 last_result_ = result; 518} 519 520void GCMClientImplTest::OnUnregisterFinished(const std::string& app_id, 521 GCMClient::Result result) { 522 last_event_ = UNREGISTRATION_COMPLETED; 523 last_app_id_ = app_id; 524 last_result_ = result; 525} 526 527void GCMClientImplTest::OnMessagesDeleted(const std::string& app_id) { 528 last_event_ = MESSAGES_DELETED; 529 last_app_id_ = app_id; 530} 531 532void GCMClientImplTest::OnMessageSendError( 533 const std::string& app_id, 534 const gcm::GCMClient::SendErrorDetails& send_error_details) { 535 last_event_ = MESSAGE_SEND_ERROR; 536 last_app_id_ = app_id; 537 last_error_details_ = send_error_details; 538} 539 540void GCMClientImplTest::OnSendAcknowledged(const std::string& app_id, 541 const std::string& message_id) { 542 last_event_ = MESSAGE_SEND_ACK; 543 last_app_id_ = app_id; 544 last_message_id_ = message_id; 545} 546 547int64 GCMClientImplTest::CurrentTime() { 548 return clock()->Now().ToInternalValue() / base::Time::kMicrosecondsPerSecond; 549} 550 551TEST_F(GCMClientImplTest, LoadingCompleted) { 552 EXPECT_EQ(LOADING_COMPLETED, last_event()); 553 EXPECT_EQ(kDeviceAndroidId, mcs_client()->last_android_id()); 554 EXPECT_EQ(kDeviceSecurityToken, mcs_client()->last_security_token()); 555 556 // Checking freshly loaded CheckinInfo. 557 EXPECT_EQ(kDeviceAndroidId, device_checkin_info().android_id); 558 EXPECT_EQ(kDeviceSecurityToken, device_checkin_info().secret); 559 EXPECT_TRUE(device_checkin_info().last_checkin_accounts.empty()); 560 EXPECT_TRUE(device_checkin_info().accounts_set); 561 EXPECT_TRUE(device_checkin_info().account_tokens.empty()); 562} 563 564TEST_F(GCMClientImplTest, CheckOut) { 565 EXPECT_TRUE(mcs_client()); 566 EXPECT_TRUE(connection_factory()); 567 gcm_client()->CheckOut(); 568 EXPECT_FALSE(mcs_client()); 569 EXPECT_FALSE(connection_factory()); 570} 571 572TEST_F(GCMClientImplTest, RegisterApp) { 573 EXPECT_FALSE(ExistsRegistration(kAppId)); 574 575 std::vector<std::string> senders; 576 senders.push_back("sender"); 577 gcm_client()->Register(kAppId, senders); 578 CompleteRegistration("reg_id"); 579 580 EXPECT_EQ(REGISTRATION_COMPLETED, last_event()); 581 EXPECT_EQ(kAppId, last_app_id()); 582 EXPECT_EQ("reg_id", last_registration_id()); 583 EXPECT_EQ(GCMClient::SUCCESS, last_result()); 584 EXPECT_TRUE(ExistsRegistration(kAppId)); 585} 586 587TEST_F(GCMClientImplTest, DISABLED_RegisterAppFromCache) { 588 EXPECT_FALSE(ExistsRegistration(kAppId)); 589 590 std::vector<std::string> senders; 591 senders.push_back("sender"); 592 gcm_client()->Register(kAppId, senders); 593 CompleteRegistration("reg_id"); 594 EXPECT_TRUE(ExistsRegistration(kAppId)); 595 596 EXPECT_EQ(kAppId, last_app_id()); 597 EXPECT_EQ("reg_id", last_registration_id()); 598 EXPECT_EQ(GCMClient::SUCCESS, last_result()); 599 EXPECT_EQ(REGISTRATION_COMPLETED, last_event()); 600 601 // Recreate GCMClient in order to load from the persistent store. 602 BuildGCMClient(base::TimeDelta()); 603 InitializeGCMClient(); 604 StartGCMClient(); 605 606 EXPECT_TRUE(ExistsRegistration(kAppId)); 607} 608 609TEST_F(GCMClientImplTest, UnregisterApp) { 610 EXPECT_FALSE(ExistsRegistration(kAppId)); 611 612 std::vector<std::string> senders; 613 senders.push_back("sender"); 614 gcm_client()->Register(kAppId, senders); 615 CompleteRegistration("reg_id"); 616 EXPECT_TRUE(ExistsRegistration(kAppId)); 617 618 gcm_client()->Unregister(kAppId); 619 CompleteUnregistration(kAppId); 620 621 EXPECT_EQ(UNREGISTRATION_COMPLETED, last_event()); 622 EXPECT_EQ(kAppId, last_app_id()); 623 EXPECT_EQ(GCMClient::SUCCESS, last_result()); 624 EXPECT_FALSE(ExistsRegistration(kAppId)); 625} 626 627TEST_F(GCMClientImplTest, DispatchDownstreamMessage) { 628 // Register to receive messages from kSender and kSender2 only. 629 std::vector<std::string> senders; 630 senders.push_back(kSender); 631 senders.push_back(kSender2); 632 AddRegistration(kAppId, senders, "reg_id"); 633 634 std::map<std::string, std::string> expected_data; 635 expected_data["message_type"] = "gcm"; 636 expected_data["key"] = "value"; 637 expected_data["key2"] = "value2"; 638 639 // Message for kSender will be received. 640 MCSMessage message(BuildDownstreamMessage(kSender, kAppId, expected_data)); 641 EXPECT_TRUE(message.IsValid()); 642 ReceiveMessageFromMCS(message); 643 644 expected_data.erase(expected_data.find("message_type")); 645 EXPECT_EQ(MESSAGE_RECEIVED, last_event()); 646 EXPECT_EQ(kAppId, last_app_id()); 647 EXPECT_EQ(expected_data.size(), last_message().data.size()); 648 EXPECT_EQ(expected_data, last_message().data); 649 EXPECT_EQ(kSender, last_message().sender_id); 650 651 reset_last_event(); 652 653 // Message for kSender2 will be received. 654 MCSMessage message2(BuildDownstreamMessage(kSender2, kAppId, expected_data)); 655 EXPECT_TRUE(message2.IsValid()); 656 ReceiveMessageFromMCS(message2); 657 658 EXPECT_EQ(MESSAGE_RECEIVED, last_event()); 659 EXPECT_EQ(kAppId, last_app_id()); 660 EXPECT_EQ(expected_data.size(), last_message().data.size()); 661 EXPECT_EQ(expected_data, last_message().data); 662 EXPECT_EQ(kSender2, last_message().sender_id); 663 664 reset_last_event(); 665 666 // Message from kSender3 will be dropped. 667 MCSMessage message3(BuildDownstreamMessage(kSender3, kAppId, expected_data)); 668 EXPECT_TRUE(message3.IsValid()); 669 ReceiveMessageFromMCS(message3); 670 671 EXPECT_NE(MESSAGE_RECEIVED, last_event()); 672 EXPECT_NE(kAppId, last_app_id()); 673} 674 675TEST_F(GCMClientImplTest, DispatchDownstreamMessageSendError) { 676 std::map<std::string, std::string> expected_data; 677 expected_data["message_type"] = "send_error"; 678 expected_data["google.message_id"] = "007"; 679 expected_data["error_details"] = "some details"; 680 MCSMessage message(BuildDownstreamMessage( 681 kSender, kAppId, expected_data)); 682 EXPECT_TRUE(message.IsValid()); 683 ReceiveMessageFromMCS(message); 684 685 EXPECT_EQ(MESSAGE_SEND_ERROR, last_event()); 686 EXPECT_EQ(kAppId, last_app_id()); 687 EXPECT_EQ("007", last_error_details().message_id); 688 EXPECT_EQ(1UL, last_error_details().additional_data.size()); 689 GCMClient::MessageData::const_iterator iter = 690 last_error_details().additional_data.find("error_details"); 691 EXPECT_TRUE(iter != last_error_details().additional_data.end()); 692 EXPECT_EQ("some details", iter->second); 693} 694 695TEST_F(GCMClientImplTest, DispatchDownstreamMessgaesDeleted) { 696 std::map<std::string, std::string> expected_data; 697 expected_data["message_type"] = "deleted_messages"; 698 MCSMessage message(BuildDownstreamMessage( 699 kSender, kAppId, expected_data)); 700 EXPECT_TRUE(message.IsValid()); 701 ReceiveMessageFromMCS(message); 702 703 EXPECT_EQ(MESSAGES_DELETED, last_event()); 704 EXPECT_EQ(kAppId, last_app_id()); 705} 706 707TEST_F(GCMClientImplTest, SendMessage) { 708 GCMClient::OutgoingMessage message; 709 message.id = "007"; 710 message.time_to_live = 500; 711 message.data["key"] = "value"; 712 gcm_client()->Send(kAppId, kSender, message); 713 714 EXPECT_EQ(kDataMessageStanzaTag, mcs_client()->last_message_tag()); 715 EXPECT_EQ(kAppId, mcs_client()->last_data_message_stanza().category()); 716 EXPECT_EQ(kSender, mcs_client()->last_data_message_stanza().to()); 717 EXPECT_EQ(500, mcs_client()->last_data_message_stanza().ttl()); 718 EXPECT_EQ(CurrentTime(), mcs_client()->last_data_message_stanza().sent()); 719 EXPECT_EQ("007", mcs_client()->last_data_message_stanza().id()); 720 EXPECT_EQ("gcm@chrome.com", mcs_client()->last_data_message_stanza().from()); 721 EXPECT_EQ(kSender, mcs_client()->last_data_message_stanza().to()); 722 EXPECT_EQ("key", mcs_client()->last_data_message_stanza().app_data(0).key()); 723 EXPECT_EQ("value", 724 mcs_client()->last_data_message_stanza().app_data(0).value()); 725} 726 727TEST_F(GCMClientImplTest, SendMessageAcknowledged) { 728 ReceiveOnMessageSentToMCS(kAppId, "007", MCSClient::SENT); 729 EXPECT_EQ(MESSAGE_SEND_ACK, last_event()); 730 EXPECT_EQ(kAppId, last_app_id()); 731 EXPECT_EQ("007", last_message_id()); 732} 733 734class GCMClientImplCheckinTest : public GCMClientImplTest { 735 public: 736 GCMClientImplCheckinTest(); 737 virtual ~GCMClientImplCheckinTest(); 738 739 virtual void SetUp() OVERRIDE; 740}; 741 742GCMClientImplCheckinTest::GCMClientImplCheckinTest() { 743} 744 745GCMClientImplCheckinTest::~GCMClientImplCheckinTest() { 746} 747 748void GCMClientImplCheckinTest::SetUp() { 749 testing::Test::SetUp(); 750 // Creating unique temp directory that will be used by GCMStore shared between 751 // GCM Client and G-services settings. 752 ASSERT_TRUE(CreateUniqueTempDir()); 753 InitializeLoop(); 754 // Time will be advancing one hour every time it is checked. 755 BuildGCMClient(base::TimeDelta::FromSeconds(kSettingsCheckinInterval)); 756 InitializeGCMClient(); 757 StartGCMClient(); 758} 759 760TEST_F(GCMClientImplCheckinTest, GServicesSettingsAfterInitialCheckin) { 761 std::map<std::string, std::string> settings; 762 settings["checkin_interval"] = base::Int64ToString(kSettingsCheckinInterval); 763 settings["checkin_url"] = "http://alternative.url/checkin"; 764 settings["gcm_hostname"] = "alternative.gcm.host"; 765 settings["gcm_secure_port"] = "7777"; 766 settings["gcm_registration_url"] = "http://alternative.url/registration"; 767 CompleteCheckin(kDeviceAndroidId, 768 kDeviceSecurityToken, 769 GServicesSettings::CalculateDigest(settings), 770 settings); 771 EXPECT_EQ(base::TimeDelta::FromSeconds(kSettingsCheckinInterval), 772 gservices_settings().GetCheckinInterval()); 773 EXPECT_EQ(GURL("http://alternative.url/checkin"), 774 gservices_settings().GetCheckinURL()); 775 EXPECT_EQ(GURL("http://alternative.url/registration"), 776 gservices_settings().GetRegistrationURL()); 777 EXPECT_EQ(GURL("https://alternative.gcm.host:7777"), 778 gservices_settings().GetMCSMainEndpoint()); 779 EXPECT_EQ(GURL("https://alternative.gcm.host:443"), 780 gservices_settings().GetMCSFallbackEndpoint()); 781} 782 783// This test only checks that periodic checkin happens. 784TEST_F(GCMClientImplCheckinTest, PeriodicCheckin) { 785 std::map<std::string, std::string> settings; 786 settings["checkin_interval"] = base::IntToString(kSettingsCheckinInterval); 787 settings["checkin_url"] = "http://alternative.url/checkin"; 788 settings["gcm_hostname"] = "alternative.gcm.host"; 789 settings["gcm_secure_port"] = "7777"; 790 settings["gcm_registration_url"] = "http://alternative.url/registration"; 791 CompleteCheckin(kDeviceAndroidId, 792 kDeviceSecurityToken, 793 GServicesSettings::CalculateDigest(settings), 794 settings); 795 796 EXPECT_EQ(2, clock()->call_count()); 797 798 PumpLoopUntilIdle(); 799 CompleteCheckin(kDeviceAndroidId, 800 kDeviceSecurityToken, 801 GServicesSettings::CalculateDigest(settings), 802 settings); 803} 804 805TEST_F(GCMClientImplCheckinTest, LoadGSettingsFromStore) { 806 std::map<std::string, std::string> settings; 807 settings["checkin_interval"] = base::IntToString(kSettingsCheckinInterval); 808 settings["checkin_url"] = "http://alternative.url/checkin"; 809 settings["gcm_hostname"] = "alternative.gcm.host"; 810 settings["gcm_secure_port"] = "7777"; 811 settings["gcm_registration_url"] = "http://alternative.url/registration"; 812 CompleteCheckin(kDeviceAndroidId, 813 kDeviceSecurityToken, 814 GServicesSettings::CalculateDigest(settings), 815 settings); 816 817 BuildGCMClient(base::TimeDelta()); 818 InitializeGCMClient(); 819 StartGCMClient(); 820 821 EXPECT_EQ(base::TimeDelta::FromSeconds(kSettingsCheckinInterval), 822 gservices_settings().GetCheckinInterval()); 823 EXPECT_EQ(GURL("http://alternative.url/checkin"), 824 gservices_settings().GetCheckinURL()); 825 EXPECT_EQ(GURL("http://alternative.url/registration"), 826 gservices_settings().GetRegistrationURL()); 827 EXPECT_EQ(GURL("https://alternative.gcm.host:7777"), 828 gservices_settings().GetMCSMainEndpoint()); 829 EXPECT_EQ(GURL("https://alternative.gcm.host:443"), 830 gservices_settings().GetMCSFallbackEndpoint()); 831} 832 833// This test only checks that periodic checkin happens. 834TEST_F(GCMClientImplCheckinTest, CheckinWithAccounts) { 835 std::map<std::string, std::string> settings; 836 settings["checkin_interval"] = base::IntToString(kSettingsCheckinInterval); 837 settings["checkin_url"] = "http://alternative.url/checkin"; 838 settings["gcm_hostname"] = "alternative.gcm.host"; 839 settings["gcm_secure_port"] = "7777"; 840 settings["gcm_registration_url"] = "http://alternative.url/registration"; 841 CompleteCheckin(kDeviceAndroidId, 842 kDeviceSecurityToken, 843 GServicesSettings::CalculateDigest(settings), 844 settings); 845 846 std::map<std::string, std::string> account_tokens; 847 account_tokens["test_user1@gmail.com"] = "token1"; 848 account_tokens["test_user2@gmail.com"] = "token2"; 849 gcm_client()->SetAccountsForCheckin(account_tokens); 850 851 EXPECT_TRUE(device_checkin_info().last_checkin_accounts.empty()); 852 EXPECT_TRUE(device_checkin_info().accounts_set); 853 EXPECT_EQ(account_tokens, device_checkin_info().account_tokens); 854 855 PumpLoopUntilIdle(); 856 CompleteCheckin(kDeviceAndroidId, 857 kDeviceSecurityToken, 858 GServicesSettings::CalculateDigest(settings), 859 settings); 860 861 std::set<std::string> accounts; 862 accounts.insert("test_user1@gmail.com"); 863 accounts.insert("test_user2@gmail.com"); 864 EXPECT_EQ(accounts, device_checkin_info().last_checkin_accounts); 865 EXPECT_TRUE(device_checkin_info().accounts_set); 866 EXPECT_EQ(account_tokens, device_checkin_info().account_tokens); 867} 868 869// This test only checks that periodic checkin happens. 870TEST_F(GCMClientImplCheckinTest, CheckinWhenAccountRemoved) { 871 std::map<std::string, std::string> settings; 872 settings["checkin_interval"] = base::IntToString(kSettingsCheckinInterval); 873 settings["checkin_url"] = "http://alternative.url/checkin"; 874 settings["gcm_hostname"] = "alternative.gcm.host"; 875 settings["gcm_secure_port"] = "7777"; 876 settings["gcm_registration_url"] = "http://alternative.url/registration"; 877 CompleteCheckin(kDeviceAndroidId, 878 kDeviceSecurityToken, 879 GServicesSettings::CalculateDigest(settings), 880 settings); 881 882 std::map<std::string, std::string> account_tokens; 883 account_tokens["test_user1@gmail.com"] = "token1"; 884 account_tokens["test_user2@gmail.com"] = "token2"; 885 gcm_client()->SetAccountsForCheckin(account_tokens); 886 PumpLoopUntilIdle(); 887 CompleteCheckin(kDeviceAndroidId, 888 kDeviceSecurityToken, 889 GServicesSettings::CalculateDigest(settings), 890 settings); 891 892 EXPECT_EQ(2UL, device_checkin_info().last_checkin_accounts.size()); 893 EXPECT_TRUE(device_checkin_info().accounts_set); 894 EXPECT_EQ(account_tokens, device_checkin_info().account_tokens); 895 896 account_tokens.erase(account_tokens.find("test_user2@gmail.com")); 897 gcm_client()->SetAccountsForCheckin(account_tokens); 898 899 PumpLoopUntilIdle(); 900 CompleteCheckin(kDeviceAndroidId, 901 kDeviceSecurityToken, 902 GServicesSettings::CalculateDigest(settings), 903 settings); 904 905 std::set<std::string> accounts; 906 accounts.insert("test_user1@gmail.com"); 907 EXPECT_EQ(accounts, device_checkin_info().last_checkin_accounts); 908 EXPECT_TRUE(device_checkin_info().accounts_set); 909 EXPECT_EQ(account_tokens, device_checkin_info().account_tokens); 910} 911 912// This test only checks that periodic checkin happens. 913TEST_F(GCMClientImplCheckinTest, CheckinWhenAccountReplaced) { 914 std::map<std::string, std::string> settings; 915 settings["checkin_interval"] = base::IntToString(kSettingsCheckinInterval); 916 settings["checkin_url"] = "http://alternative.url/checkin"; 917 settings["gcm_hostname"] = "alternative.gcm.host"; 918 settings["gcm_secure_port"] = "7777"; 919 settings["gcm_registration_url"] = "http://alternative.url/registration"; 920 CompleteCheckin(kDeviceAndroidId, 921 kDeviceSecurityToken, 922 GServicesSettings::CalculateDigest(settings), 923 settings); 924 925 std::map<std::string, std::string> account_tokens; 926 account_tokens["test_user1@gmail.com"] = "token1"; 927 gcm_client()->SetAccountsForCheckin(account_tokens); 928 929 PumpLoopUntilIdle(); 930 CompleteCheckin(kDeviceAndroidId, 931 kDeviceSecurityToken, 932 GServicesSettings::CalculateDigest(settings), 933 settings); 934 935 std::set<std::string> accounts; 936 accounts.insert("test_user1@gmail.com"); 937 EXPECT_EQ(accounts, device_checkin_info().last_checkin_accounts); 938 939 // This should trigger another checkin, because the list of accounts is 940 // different. 941 account_tokens.erase(account_tokens.find("test_user1@gmail.com")); 942 account_tokens["test_user2@gmail.com"] = "token2"; 943 gcm_client()->SetAccountsForCheckin(account_tokens); 944 945 PumpLoopUntilIdle(); 946 CompleteCheckin(kDeviceAndroidId, 947 kDeviceSecurityToken, 948 GServicesSettings::CalculateDigest(settings), 949 settings); 950 951 accounts.clear(); 952 accounts.insert("test_user2@gmail.com"); 953 EXPECT_EQ(accounts, device_checkin_info().last_checkin_accounts); 954 EXPECT_TRUE(device_checkin_info().accounts_set); 955 EXPECT_EQ(account_tokens, device_checkin_info().account_tokens); 956} 957 958class GCMClientImplStartAndStopTest : public GCMClientImplTest { 959public: 960 GCMClientImplStartAndStopTest(); 961 virtual ~GCMClientImplStartAndStopTest(); 962 963 virtual void SetUp() OVERRIDE; 964}; 965 966GCMClientImplStartAndStopTest::GCMClientImplStartAndStopTest() { 967} 968 969GCMClientImplStartAndStopTest::~GCMClientImplStartAndStopTest() { 970} 971 972void GCMClientImplStartAndStopTest::SetUp() { 973 testing::Test::SetUp(); 974 ASSERT_TRUE(CreateUniqueTempDir()); 975 InitializeLoop(); 976 BuildGCMClient(base::TimeDelta()); 977 InitializeGCMClient(); 978} 979 980TEST_F(GCMClientImplStartAndStopTest, StartStopAndRestart) { 981 // Start the GCM and wait until it is ready. 982 gcm_client()->Start(); 983 PumpLoopUntilIdle(); 984 985 // Stop the GCM. 986 gcm_client()->Stop(); 987 PumpLoopUntilIdle(); 988 989 // Restart the GCM. 990 gcm_client()->Start(); 991 PumpLoopUntilIdle(); 992} 993 994TEST_F(GCMClientImplStartAndStopTest, StartAndStopImmediately) { 995 // Start the GCM and then stop it immediately. 996 gcm_client()->Start(); 997 gcm_client()->Stop(); 998 999 PumpLoopUntilIdle(); 1000} 1001 1002TEST_F(GCMClientImplStartAndStopTest, StartStopAndRestartImmediately) { 1003 // Start the GCM and then stop and restart it immediately. 1004 gcm_client()->Start(); 1005 gcm_client()->Stop(); 1006 gcm_client()->Start(); 1007 1008 PumpLoopUntilIdle(); 1009} 1010 1011} // namespace gcm 1012