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// See network_change_notifier_android.h for design explanations.
6
7#include "base/basictypes.h"
8#include "base/bind.h"
9#include "base/callback.h"
10#include "base/compiler_specific.h"
11#include "base/message_loop/message_loop.h"
12#include "net/android/network_change_notifier_android.h"
13#include "net/android/network_change_notifier_delegate_android.h"
14#include "net/base/network_change_notifier.h"
15#include "testing/gtest/include/gtest/gtest.h"
16
17namespace net {
18
19namespace {
20
21class NetworkChangeNotifierDelegateAndroidObserver
22    : public NetworkChangeNotifierDelegateAndroid::Observer {
23 public:
24  NetworkChangeNotifierDelegateAndroidObserver() : notifications_count_(0) {}
25
26  // NetworkChangeNotifierDelegateAndroid::Observer:
27  virtual void OnConnectionTypeChanged() OVERRIDE {
28    notifications_count_++;
29  }
30
31  int notifications_count() const {
32    return notifications_count_;
33  }
34
35 private:
36  int notifications_count_;
37};
38
39class NetworkChangeNotifierObserver
40    : public NetworkChangeNotifier::ConnectionTypeObserver {
41 public:
42  NetworkChangeNotifierObserver() : notifications_count_(0) {}
43
44  // NetworkChangeNotifier::Observer:
45  virtual void OnConnectionTypeChanged(
46      NetworkChangeNotifier::ConnectionType connection_type) OVERRIDE {
47    notifications_count_++;
48  }
49
50  int notifications_count() const {
51    return notifications_count_;
52  }
53
54 private:
55  int notifications_count_;
56};
57
58}  // namespace
59
60class BaseNetworkChangeNotifierAndroidTest : public testing::Test {
61 protected:
62  typedef NetworkChangeNotifier::ConnectionType ConnectionType;
63
64  virtual ~BaseNetworkChangeNotifierAndroidTest() {}
65
66  void RunTest(
67      const base::Callback<int(void)>& notifications_count_getter,
68      const base::Callback<ConnectionType(void)>&  connection_type_getter) {
69    EXPECT_EQ(0, notifications_count_getter.Run());
70    EXPECT_EQ(NetworkChangeNotifier::CONNECTION_UNKNOWN,
71              connection_type_getter.Run());
72
73    // Changing from online to offline should trigger a notification.
74    SetOffline();
75    EXPECT_EQ(1, notifications_count_getter.Run());
76    EXPECT_EQ(NetworkChangeNotifier::CONNECTION_NONE,
77              connection_type_getter.Run());
78
79    // No notification should be triggered when the offline state hasn't
80    // changed.
81    SetOffline();
82    EXPECT_EQ(1, notifications_count_getter.Run());
83    EXPECT_EQ(NetworkChangeNotifier::CONNECTION_NONE,
84              connection_type_getter.Run());
85
86    // Going from offline to online should trigger a notification.
87    SetOnline();
88    EXPECT_EQ(2, notifications_count_getter.Run());
89    EXPECT_EQ(NetworkChangeNotifier::CONNECTION_UNKNOWN,
90              connection_type_getter.Run());
91  }
92
93  void SetOnline() {
94    delegate_.SetOnline();
95    // Note that this is needed because ObserverListThreadSafe uses PostTask().
96    base::MessageLoop::current()->RunUntilIdle();
97  }
98
99  void SetOffline() {
100    delegate_.SetOffline();
101    // See comment above.
102    base::MessageLoop::current()->RunUntilIdle();
103  }
104
105  NetworkChangeNotifierDelegateAndroid delegate_;
106};
107
108// Tests that NetworkChangeNotifierDelegateAndroid is initialized with the
109// actual connection type rather than a hardcoded one (e.g.
110// CONNECTION_UNKNOWN). Initializing the connection type to CONNECTION_UNKNOWN
111// and relying on the first network change notification to set it correctly can
112// be problematic in case there is a long delay between the delegate's
113// construction and the notification.
114TEST_F(BaseNetworkChangeNotifierAndroidTest,
115       DelegateIsInitializedWithCurrentConnectionType) {
116  SetOffline();
117  ASSERT_EQ(NetworkChangeNotifier::CONNECTION_NONE,
118            delegate_.GetCurrentConnectionType());
119  // Instantiate another delegate to validate that it uses the actual
120  // connection type at construction.
121  scoped_ptr<NetworkChangeNotifierDelegateAndroid> other_delegate(
122      new NetworkChangeNotifierDelegateAndroid());
123  EXPECT_EQ(NetworkChangeNotifier::CONNECTION_NONE,
124            other_delegate->GetCurrentConnectionType());
125
126  // Toggle the global connectivity state and instantiate another delegate
127  // again.
128  SetOnline();
129  ASSERT_EQ(NetworkChangeNotifier::CONNECTION_UNKNOWN,
130            delegate_.GetCurrentConnectionType());
131  other_delegate.reset(new NetworkChangeNotifierDelegateAndroid());
132  EXPECT_EQ(NetworkChangeNotifier::CONNECTION_UNKNOWN,
133            other_delegate->GetCurrentConnectionType());
134}
135
136class NetworkChangeNotifierDelegateAndroidTest
137    : public BaseNetworkChangeNotifierAndroidTest {
138 protected:
139  NetworkChangeNotifierDelegateAndroidTest() {
140    delegate_.AddObserver(&delegate_observer_);
141    delegate_.AddObserver(&other_delegate_observer_);
142  }
143
144  virtual ~NetworkChangeNotifierDelegateAndroidTest() {
145    delegate_.RemoveObserver(&delegate_observer_);
146    delegate_.RemoveObserver(&other_delegate_observer_);
147  }
148
149  NetworkChangeNotifierDelegateAndroidObserver delegate_observer_;
150  NetworkChangeNotifierDelegateAndroidObserver other_delegate_observer_;
151};
152
153// Tests that the NetworkChangeNotifierDelegateAndroid's observers are notified.
154// A testing-only observer is used here for testing. In production the
155// delegate's observers are instances of NetworkChangeNotifierAndroid.
156TEST_F(NetworkChangeNotifierDelegateAndroidTest, DelegateObserverNotified) {
157  // Test the logic with a single observer.
158  RunTest(
159      base::Bind(
160          &NetworkChangeNotifierDelegateAndroidObserver::notifications_count,
161          base::Unretained(&delegate_observer_)),
162      base::Bind(
163          &NetworkChangeNotifierDelegateAndroid::GetCurrentConnectionType,
164          base::Unretained(&delegate_)));
165  // Check that *all* the observers are notified. Both observers should have the
166  // same state.
167  EXPECT_EQ(delegate_observer_.notifications_count(),
168            other_delegate_observer_.notifications_count());
169}
170
171class NetworkChangeNotifierAndroidTest
172    : public BaseNetworkChangeNotifierAndroidTest {
173 protected:
174  NetworkChangeNotifierAndroidTest() : notifier_(&delegate_) {
175    NetworkChangeNotifier::AddConnectionTypeObserver(
176        &connection_type_observer_);
177    NetworkChangeNotifier::AddConnectionTypeObserver(
178        &other_connection_type_observer_);
179  }
180
181  NetworkChangeNotifierObserver connection_type_observer_;
182  NetworkChangeNotifierObserver other_connection_type_observer_;
183  NetworkChangeNotifier::DisableForTest disable_for_test_;
184  NetworkChangeNotifierAndroid notifier_;
185};
186
187// When a NetworkChangeNotifierAndroid is observing a
188// NetworkChangeNotifierDelegateAndroid for network state changes, and the
189// NetworkChangeNotifierDelegateAndroid's connectivity state changes, the
190// NetworkChangeNotifierAndroid should reflect that state.
191TEST_F(NetworkChangeNotifierAndroidTest,
192       NotificationsSentToNetworkChangeNotifierAndroid) {
193  RunTest(
194      base::Bind(
195          &NetworkChangeNotifierObserver::notifications_count,
196          base::Unretained(&connection_type_observer_)),
197      base::Bind(
198          &NetworkChangeNotifierAndroid::GetCurrentConnectionType,
199          base::Unretained(&notifier_)));
200}
201
202// When a NetworkChangeNotifierAndroid's connection state changes, it should
203// notify all of its observers.
204TEST_F(NetworkChangeNotifierAndroidTest,
205       NotificationsSentToClientsOfNetworkChangeNotifier) {
206  RunTest(
207      base::Bind(
208          &NetworkChangeNotifierObserver::notifications_count,
209          base::Unretained(&connection_type_observer_)),
210      base::Bind(&NetworkChangeNotifier::GetConnectionType));
211  // Check that *all* the observers are notified.
212  EXPECT_EQ(connection_type_observer_.notifications_count(),
213            other_connection_type_observer_.notifications_count());
214}
215
216}  // namespace net
217