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