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
28 namespace gcm {
29
30 namespace {
31
32 enum 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
43 const uint64 kDeviceAndroidId = 54321;
44 const uint64 kDeviceSecurityToken = 12345;
45 const int64 kSettingsCheckinInterval = 16 * 60 * 60;
46 const char kAppId[] = "app_id";
47 const char kSender[] = "project_id";
48 const char kSender2[] = "project_id2";
49 const char kSender3[] = "project_id3";
50 const char kRegistrationResponsePrefix[] = "token=";
51 const char kUnregistrationResponsePrefix[] = "deleted=";
52
53 // Helper for building arbitrary data messages.
BuildDownstreamMessage(const std::string & project_id,const std::string & app_id,const std::map<std::string,std::string> & data)54 MCSMessage 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
71 class 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
last_android_id() const81 uint64 last_android_id() const { return last_android_id_; }
last_security_token() const82 uint64 last_security_token() const { return last_security_token_; }
last_message_tag() const83 uint8 last_message_tag() const { return last_message_tag_; }
last_data_message_stanza() const84 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
FakeMCSClient(base::Clock * clock,ConnectionFactory * connection_factory,GCMStore * gcm_store,GCMStatsRecorder * recorder)95 FakeMCSClient::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
~FakeMCSClient()105 FakeMCSClient::~FakeMCSClient() {
106 }
107
Login(uint64 android_id,uint64 security_token)108 void FakeMCSClient::Login(uint64 android_id, uint64 security_token) {
109 last_android_id_ = android_id;
110 last_security_token_ = security_token;
111 }
112
SendMessage(const MCSMessage & message)113 void 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
122 class 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);
call_count() const129 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
AutoAdvancingTestClock(base::TimeDelta auto_increment_time_delta)139 AutoAdvancingTestClock::AutoAdvancingTestClock(
140 base::TimeDelta auto_increment_time_delta)
141 : call_count_(0), auto_increment_time_delta_(auto_increment_time_delta) {
142 }
143
~AutoAdvancingTestClock()144 AutoAdvancingTestClock::~AutoAdvancingTestClock() {
145 }
146
Now()147 base::Time AutoAdvancingTestClock::Now() {
148 call_count_++;
149 now_ += auto_increment_time_delta_;
150 return now_;
151 }
152
Advance(base::TimeDelta delta)153 void AutoAdvancingTestClock::Advance(base::TimeDelta delta) {
154 now_ += delta;
155 }
156
157 class 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
FakeGCMInternalsBuilder(base::TimeDelta clock_step)181 FakeGCMInternalsBuilder::FakeGCMInternalsBuilder(base::TimeDelta clock_step)
182 : clock_step_(clock_step) {
183 }
184
~FakeGCMInternalsBuilder()185 FakeGCMInternalsBuilder::~FakeGCMInternalsBuilder() {}
186
BuildClock()187 scoped_ptr<base::Clock> FakeGCMInternalsBuilder::BuildClock() {
188 return make_scoped_ptr<base::Clock>(new AutoAdvancingTestClock(clock_step_));
189 }
190
BuildMCSClient(const std::string & version,base::Clock * clock,ConnectionFactory * connection_factory,GCMStore * gcm_store,GCMStatsRecorder * recorder)191 scoped_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
BuildConnectionFactory(const std::vector<GURL> & endpoints,const net::BackoffEntry::Policy & backoff_policy,const scoped_refptr<net::HttpNetworkSession> & gcm_network_session,const scoped_refptr<net::HttpNetworkSession> & http_network_session,net::NetLog * net_log,GCMStatsRecorder * recorder)203 scoped_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
215 class 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;
OnSendFinished(const std::string & app_id,const std::string & message_id,GCMClient::Result result)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;
OnActivityRecorded()263 virtual void OnActivityRecorded() OVERRIDE {}
OnConnected(const net::IPEndPoint & ip_endpoint)264 virtual void OnConnected(const net::IPEndPoint& ip_endpoint) OVERRIDE {}
OnDisconnected()265 virtual void OnDisconnected() OVERRIDE {}
266
gcm_client() const267 GCMClientImpl* gcm_client() const { return gcm_client_.get(); }
mcs_client() const268 FakeMCSClient* mcs_client() const {
269 return reinterpret_cast<FakeMCSClient*>(gcm_client_->mcs_client_.get());
270 }
connection_factory() const271 ConnectionFactory* connection_factory() const {
272 return gcm_client_->connection_factory_.get();
273 }
274
device_checkin_info() const275 const GCMClientImpl::CheckinInfo& device_checkin_info() const {
276 return gcm_client_->device_checkin_info_;
277 }
278
reset_last_event()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
last_event() const287 LastEvent last_event() const { return last_event_; }
last_app_id() const288 const std::string& last_app_id() const { return last_app_id_; }
last_registration_id() const289 const std::string& last_registration_id() const {
290 return last_registration_id_;
291 }
last_message_id() const292 const std::string& last_message_id() const { return last_message_id_; }
last_result() const293 GCMClient::Result last_result() const { return last_result_; }
last_message() const294 const GCMClient::IncomingMessage& last_message() const {
295 return last_message_;
296 }
last_error_details() const297 const GCMClient::SendErrorDetails& last_error_details() const {
298 return last_error_details_;
299 }
300
gservices_settings() const301 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();
clock() const313 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
GCMClientImplTest()338 GCMClientImplTest::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
~GCMClientImplTest()345 GCMClientImplTest::~GCMClientImplTest() {}
346
SetUp()347 void 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
PumpLoop()360 void GCMClientImplTest::PumpLoop() {
361 run_loop_->Run();
362 run_loop_.reset(new base::RunLoop());
363 }
364
PumpLoopUntilIdle()365 void GCMClientImplTest::PumpLoopUntilIdle() {
366 run_loop_->RunUntilIdle();
367 run_loop_.reset(new base::RunLoop());
368 }
369
QuitLoop()370 void GCMClientImplTest::QuitLoop() {
371 if (run_loop_ && run_loop_->running())
372 run_loop_->Quit();
373 }
374
InitializeLoop()375 void GCMClientImplTest::InitializeLoop() {
376 run_loop_.reset(new base::RunLoop);
377 }
378
CreateUniqueTempDir()379 bool GCMClientImplTest::CreateUniqueTempDir() {
380 return temp_directory_.CreateUniqueTempDir();
381 }
382
BuildGCMClient(base::TimeDelta clock_step)383 void GCMClientImplTest::BuildGCMClient(base::TimeDelta clock_step) {
384 gcm_client_.reset(new GCMClientImpl(make_scoped_ptr<GCMInternalsBuilder>(
385 new FakeGCMInternalsBuilder(clock_step))));
386 }
387
CompleteCheckin(uint64 android_id,uint64 security_token,const std::string & digest,const std::map<std::string,std::string> & settings)388 void 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
CompleteRegistration(const std::string & registration_id)423 void 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
CompleteUnregistration(const std::string & app_id)435 void 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
ExistsRegistration(const std::string & app_id) const447 bool GCMClientImplTest::ExistsRegistration(const std::string& app_id) const {
448 return gcm_client_->registrations_.count(app_id) > 0;
449 }
450
AddRegistration(const std::string & app_id,const std::vector<std::string> & sender_ids,const std::string & registration_id)451 void 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
InitializeGCMClient()461 void 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
StartGCMClient()474 void GCMClientImplTest::StartGCMClient() {
475 // Start loading and check-in.
476 gcm_client_->Start();
477
478 PumpLoopUntilIdle();
479 }
480
ReceiveMessageFromMCS(const MCSMessage & message)481 void GCMClientImplTest::ReceiveMessageFromMCS(const MCSMessage& message) {
482 gcm_client_->recorder_.RecordConnectionInitiated(std::string());
483 gcm_client_->recorder_.RecordConnectionSuccess();
484 gcm_client_->OnMessageReceivedFromMCS(message);
485 }
486
ReceiveOnMessageSentToMCS(const std::string & app_id,const std::string & message_id,const MCSClient::MessageSendStatus status)487 void 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
OnGCMReady(const std::vector<AccountMapping> & account_mappings)494 void 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
OnMessageReceived(const std::string & registration_id,const GCMClient::IncomingMessage & message)502 void 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
OnRegisterFinished(const std::string & app_id,const std::string & registration_id,GCMClient::Result result)511 void 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
OnUnregisterFinished(const std::string & app_id,GCMClient::Result result)520 void 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
OnMessagesDeleted(const std::string & app_id)527 void GCMClientImplTest::OnMessagesDeleted(const std::string& app_id) {
528 last_event_ = MESSAGES_DELETED;
529 last_app_id_ = app_id;
530 }
531
OnMessageSendError(const std::string & app_id,const gcm::GCMClient::SendErrorDetails & send_error_details)532 void 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
OnSendAcknowledged(const std::string & app_id,const std::string & message_id)540 void 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
CurrentTime()547 int64 GCMClientImplTest::CurrentTime() {
548 return clock()->Now().ToInternalValue() / base::Time::kMicrosecondsPerSecond;
549 }
550
TEST_F(GCMClientImplTest,LoadingCompleted)551 TEST_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
TEST_F(GCMClientImplTest,CheckOut)564 TEST_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
TEST_F(GCMClientImplTest,RegisterApp)572 TEST_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
TEST_F(GCMClientImplTest,DISABLED_RegisterAppFromCache)587 TEST_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
TEST_F(GCMClientImplTest,UnregisterApp)609 TEST_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
TEST_F(GCMClientImplTest,DispatchDownstreamMessage)627 TEST_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
TEST_F(GCMClientImplTest,DispatchDownstreamMessageSendError)675 TEST_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
TEST_F(GCMClientImplTest,DispatchDownstreamMessgaesDeleted)695 TEST_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
TEST_F(GCMClientImplTest,SendMessage)707 TEST_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
TEST_F(GCMClientImplTest,SendMessageAcknowledged)727 TEST_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
734 class GCMClientImplCheckinTest : public GCMClientImplTest {
735 public:
736 GCMClientImplCheckinTest();
737 virtual ~GCMClientImplCheckinTest();
738
739 virtual void SetUp() OVERRIDE;
740 };
741
GCMClientImplCheckinTest()742 GCMClientImplCheckinTest::GCMClientImplCheckinTest() {
743 }
744
~GCMClientImplCheckinTest()745 GCMClientImplCheckinTest::~GCMClientImplCheckinTest() {
746 }
747
SetUp()748 void 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
TEST_F(GCMClientImplCheckinTest,GServicesSettingsAfterInitialCheckin)760 TEST_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.
TEST_F(GCMClientImplCheckinTest,PeriodicCheckin)784 TEST_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
TEST_F(GCMClientImplCheckinTest,LoadGSettingsFromStore)805 TEST_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.
TEST_F(GCMClientImplCheckinTest,CheckinWithAccounts)834 TEST_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.
TEST_F(GCMClientImplCheckinTest,CheckinWhenAccountRemoved)870 TEST_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.
TEST_F(GCMClientImplCheckinTest,CheckinWhenAccountReplaced)913 TEST_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
958 class GCMClientImplStartAndStopTest : public GCMClientImplTest {
959 public:
960 GCMClientImplStartAndStopTest();
961 virtual ~GCMClientImplStartAndStopTest();
962
963 virtual void SetUp() OVERRIDE;
964 };
965
GCMClientImplStartAndStopTest()966 GCMClientImplStartAndStopTest::GCMClientImplStartAndStopTest() {
967 }
968
~GCMClientImplStartAndStopTest()969 GCMClientImplStartAndStopTest::~GCMClientImplStartAndStopTest() {
970 }
971
SetUp()972 void GCMClientImplStartAndStopTest::SetUp() {
973 testing::Test::SetUp();
974 ASSERT_TRUE(CreateUniqueTempDir());
975 InitializeLoop();
976 BuildGCMClient(base::TimeDelta());
977 InitializeGCMClient();
978 }
979
TEST_F(GCMClientImplStartAndStopTest,StartStopAndRestart)980 TEST_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
TEST_F(GCMClientImplStartAndStopTest,StartAndStopImmediately)994 TEST_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
TEST_F(GCMClientImplStartAndStopTest,StartStopAndRestartImmediately)1002 TEST_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