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