1// Copyright (c) 2012 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 "jingle/notifier/listener/non_blocking_push_client.h"
6
7#include <cstddef>
8
9#include "base/compiler_specific.h"
10#include "base/memory/scoped_ptr.h"
11#include "base/message_loop/message_loop.h"
12#include "jingle/notifier/base/fake_base_task.h"
13#include "jingle/notifier/listener/fake_push_client.h"
14#include "jingle/notifier/listener/fake_push_client_observer.h"
15#include "jingle/notifier/listener/push_client_observer.h"
16#include "net/url_request/url_request_test_util.h"
17#include "testing/gtest/include/gtest/gtest.h"
18
19namespace notifier {
20
21namespace {
22
23class NonBlockingPushClientTest : public testing::Test {
24 protected:
25  NonBlockingPushClientTest() : fake_push_client_(NULL) {}
26
27  virtual ~NonBlockingPushClientTest() {}
28
29  virtual void SetUp() OVERRIDE {
30    push_client_.reset(
31        new NonBlockingPushClient(
32            base::MessageLoopProxy::current(),
33            base::Bind(&NonBlockingPushClientTest::CreateFakePushClient,
34                       base::Unretained(this))));
35    push_client_->AddObserver(&fake_observer_);
36    // Pump message loop to run CreateFakePushClient.
37    message_loop_.RunUntilIdle();
38  }
39
40  virtual void TearDown() OVERRIDE {
41    // Clear out any pending notifications before removing observers.
42    message_loop_.RunUntilIdle();
43    push_client_->RemoveObserver(&fake_observer_);
44    push_client_.reset();
45    // Then pump message loop to run
46    // NonBlockingPushClient::DestroyOnDelegateThread().
47    message_loop_.RunUntilIdle();
48  }
49
50  scoped_ptr<PushClient> CreateFakePushClient() {
51    if (fake_push_client_) {
52      ADD_FAILURE();
53      return scoped_ptr<PushClient>();
54    }
55    fake_push_client_ = new FakePushClient();
56    return scoped_ptr<PushClient>(fake_push_client_);
57  }
58
59  base::MessageLoop message_loop_;
60  FakePushClientObserver fake_observer_;
61  scoped_ptr<NonBlockingPushClient> push_client_;
62  // Owned by |push_client_|.
63  FakePushClient* fake_push_client_;
64};
65
66// Make sure UpdateSubscriptions() gets delegated properly.
67TEST_F(NonBlockingPushClientTest, UpdateSubscriptions) {
68  SubscriptionList subscriptions(10);
69  subscriptions[0].channel = "channel";
70  subscriptions[9].from = "from";
71
72  push_client_->UpdateSubscriptions(subscriptions);
73  EXPECT_TRUE(fake_push_client_->subscriptions().empty());
74  message_loop_.RunUntilIdle();
75  EXPECT_TRUE(
76      SubscriptionListsEqual(
77          fake_push_client_->subscriptions(), subscriptions));
78}
79
80// Make sure UpdateCredentials() gets delegated properly.
81TEST_F(NonBlockingPushClientTest, UpdateCredentials) {
82  const char kEmail[] = "foo@bar.com";
83  const char kToken[] = "baz";
84
85  push_client_->UpdateCredentials(kEmail, kToken);
86  EXPECT_TRUE(fake_push_client_->email().empty());
87  EXPECT_TRUE(fake_push_client_->token().empty());
88  message_loop_.RunUntilIdle();
89  EXPECT_EQ(kEmail, fake_push_client_->email());
90  EXPECT_EQ(kToken, fake_push_client_->token());
91}
92
93Notification MakeTestNotification() {
94  Notification notification;
95  notification.channel = "channel";
96  notification.recipients.resize(10);
97  notification.recipients[0].to = "to";
98  notification.recipients[9].user_specific_data = "user_specific_data";
99  notification.data = "data";
100  return notification;
101}
102
103// Make sure SendNotification() gets delegated properly.
104TEST_F(NonBlockingPushClientTest, SendNotification) {
105  const Notification notification = MakeTestNotification();
106
107  push_client_->SendNotification(notification);
108  EXPECT_TRUE(fake_push_client_->sent_notifications().empty());
109  message_loop_.RunUntilIdle();
110  ASSERT_EQ(1u, fake_push_client_->sent_notifications().size());
111  EXPECT_TRUE(
112      fake_push_client_->sent_notifications()[0].Equals(notification));
113}
114
115// Make sure SendPing() gets delegated properly.
116TEST_F(NonBlockingPushClientTest, SendPing) {
117  push_client_->SendPing();
118  EXPECT_EQ(0, fake_push_client_->sent_pings());
119  message_loop_.RunUntilIdle();
120  ASSERT_EQ(1, fake_push_client_->sent_pings());
121}
122
123// Make sure notification state changes get propagated back to the
124// parent.
125TEST_F(NonBlockingPushClientTest, NotificationStateChange) {
126  EXPECT_EQ(DEFAULT_NOTIFICATION_ERROR,
127            fake_observer_.last_notifications_disabled_reason());
128  fake_push_client_->EnableNotifications();
129  message_loop_.RunUntilIdle();
130  EXPECT_EQ(NO_NOTIFICATION_ERROR,
131            fake_observer_.last_notifications_disabled_reason());
132  fake_push_client_->DisableNotifications(
133      NOTIFICATION_CREDENTIALS_REJECTED);
134  message_loop_.RunUntilIdle();
135  EXPECT_EQ(NOTIFICATION_CREDENTIALS_REJECTED,
136            fake_observer_.last_notifications_disabled_reason());
137}
138
139// Make sure incoming notifications get propagated back to the parent.
140TEST_F(NonBlockingPushClientTest, OnIncomingNotification) {
141  const Notification notification = MakeTestNotification();
142
143  fake_push_client_->SimulateIncomingNotification(notification);
144  message_loop_.RunUntilIdle();
145  EXPECT_TRUE(
146      fake_observer_.last_incoming_notification().Equals(notification));
147}
148
149}  // namespace
150
151}  // namespace notifier
152