gcm_client_impl_unittest.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
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() OVERRIDE;
262  virtual void OnActivityRecorded() OVERRIDE {}
263  virtual void OnConnected(const net::IPEndPoint& ip_endpoint) OVERRIDE {}
264  virtual void OnDisconnected() OVERRIDE {}
265
266  GCMClientImpl* gcm_client() const { return gcm_client_.get(); }
267  FakeMCSClient* mcs_client() const {
268    return reinterpret_cast<FakeMCSClient*>(gcm_client_->mcs_client_.get());
269  }
270  ConnectionFactory* connection_factory() const {
271    return gcm_client_->connection_factory_.get();
272  }
273
274  const GCMClientImpl::CheckinInfo& device_checkin_info() const {
275    return gcm_client_->device_checkin_info_;
276  }
277
278  void reset_last_event() {
279    last_event_ = NONE;
280    last_app_id_.clear();
281    last_registration_id_.clear();
282    last_message_id_.clear();
283    last_result_ = GCMClient::UNKNOWN_ERROR;
284  }
285
286  LastEvent last_event() const { return last_event_; }
287  const std::string& last_app_id() const { return last_app_id_; }
288  const std::string& last_registration_id() const {
289    return last_registration_id_;
290  }
291  const std::string& last_message_id() const { return last_message_id_; }
292  GCMClient::Result last_result() const { return last_result_; }
293  const GCMClient::IncomingMessage& last_message() const {
294    return last_message_;
295  }
296  const GCMClient::SendErrorDetails& last_error_details() const {
297    return last_error_details_;
298  }
299
300  const GServicesSettings& gservices_settings() const {
301    return gcm_client_->gservices_settings_;
302  }
303
304  int64 CurrentTime();
305
306  // Tooling.
307  void PumpLoop();
308  void PumpLoopUntilIdle();
309  void QuitLoop();
310  void InitializeLoop();
311  bool CreateUniqueTempDir();
312  AutoAdvancingTestClock* clock() const {
313    return reinterpret_cast<AutoAdvancingTestClock*>(gcm_client_->clock_.get());
314  }
315
316 private:
317  // Variables used for verification.
318  LastEvent last_event_;
319  std::string last_app_id_;
320  std::string last_registration_id_;
321  std::string last_message_id_;
322  GCMClient::Result last_result_;
323  GCMClient::IncomingMessage last_message_;
324  GCMClient::SendErrorDetails last_error_details_;
325
326  scoped_ptr<GCMClientImpl> gcm_client_;
327
328  base::MessageLoop message_loop_;
329  scoped_ptr<base::RunLoop> run_loop_;
330  net::TestURLFetcherFactory url_fetcher_factory_;
331
332  // Injected to GCM client:
333  base::ScopedTempDir temp_directory_;
334  scoped_refptr<net::TestURLRequestContextGetter> url_request_context_getter_;
335};
336
337GCMClientImplTest::GCMClientImplTest()
338    : last_event_(NONE),
339      last_result_(GCMClient::UNKNOWN_ERROR),
340      url_request_context_getter_(new net::TestURLRequestContextGetter(
341          message_loop_.message_loop_proxy())) {
342}
343
344GCMClientImplTest::~GCMClientImplTest() {}
345
346void GCMClientImplTest::SetUp() {
347  testing::Test::SetUp();
348  ASSERT_TRUE(CreateUniqueTempDir());
349  InitializeLoop();
350  BuildGCMClient(base::TimeDelta());
351  InitializeGCMClient();
352  StartGCMClient();
353  CompleteCheckin(kDeviceAndroidId,
354                  kDeviceSecurityToken,
355                  std::string(),
356                  std::map<std::string, std::string>());
357}
358
359void GCMClientImplTest::PumpLoop() {
360  run_loop_->Run();
361  run_loop_.reset(new base::RunLoop());
362}
363
364void GCMClientImplTest::PumpLoopUntilIdle() {
365  run_loop_->RunUntilIdle();
366  run_loop_.reset(new base::RunLoop());
367}
368
369void GCMClientImplTest::QuitLoop() {
370  if (run_loop_ && run_loop_->running())
371    run_loop_->Quit();
372}
373
374void GCMClientImplTest::InitializeLoop() {
375  run_loop_.reset(new base::RunLoop);
376}
377
378bool GCMClientImplTest::CreateUniqueTempDir() {
379  return temp_directory_.CreateUniqueTempDir();
380}
381
382void GCMClientImplTest::BuildGCMClient(base::TimeDelta clock_step) {
383  gcm_client_.reset(new GCMClientImpl(make_scoped_ptr<GCMInternalsBuilder>(
384      new FakeGCMInternalsBuilder(clock_step))));
385}
386
387void GCMClientImplTest::CompleteCheckin(
388    uint64 android_id,
389    uint64 security_token,
390    const std::string& digest,
391    const std::map<std::string, std::string>& settings) {
392  checkin_proto::AndroidCheckinResponse response;
393  response.set_stats_ok(true);
394  response.set_android_id(android_id);
395  response.set_security_token(security_token);
396
397  // For testing G-services settings.
398  if (!digest.empty()) {
399    response.set_digest(digest);
400    for (std::map<std::string, std::string>::const_iterator it =
401             settings.begin();
402         it != settings.end();
403         ++it) {
404      checkin_proto::GservicesSetting* setting = response.add_setting();
405      setting->set_name(it->first);
406      setting->set_value(it->second);
407    }
408    response.set_settings_diff(false);
409  }
410
411  std::string response_string;
412  response.SerializeToString(&response_string);
413
414  net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
415  ASSERT_TRUE(fetcher);
416  fetcher->set_response_code(net::HTTP_OK);
417  fetcher->SetResponseString(response_string);
418  fetcher->delegate()->OnURLFetchComplete(fetcher);
419  url_fetcher_factory_.RemoveFetcherFromMap(0);
420}
421
422void GCMClientImplTest::CompleteRegistration(
423    const std::string& registration_id) {
424  std::string response(kRegistrationResponsePrefix);
425  response.append(registration_id);
426  net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
427  ASSERT_TRUE(fetcher);
428  fetcher->set_response_code(net::HTTP_OK);
429  fetcher->SetResponseString(response);
430  fetcher->delegate()->OnURLFetchComplete(fetcher);
431  url_fetcher_factory_.RemoveFetcherFromMap(0);
432}
433
434void GCMClientImplTest::CompleteUnregistration(
435    const std::string& app_id) {
436  std::string response(kUnregistrationResponsePrefix);
437  response.append(app_id);
438  net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0);
439  ASSERT_TRUE(fetcher);
440  fetcher->set_response_code(net::HTTP_OK);
441  fetcher->SetResponseString(response);
442  fetcher->delegate()->OnURLFetchComplete(fetcher);
443  url_fetcher_factory_.RemoveFetcherFromMap(0);
444}
445
446bool GCMClientImplTest::ExistsRegistration(const std::string& app_id) const {
447  return gcm_client_->registrations_.count(app_id) > 0;
448}
449
450void GCMClientImplTest::AddRegistration(
451    const std::string& app_id,
452    const std::vector<std::string>& sender_ids,
453    const std::string& registration_id) {
454  linked_ptr<RegistrationInfo> registration(new RegistrationInfo);
455  registration->sender_ids = sender_ids;
456  registration->registration_id = registration_id;
457  gcm_client_->registrations_[app_id] = registration;
458}
459
460void GCMClientImplTest::InitializeGCMClient() {
461  clock()->Advance(base::TimeDelta::FromMilliseconds(1));
462
463  // Actual initialization.
464  GCMClient::ChromeBuildInfo chrome_build_info;
465  gcm_client_->Initialize(chrome_build_info,
466                          temp_directory_.path(),
467                          message_loop_.message_loop_proxy(),
468                          url_request_context_getter_,
469                          make_scoped_ptr<Encryptor>(new FakeEncryptor),
470                          this);
471}
472
473void GCMClientImplTest::StartGCMClient() {
474  // Start loading and check-in.
475  gcm_client_->Start();
476
477  PumpLoopUntilIdle();
478}
479
480void GCMClientImplTest::ReceiveMessageFromMCS(const MCSMessage& message) {
481  gcm_client_->recorder_.RecordConnectionInitiated(std::string());
482  gcm_client_->recorder_.RecordConnectionSuccess();
483  gcm_client_->OnMessageReceivedFromMCS(message);
484}
485
486void GCMClientImplTest::ReceiveOnMessageSentToMCS(
487      const std::string& app_id,
488      const std::string& message_id,
489      const MCSClient::MessageSendStatus status) {
490  gcm_client_->OnMessageSentToMCS(0LL, app_id, message_id, status);
491}
492
493void GCMClientImplTest::OnGCMReady() {
494  last_event_ = LOADING_COMPLETED;
495  QuitLoop();
496}
497
498void GCMClientImplTest::OnMessageReceived(
499    const std::string& registration_id,
500    const GCMClient::IncomingMessage& message) {
501  last_event_ = MESSAGE_RECEIVED;
502  last_app_id_ = registration_id;
503  last_message_ = message;
504  QuitLoop();
505}
506
507void GCMClientImplTest::OnRegisterFinished(const std::string& app_id,
508                                           const std::string& registration_id,
509                                           GCMClient::Result result) {
510  last_event_ = REGISTRATION_COMPLETED;
511  last_app_id_ = app_id;
512  last_registration_id_ = registration_id;
513  last_result_ = result;
514}
515
516void GCMClientImplTest::OnUnregisterFinished(const std::string& app_id,
517                                             GCMClient::Result result) {
518  last_event_ = UNREGISTRATION_COMPLETED;
519  last_app_id_ = app_id;
520  last_result_ = result;
521}
522
523void GCMClientImplTest::OnMessagesDeleted(const std::string& app_id) {
524  last_event_ = MESSAGES_DELETED;
525  last_app_id_ = app_id;
526}
527
528void GCMClientImplTest::OnMessageSendError(
529    const std::string& app_id,
530    const gcm::GCMClient::SendErrorDetails& send_error_details) {
531  last_event_ = MESSAGE_SEND_ERROR;
532  last_app_id_ = app_id;
533  last_error_details_ = send_error_details;
534}
535
536void GCMClientImplTest::OnSendAcknowledged(const std::string& app_id,
537                                           const std::string& message_id) {
538  last_event_ = MESSAGE_SEND_ACK;
539  last_app_id_ = app_id;
540  last_message_id_ = message_id;
541}
542
543int64 GCMClientImplTest::CurrentTime() {
544  return clock()->Now().ToInternalValue() / base::Time::kMicrosecondsPerSecond;
545}
546
547TEST_F(GCMClientImplTest, LoadingCompleted) {
548  EXPECT_EQ(LOADING_COMPLETED, last_event());
549  EXPECT_EQ(kDeviceAndroidId, mcs_client()->last_android_id());
550  EXPECT_EQ(kDeviceSecurityToken, mcs_client()->last_security_token());
551
552  // Checking freshly loaded CheckinInfo.
553  EXPECT_EQ(kDeviceAndroidId, device_checkin_info().android_id);
554  EXPECT_EQ(kDeviceSecurityToken, device_checkin_info().secret);
555  EXPECT_TRUE(device_checkin_info().last_checkin_accounts.empty());
556  EXPECT_TRUE(device_checkin_info().accounts_set);
557  EXPECT_TRUE(device_checkin_info().account_tokens.empty());
558}
559
560TEST_F(GCMClientImplTest, CheckOut) {
561  EXPECT_TRUE(mcs_client());
562  EXPECT_TRUE(connection_factory());
563  gcm_client()->CheckOut();
564  EXPECT_FALSE(mcs_client());
565  EXPECT_FALSE(connection_factory());
566}
567
568TEST_F(GCMClientImplTest, RegisterApp) {
569  EXPECT_FALSE(ExistsRegistration(kAppId));
570
571  std::vector<std::string> senders;
572  senders.push_back("sender");
573  gcm_client()->Register(kAppId, senders);
574  CompleteRegistration("reg_id");
575
576  EXPECT_EQ(REGISTRATION_COMPLETED, last_event());
577  EXPECT_EQ(kAppId, last_app_id());
578  EXPECT_EQ("reg_id", last_registration_id());
579  EXPECT_EQ(GCMClient::SUCCESS, last_result());
580  EXPECT_TRUE(ExistsRegistration(kAppId));
581}
582
583TEST_F(GCMClientImplTest, DISABLED_RegisterAppFromCache) {
584  EXPECT_FALSE(ExistsRegistration(kAppId));
585
586  std::vector<std::string> senders;
587  senders.push_back("sender");
588  gcm_client()->Register(kAppId, senders);
589  CompleteRegistration("reg_id");
590  EXPECT_TRUE(ExistsRegistration(kAppId));
591
592  EXPECT_EQ(kAppId, last_app_id());
593  EXPECT_EQ("reg_id", last_registration_id());
594  EXPECT_EQ(GCMClient::SUCCESS, last_result());
595  EXPECT_EQ(REGISTRATION_COMPLETED, last_event());
596
597  // Recreate GCMClient in order to load from the persistent store.
598  BuildGCMClient(base::TimeDelta());
599  InitializeGCMClient();
600  StartGCMClient();
601
602  EXPECT_TRUE(ExistsRegistration(kAppId));
603}
604
605TEST_F(GCMClientImplTest, UnregisterApp) {
606  EXPECT_FALSE(ExistsRegistration(kAppId));
607
608  std::vector<std::string> senders;
609  senders.push_back("sender");
610  gcm_client()->Register(kAppId, senders);
611  CompleteRegistration("reg_id");
612  EXPECT_TRUE(ExistsRegistration(kAppId));
613
614  gcm_client()->Unregister(kAppId);
615  CompleteUnregistration(kAppId);
616
617  EXPECT_EQ(UNREGISTRATION_COMPLETED, last_event());
618  EXPECT_EQ(kAppId, last_app_id());
619  EXPECT_EQ(GCMClient::SUCCESS, last_result());
620  EXPECT_FALSE(ExistsRegistration(kAppId));
621}
622
623TEST_F(GCMClientImplTest, DispatchDownstreamMessage) {
624  // Register to receive messages from kSender and kSender2 only.
625  std::vector<std::string> senders;
626  senders.push_back(kSender);
627  senders.push_back(kSender2);
628  AddRegistration(kAppId, senders, "reg_id");
629
630  std::map<std::string, std::string> expected_data;
631  expected_data["message_type"] = "gcm";
632  expected_data["key"] = "value";
633  expected_data["key2"] = "value2";
634
635  // Message for kSender will be received.
636  MCSMessage message(BuildDownstreamMessage(kSender, kAppId, expected_data));
637  EXPECT_TRUE(message.IsValid());
638  ReceiveMessageFromMCS(message);
639
640  expected_data.erase(expected_data.find("message_type"));
641  EXPECT_EQ(MESSAGE_RECEIVED, last_event());
642  EXPECT_EQ(kAppId, last_app_id());
643  EXPECT_EQ(expected_data.size(), last_message().data.size());
644  EXPECT_EQ(expected_data, last_message().data);
645  EXPECT_EQ(kSender, last_message().sender_id);
646
647  reset_last_event();
648
649  // Message for kSender2 will be received.
650  MCSMessage message2(BuildDownstreamMessage(kSender2, kAppId, expected_data));
651  EXPECT_TRUE(message2.IsValid());
652  ReceiveMessageFromMCS(message2);
653
654  EXPECT_EQ(MESSAGE_RECEIVED, last_event());
655  EXPECT_EQ(kAppId, last_app_id());
656  EXPECT_EQ(expected_data.size(), last_message().data.size());
657  EXPECT_EQ(expected_data, last_message().data);
658  EXPECT_EQ(kSender2, last_message().sender_id);
659
660  reset_last_event();
661
662  // Message from kSender3 will be dropped.
663  MCSMessage message3(BuildDownstreamMessage(kSender3, kAppId, expected_data));
664  EXPECT_TRUE(message3.IsValid());
665  ReceiveMessageFromMCS(message3);
666
667  EXPECT_NE(MESSAGE_RECEIVED, last_event());
668  EXPECT_NE(kAppId, last_app_id());
669}
670
671TEST_F(GCMClientImplTest, DispatchDownstreamMessageSendError) {
672  std::map<std::string, std::string> expected_data;
673  expected_data["message_type"] = "send_error";
674  expected_data["google.message_id"] = "007";
675  expected_data["error_details"] = "some details";
676  MCSMessage message(BuildDownstreamMessage(
677      kSender, kAppId, expected_data));
678  EXPECT_TRUE(message.IsValid());
679  ReceiveMessageFromMCS(message);
680
681  EXPECT_EQ(MESSAGE_SEND_ERROR, last_event());
682  EXPECT_EQ(kAppId, last_app_id());
683  EXPECT_EQ("007", last_error_details().message_id);
684  EXPECT_EQ(1UL, last_error_details().additional_data.size());
685  GCMClient::MessageData::const_iterator iter =
686      last_error_details().additional_data.find("error_details");
687  EXPECT_TRUE(iter != last_error_details().additional_data.end());
688  EXPECT_EQ("some details", iter->second);
689}
690
691TEST_F(GCMClientImplTest, DispatchDownstreamMessgaesDeleted) {
692  std::map<std::string, std::string> expected_data;
693  expected_data["message_type"] = "deleted_messages";
694  MCSMessage message(BuildDownstreamMessage(
695      kSender, kAppId, expected_data));
696  EXPECT_TRUE(message.IsValid());
697  ReceiveMessageFromMCS(message);
698
699  EXPECT_EQ(MESSAGES_DELETED, last_event());
700  EXPECT_EQ(kAppId, last_app_id());
701}
702
703TEST_F(GCMClientImplTest, SendMessage) {
704  GCMClient::OutgoingMessage message;
705  message.id = "007";
706  message.time_to_live = 500;
707  message.data["key"] = "value";
708  gcm_client()->Send(kAppId, kSender, message);
709
710  EXPECT_EQ(kDataMessageStanzaTag, mcs_client()->last_message_tag());
711  EXPECT_EQ(kAppId, mcs_client()->last_data_message_stanza().category());
712  EXPECT_EQ(kSender, mcs_client()->last_data_message_stanza().to());
713  EXPECT_EQ(500, mcs_client()->last_data_message_stanza().ttl());
714  EXPECT_EQ(CurrentTime(), mcs_client()->last_data_message_stanza().sent());
715  EXPECT_EQ("007", mcs_client()->last_data_message_stanza().id());
716  EXPECT_EQ("gcm@chrome.com", mcs_client()->last_data_message_stanza().from());
717  EXPECT_EQ(kSender, mcs_client()->last_data_message_stanza().to());
718  EXPECT_EQ("key", mcs_client()->last_data_message_stanza().app_data(0).key());
719  EXPECT_EQ("value",
720            mcs_client()->last_data_message_stanza().app_data(0).value());
721}
722
723TEST_F(GCMClientImplTest, SendMessageAcknowledged) {
724  ReceiveOnMessageSentToMCS(kAppId, "007", MCSClient::SENT);
725  EXPECT_EQ(MESSAGE_SEND_ACK, last_event());
726  EXPECT_EQ(kAppId, last_app_id());
727  EXPECT_EQ("007", last_message_id());
728}
729
730class GCMClientImplCheckinTest : public GCMClientImplTest {
731 public:
732  GCMClientImplCheckinTest();
733  virtual ~GCMClientImplCheckinTest();
734
735  virtual void SetUp() OVERRIDE;
736};
737
738GCMClientImplCheckinTest::GCMClientImplCheckinTest() {
739}
740
741GCMClientImplCheckinTest::~GCMClientImplCheckinTest() {
742}
743
744void GCMClientImplCheckinTest::SetUp() {
745  testing::Test::SetUp();
746  // Creating unique temp directory that will be used by GCMStore shared between
747  // GCM Client and G-services settings.
748  ASSERT_TRUE(CreateUniqueTempDir());
749  InitializeLoop();
750  // Time will be advancing one hour every time it is checked.
751  BuildGCMClient(base::TimeDelta::FromSeconds(kSettingsCheckinInterval));
752  InitializeGCMClient();
753  StartGCMClient();
754}
755
756TEST_F(GCMClientImplCheckinTest, GServicesSettingsAfterInitialCheckin) {
757  std::map<std::string, std::string> settings;
758  settings["checkin_interval"] = base::Int64ToString(kSettingsCheckinInterval);
759  settings["checkin_url"] = "http://alternative.url/checkin";
760  settings["gcm_hostname"] = "alternative.gcm.host";
761  settings["gcm_secure_port"] = "7777";
762  settings["gcm_registration_url"] = "http://alternative.url/registration";
763  CompleteCheckin(kDeviceAndroidId,
764                  kDeviceSecurityToken,
765                  GServicesSettings::CalculateDigest(settings),
766                  settings);
767  EXPECT_EQ(base::TimeDelta::FromSeconds(kSettingsCheckinInterval),
768            gservices_settings().GetCheckinInterval());
769  EXPECT_EQ(GURL("http://alternative.url/checkin"),
770            gservices_settings().GetCheckinURL());
771  EXPECT_EQ(GURL("http://alternative.url/registration"),
772            gservices_settings().GetRegistrationURL());
773  EXPECT_EQ(GURL("https://alternative.gcm.host:7777"),
774            gservices_settings().GetMCSMainEndpoint());
775  EXPECT_EQ(GURL("https://alternative.gcm.host:443"),
776            gservices_settings().GetMCSFallbackEndpoint());
777}
778
779// This test only checks that periodic checkin happens.
780TEST_F(GCMClientImplCheckinTest, PeriodicCheckin) {
781  std::map<std::string, std::string> settings;
782  settings["checkin_interval"] = base::IntToString(kSettingsCheckinInterval);
783  settings["checkin_url"] = "http://alternative.url/checkin";
784  settings["gcm_hostname"] = "alternative.gcm.host";
785  settings["gcm_secure_port"] = "7777";
786  settings["gcm_registration_url"] = "http://alternative.url/registration";
787  CompleteCheckin(kDeviceAndroidId,
788                  kDeviceSecurityToken,
789                  GServicesSettings::CalculateDigest(settings),
790                  settings);
791
792  EXPECT_EQ(2, clock()->call_count());
793
794  PumpLoopUntilIdle();
795  CompleteCheckin(kDeviceAndroidId,
796                  kDeviceSecurityToken,
797                  GServicesSettings::CalculateDigest(settings),
798                  settings);
799}
800
801TEST_F(GCMClientImplCheckinTest, LoadGSettingsFromStore) {
802  std::map<std::string, std::string> settings;
803  settings["checkin_interval"] = base::IntToString(kSettingsCheckinInterval);
804  settings["checkin_url"] = "http://alternative.url/checkin";
805  settings["gcm_hostname"] = "alternative.gcm.host";
806  settings["gcm_secure_port"] = "7777";
807  settings["gcm_registration_url"] = "http://alternative.url/registration";
808  CompleteCheckin(kDeviceAndroidId,
809                  kDeviceSecurityToken,
810                  GServicesSettings::CalculateDigest(settings),
811                  settings);
812
813  BuildGCMClient(base::TimeDelta());
814  InitializeGCMClient();
815  StartGCMClient();
816
817  EXPECT_EQ(base::TimeDelta::FromSeconds(kSettingsCheckinInterval),
818            gservices_settings().GetCheckinInterval());
819  EXPECT_EQ(GURL("http://alternative.url/checkin"),
820            gservices_settings().GetCheckinURL());
821  EXPECT_EQ(GURL("http://alternative.url/registration"),
822            gservices_settings().GetRegistrationURL());
823  EXPECT_EQ(GURL("https://alternative.gcm.host:7777"),
824            gservices_settings().GetMCSMainEndpoint());
825  EXPECT_EQ(GURL("https://alternative.gcm.host:443"),
826            gservices_settings().GetMCSFallbackEndpoint());
827}
828
829// This test only checks that periodic checkin happens.
830TEST_F(GCMClientImplCheckinTest, CheckinWithAccounts) {
831  std::map<std::string, std::string> settings;
832  settings["checkin_interval"] = base::IntToString(kSettingsCheckinInterval);
833  settings["checkin_url"] = "http://alternative.url/checkin";
834  settings["gcm_hostname"] = "alternative.gcm.host";
835  settings["gcm_secure_port"] = "7777";
836  settings["gcm_registration_url"] = "http://alternative.url/registration";
837  CompleteCheckin(kDeviceAndroidId,
838                  kDeviceSecurityToken,
839                  GServicesSettings::CalculateDigest(settings),
840                  settings);
841
842  std::map<std::string, std::string> account_tokens;
843  account_tokens["test_user1@gmail.com"] = "token1";
844  account_tokens["test_user2@gmail.com"] = "token2";
845  gcm_client()->SetAccountsForCheckin(account_tokens);
846
847  EXPECT_TRUE(device_checkin_info().last_checkin_accounts.empty());
848  EXPECT_TRUE(device_checkin_info().accounts_set);
849  EXPECT_EQ(account_tokens, device_checkin_info().account_tokens);
850
851  PumpLoopUntilIdle();
852  CompleteCheckin(kDeviceAndroidId,
853                  kDeviceSecurityToken,
854                  GServicesSettings::CalculateDigest(settings),
855                  settings);
856
857  std::set<std::string> accounts;
858  accounts.insert("test_user1@gmail.com");
859  accounts.insert("test_user2@gmail.com");
860  EXPECT_EQ(accounts, device_checkin_info().last_checkin_accounts);
861  EXPECT_TRUE(device_checkin_info().accounts_set);
862  EXPECT_EQ(account_tokens, device_checkin_info().account_tokens);
863}
864
865// This test only checks that periodic checkin happens.
866TEST_F(GCMClientImplCheckinTest, CheckinWhenAccountRemoved) {
867  std::map<std::string, std::string> settings;
868  settings["checkin_interval"] = base::IntToString(kSettingsCheckinInterval);
869  settings["checkin_url"] = "http://alternative.url/checkin";
870  settings["gcm_hostname"] = "alternative.gcm.host";
871  settings["gcm_secure_port"] = "7777";
872  settings["gcm_registration_url"] = "http://alternative.url/registration";
873  CompleteCheckin(kDeviceAndroidId,
874                  kDeviceSecurityToken,
875                  GServicesSettings::CalculateDigest(settings),
876                  settings);
877
878  std::map<std::string, std::string> account_tokens;
879  account_tokens["test_user1@gmail.com"] = "token1";
880  account_tokens["test_user2@gmail.com"] = "token2";
881  gcm_client()->SetAccountsForCheckin(account_tokens);
882  PumpLoopUntilIdle();
883  CompleteCheckin(kDeviceAndroidId,
884                  kDeviceSecurityToken,
885                  GServicesSettings::CalculateDigest(settings),
886                  settings);
887
888  EXPECT_EQ(2UL, device_checkin_info().last_checkin_accounts.size());
889  EXPECT_TRUE(device_checkin_info().accounts_set);
890  EXPECT_EQ(account_tokens, device_checkin_info().account_tokens);
891
892  account_tokens.erase(account_tokens.find("test_user2@gmail.com"));
893  gcm_client()->SetAccountsForCheckin(account_tokens);
894
895  PumpLoopUntilIdle();
896  CompleteCheckin(kDeviceAndroidId,
897                  kDeviceSecurityToken,
898                  GServicesSettings::CalculateDigest(settings),
899                  settings);
900
901  std::set<std::string> accounts;
902  accounts.insert("test_user1@gmail.com");
903  EXPECT_EQ(accounts, device_checkin_info().last_checkin_accounts);
904  EXPECT_TRUE(device_checkin_info().accounts_set);
905  EXPECT_EQ(account_tokens, device_checkin_info().account_tokens);
906}
907
908// This test only checks that periodic checkin happens.
909TEST_F(GCMClientImplCheckinTest, CheckinWhenAccountReplaced) {
910  std::map<std::string, std::string> settings;
911  settings["checkin_interval"] = base::IntToString(kSettingsCheckinInterval);
912  settings["checkin_url"] = "http://alternative.url/checkin";
913  settings["gcm_hostname"] = "alternative.gcm.host";
914  settings["gcm_secure_port"] = "7777";
915  settings["gcm_registration_url"] = "http://alternative.url/registration";
916  CompleteCheckin(kDeviceAndroidId,
917                  kDeviceSecurityToken,
918                  GServicesSettings::CalculateDigest(settings),
919                  settings);
920
921  std::map<std::string, std::string> account_tokens;
922  account_tokens["test_user1@gmail.com"] = "token1";
923  gcm_client()->SetAccountsForCheckin(account_tokens);
924
925  PumpLoopUntilIdle();
926  CompleteCheckin(kDeviceAndroidId,
927                  kDeviceSecurityToken,
928                  GServicesSettings::CalculateDigest(settings),
929                  settings);
930
931  std::set<std::string> accounts;
932  accounts.insert("test_user1@gmail.com");
933  EXPECT_EQ(accounts, device_checkin_info().last_checkin_accounts);
934
935  // This should trigger another checkin, because the list of accounts is
936  // different.
937  account_tokens.erase(account_tokens.find("test_user1@gmail.com"));
938  account_tokens["test_user2@gmail.com"] = "token2";
939  gcm_client()->SetAccountsForCheckin(account_tokens);
940
941  PumpLoopUntilIdle();
942  CompleteCheckin(kDeviceAndroidId,
943                  kDeviceSecurityToken,
944                  GServicesSettings::CalculateDigest(settings),
945                  settings);
946
947  accounts.clear();
948  accounts.insert("test_user2@gmail.com");
949  EXPECT_EQ(accounts, device_checkin_info().last_checkin_accounts);
950  EXPECT_TRUE(device_checkin_info().accounts_set);
951  EXPECT_EQ(account_tokens, device_checkin_info().account_tokens);
952}
953
954class GCMClientImplStartAndStopTest : public GCMClientImplTest {
955public:
956  GCMClientImplStartAndStopTest();
957  virtual ~GCMClientImplStartAndStopTest();
958
959  virtual void SetUp() OVERRIDE;
960};
961
962GCMClientImplStartAndStopTest::GCMClientImplStartAndStopTest() {
963}
964
965GCMClientImplStartAndStopTest::~GCMClientImplStartAndStopTest() {
966}
967
968void GCMClientImplStartAndStopTest::SetUp() {
969  testing::Test::SetUp();
970  ASSERT_TRUE(CreateUniqueTempDir());
971  InitializeLoop();
972  BuildGCMClient(base::TimeDelta());
973  InitializeGCMClient();
974}
975
976TEST_F(GCMClientImplStartAndStopTest, StartStopAndRestart) {
977  // Start the GCM and wait until it is ready.
978  gcm_client()->Start();
979  PumpLoopUntilIdle();
980
981  // Stop the GCM.
982  gcm_client()->Stop();
983  PumpLoopUntilIdle();
984
985  // Restart the GCM.
986  gcm_client()->Start();
987  PumpLoopUntilIdle();
988}
989
990TEST_F(GCMClientImplStartAndStopTest, StartAndStopImmediately) {
991  // Start the GCM and then stop it immediately.
992  gcm_client()->Start();
993  gcm_client()->Stop();
994
995  PumpLoopUntilIdle();
996}
997
998TEST_F(GCMClientImplStartAndStopTest, StartStopAndRestartImmediately) {
999  // Start the GCM and then stop and restart it immediately.
1000  gcm_client()->Start();
1001  gcm_client()->Stop();
1002  gcm_client()->Start();
1003
1004  PumpLoopUntilIdle();
1005}
1006
1007}  // namespace gcm
1008