Home | History | Annotate | Download | only in invalidation
      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 <string>
      6 
      7 #include "base/compiler_specific.h"
      8 #include "components/invalidation/push_client_channel.h"
      9 #include "jingle/notifier/listener/fake_push_client.h"
     10 #include "jingle/notifier/listener/notification_defines.h"
     11 #include "testing/gtest/include/gtest/gtest.h"
     12 
     13 namespace syncer {
     14 namespace {
     15 
     16 class PushClientChannelTest
     17     : public ::testing::Test,
     18       public SyncNetworkChannel::Observer {
     19  protected:
     20   PushClientChannelTest()
     21       : fake_push_client_(new notifier::FakePushClient()),
     22         push_client_channel_(
     23             scoped_ptr<notifier::PushClient>(fake_push_client_)),
     24         last_invalidator_state_(DEFAULT_INVALIDATION_ERROR) {
     25     push_client_channel_.AddObserver(this);
     26     push_client_channel_.SetMessageReceiver(
     27         invalidation::NewPermanentCallback(
     28             this, &PushClientChannelTest::OnIncomingMessage));
     29     push_client_channel_.SetSystemResources(NULL);
     30   }
     31 
     32   virtual ~PushClientChannelTest() {
     33     push_client_channel_.RemoveObserver(this);
     34   }
     35 
     36   virtual void OnNetworkChannelStateChanged(
     37       InvalidatorState invalidator_state) OVERRIDE {
     38     last_invalidator_state_ = invalidator_state;
     39   }
     40 
     41   void OnIncomingMessage(std::string incoming_message) {
     42     last_message_ = incoming_message;
     43   }
     44 
     45   notifier::FakePushClient* fake_push_client_;
     46   PushClientChannel push_client_channel_;
     47   std::string last_message_;
     48   InvalidatorState last_invalidator_state_;
     49 };
     50 
     51 const char kMessage[] = "message";
     52 const char kServiceContext[] = "service context";
     53 const int64 kSchedulingHash = 100;
     54 
     55 // Make sure the channel subscribes to the correct notifications
     56 // channel on construction.
     57 TEST_F(PushClientChannelTest, Subscriptions) {
     58   notifier::Subscription expected_subscription;
     59   expected_subscription.channel = "tango_raw";
     60   EXPECT_TRUE(notifier::SubscriptionListsEqual(
     61       fake_push_client_->subscriptions(),
     62       notifier::SubscriptionList(1, expected_subscription)));
     63 }
     64 
     65 // Call UpdateCredentials on the channel.  It should propagate it to
     66 // the push client.
     67 TEST_F(PushClientChannelTest, UpdateCredentials) {
     68   const char kEmail[] = "foo (at) bar.com";
     69   const char kToken[] = "token";
     70   EXPECT_TRUE(fake_push_client_->email().empty());
     71   EXPECT_TRUE(fake_push_client_->token().empty());
     72   push_client_channel_.UpdateCredentials(kEmail, kToken);
     73   EXPECT_EQ(kEmail, fake_push_client_->email());
     74   EXPECT_EQ(kToken, fake_push_client_->token());
     75 }
     76 
     77 // Simulate push client state changes on the push client.  It should
     78 // propagate to the channel.
     79 TEST_F(PushClientChannelTest, OnPushClientStateChange) {
     80   EXPECT_EQ(DEFAULT_INVALIDATION_ERROR, last_invalidator_state_);
     81   fake_push_client_->EnableNotifications();
     82   EXPECT_EQ(INVALIDATIONS_ENABLED, last_invalidator_state_);
     83   fake_push_client_->DisableNotifications(
     84       notifier::TRANSIENT_NOTIFICATION_ERROR);
     85   EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, last_invalidator_state_);
     86   fake_push_client_->DisableNotifications(
     87       notifier::NOTIFICATION_CREDENTIALS_REJECTED);
     88   EXPECT_EQ(INVALIDATION_CREDENTIALS_REJECTED, last_invalidator_state_);
     89 }
     90 
     91 // Call SendMessage on the channel.  It should propagate it to the
     92 // push client.
     93 TEST_F(PushClientChannelTest, SendMessage) {
     94   EXPECT_TRUE(fake_push_client_->sent_notifications().empty());
     95   push_client_channel_.SendMessage(kMessage);
     96   ASSERT_EQ(1u, fake_push_client_->sent_notifications().size());
     97   std::string expected_encoded_message =
     98       PushClientChannel::EncodeMessageForTest(
     99           kMessage,
    100           push_client_channel_.GetServiceContextForTest(),
    101           push_client_channel_.GetSchedulingHashForTest());
    102   ASSERT_EQ(expected_encoded_message,
    103             fake_push_client_->sent_notifications()[0].data);
    104 }
    105 
    106 // Encode a message with some context and then decode it.  The decoded info
    107 // should match the original info.
    108 TEST_F(PushClientChannelTest, EncodeDecode) {
    109   const std::string& data = PushClientChannel::EncodeMessageForTest(
    110       kMessage, kServiceContext, kSchedulingHash);
    111   std::string message;
    112   std::string service_context;
    113   int64 scheduling_hash = 0LL;
    114   EXPECT_TRUE(PushClientChannel::DecodeMessageForTest(
    115       data, &message, &service_context, &scheduling_hash));
    116   EXPECT_EQ(kMessage, message);
    117   EXPECT_EQ(kServiceContext, service_context);
    118   EXPECT_EQ(kSchedulingHash, scheduling_hash);
    119 }
    120 
    121 // Encode a message with no context and then decode it.  The decoded message
    122 // should match the original message, but the context and hash should be
    123 // untouched.
    124 TEST_F(PushClientChannelTest, EncodeDecodeNoContext) {
    125   const std::string& data = PushClientChannel::EncodeMessageForTest(
    126       kMessage, std::string(), kSchedulingHash);
    127   std::string message;
    128   std::string service_context = kServiceContext;
    129   int64 scheduling_hash = kSchedulingHash + 1;
    130   EXPECT_TRUE(PushClientChannel::DecodeMessageForTest(
    131       data, &message, &service_context, &scheduling_hash));
    132   EXPECT_EQ(kMessage, message);
    133   EXPECT_EQ(kServiceContext, service_context);
    134   EXPECT_EQ(kSchedulingHash + 1, scheduling_hash);
    135 }
    136 
    137 // Decode an empty notification. It should result in an empty message
    138 // but should leave the context and hash untouched.
    139 TEST_F(PushClientChannelTest, DecodeEmpty) {
    140   std::string message = kMessage;
    141   std::string service_context = kServiceContext;
    142   int64 scheduling_hash = kSchedulingHash;
    143   EXPECT_TRUE(PushClientChannel::DecodeMessageForTest(
    144       std::string(), &message, &service_context, &scheduling_hash));
    145   EXPECT_TRUE(message.empty());
    146   EXPECT_EQ(kServiceContext, service_context);
    147   EXPECT_EQ(kSchedulingHash, scheduling_hash);
    148 }
    149 
    150 // Try to decode a garbage notification.  It should leave all its
    151 // arguments untouched and return false.
    152 TEST_F(PushClientChannelTest, DecodeGarbage) {
    153   std::string data = "garbage";
    154   std::string message = kMessage;
    155   std::string service_context = kServiceContext;
    156   int64 scheduling_hash = kSchedulingHash;
    157   EXPECT_FALSE(PushClientChannel::DecodeMessageForTest(
    158       data, &message, &service_context, &scheduling_hash));
    159   EXPECT_EQ(kMessage, message);
    160   EXPECT_EQ(kServiceContext, service_context);
    161   EXPECT_EQ(kSchedulingHash, scheduling_hash);
    162 }
    163 
    164 // Simulate an incoming notification. It should be decoded properly
    165 // by the channel.
    166 TEST_F(PushClientChannelTest, OnIncomingMessage) {
    167   notifier::Notification notification;
    168   notification.data =
    169       PushClientChannel::EncodeMessageForTest(
    170           kMessage, kServiceContext, kSchedulingHash);
    171   fake_push_client_->SimulateIncomingNotification(notification);
    172 
    173   EXPECT_EQ(kServiceContext,
    174             push_client_channel_.GetServiceContextForTest());
    175   EXPECT_EQ(kSchedulingHash,
    176             push_client_channel_.GetSchedulingHashForTest());
    177   EXPECT_EQ(kMessage, last_message_);
    178 }
    179 
    180 // Simulate an incoming notification with no receiver. It should be dropped by
    181 // the channel.
    182 TEST_F(PushClientChannelTest, OnIncomingMessageNoReceiver) {
    183   push_client_channel_.SetMessageReceiver(NULL);
    184 
    185   notifier::Notification notification;
    186   notification.data = PushClientChannel::EncodeMessageForTest(
    187       kMessage, kServiceContext, kSchedulingHash);
    188   fake_push_client_->SimulateIncomingNotification(notification);
    189 
    190   EXPECT_TRUE(push_client_channel_.GetServiceContextForTest().empty());
    191   EXPECT_EQ(static_cast<int64>(0),
    192             push_client_channel_.GetSchedulingHashForTest());
    193   EXPECT_TRUE(last_message_.empty());
    194 }
    195 
    196 // Simulate an incoming garbage notification. It should be dropped by
    197 // the channel.
    198 TEST_F(PushClientChannelTest, OnIncomingMessageGarbage) {
    199   notifier::Notification notification;
    200   notification.data = "garbage";
    201   fake_push_client_->SimulateIncomingNotification(notification);
    202   EXPECT_TRUE(push_client_channel_.GetServiceContextForTest().empty());
    203   EXPECT_EQ(static_cast<int64>(0),
    204             push_client_channel_.GetSchedulingHashForTest());
    205   EXPECT_TRUE(last_message_.empty());
    206 }
    207 
    208 // Send a message, simulate an incoming message with context, and then
    209 // send the same message again.  The first sent message should not
    210 // have any context, but the second sent message should have the
    211 // context from the incoming emssage.
    212 TEST_F(PushClientChannelTest, PersistedMessageState) {
    213   push_client_channel_.SendMessage(kMessage);
    214   ASSERT_EQ(1u, fake_push_client_->sent_notifications().size());
    215   {
    216     std::string message;
    217     std::string service_context;
    218     int64 scheduling_hash = 0LL;
    219     EXPECT_TRUE(PushClientChannel::DecodeMessageForTest(
    220         fake_push_client_->sent_notifications()[0].data,
    221         &message,
    222         &service_context,
    223         &scheduling_hash));
    224     EXPECT_EQ(kMessage, message);
    225     EXPECT_TRUE(service_context.empty());
    226     EXPECT_EQ(0LL, scheduling_hash);
    227   }
    228 
    229   notifier::Notification notification;
    230   notification.data = PushClientChannel::EncodeMessageForTest(
    231       kMessage, kServiceContext, kSchedulingHash);
    232   fake_push_client_->SimulateIncomingNotification(notification);
    233 
    234   push_client_channel_.SendMessage(kMessage);
    235   ASSERT_EQ(2u, fake_push_client_->sent_notifications().size());
    236   {
    237     std::string message;
    238     std::string service_context;
    239     int64 scheduling_hash = 0LL;
    240     EXPECT_TRUE(PushClientChannel::DecodeMessageForTest(
    241         fake_push_client_->sent_notifications()[1].data,
    242         &message,
    243         &service_context,
    244         &scheduling_hash));
    245     EXPECT_EQ(kMessage, message);
    246     EXPECT_EQ(kServiceContext, service_context);
    247     EXPECT_EQ(kSchedulingHash, scheduling_hash);
    248   }
    249 }
    250 
    251 }  // namespace
    252 }  // namespace syncer
    253