Home | History | Annotate | Download | only in page
      1 /*
      2  * Copyright (c) 2014, Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "config.h"
     32 #include "core/page/NetworkStateNotifier.h"
     33 
     34 #include "core/dom/Document.h"
     35 #include "public/platform/Platform.h"
     36 #include "public/platform/WebConnectionType.h"
     37 #include "public/platform/WebThread.h"
     38 #include "wtf/Functional.h"
     39 #include <gtest/gtest.h>
     40 
     41 namespace WebCore {
     42 
     43 class StateObserver : public NetworkStateNotifier::NetworkStateObserver {
     44 public:
     45     StateObserver()
     46         : m_observedType(blink::ConnectionTypeNone)
     47         , m_callbackCount(0)
     48     {
     49     }
     50 
     51     virtual void connectionTypeChange(blink::WebConnectionType type)
     52     {
     53         m_observedType = type;
     54         m_callbackCount += 1;
     55 
     56         if (!m_closure.isNull())
     57             m_closure();
     58     }
     59 
     60     blink::WebConnectionType observedType() const
     61     {
     62         return m_observedType;
     63     }
     64 
     65     int callbackCount() const
     66     {
     67         return m_callbackCount;
     68     }
     69 
     70     void setNotificationCallback(const Closure& closure)
     71     {
     72         m_closure = closure;
     73     }
     74 
     75 private:
     76     Closure m_closure;
     77     blink::WebConnectionType m_observedType;
     78     int m_callbackCount;
     79 };
     80 
     81 class ExitTask
     82     : public blink::WebThread::Task {
     83 public:
     84     ExitTask(blink::WebThread* thread)
     85         : m_thread(thread)
     86     {
     87     }
     88     virtual void run() OVERRIDE
     89     {
     90         m_thread->exitRunLoop();
     91     }
     92 
     93 private:
     94     blink::WebThread* m_thread;
     95 };
     96 
     97 class NetworkStateNotifierTest : public testing::Test {
     98 public:
     99     NetworkStateNotifierTest()
    100         : m_document(Document::create())
    101         , m_document2(Document::create())
    102     {
    103     }
    104 
    105     ExecutionContext* executionContext()
    106     {
    107         return m_document.get();
    108     }
    109 
    110     ExecutionContext* executionContext2()
    111     {
    112         return m_document2.get();
    113     }
    114 
    115 protected:
    116     void setType(blink::WebConnectionType type)
    117     {
    118         m_notifier.setWebConnectionType(type);
    119 
    120         blink::WebThread* thread = blink::Platform::current()->currentThread();
    121         thread->postTask(new ExitTask(thread));
    122         thread->enterRunLoop();
    123     }
    124 
    125     void addObserverOnNotification(StateObserver* observer, StateObserver* observerToAdd)
    126     {
    127         observer->setNotificationCallback(bind(&NetworkStateNotifier::addObserver, &m_notifier, observerToAdd, executionContext()));
    128     }
    129 
    130     void removeObserverOnNotification(StateObserver* observer, StateObserver* observerToRemove)
    131     {
    132         observer->setNotificationCallback(bind(&NetworkStateNotifier::removeObserver, &m_notifier, observerToRemove, executionContext()));
    133     }
    134 
    135     RefPtrWillBePersistent<Document> m_document;
    136     RefPtrWillBePersistent<Document> m_document2;
    137     NetworkStateNotifier m_notifier;
    138 };
    139 
    140 TEST_F(NetworkStateNotifierTest, AddObserver)
    141 {
    142     StateObserver observer;
    143     m_notifier.addObserver(&observer, executionContext());
    144     EXPECT_EQ(observer.observedType(), blink::ConnectionTypeNone);
    145 
    146     setType(blink::ConnectionTypeBluetooth);
    147     EXPECT_EQ(observer.observedType(), blink::ConnectionTypeBluetooth);
    148     EXPECT_EQ(observer.callbackCount(), 1);
    149 }
    150 
    151 TEST_F(NetworkStateNotifierTest, RemoveObserver)
    152 {
    153     StateObserver observer1, observer2;
    154     m_notifier.addObserver(&observer1, executionContext());
    155     m_notifier.removeObserver(&observer1, executionContext());
    156     m_notifier.addObserver(&observer2, executionContext());
    157 
    158     setType(blink::ConnectionTypeBluetooth);
    159     EXPECT_EQ(observer1.observedType(), blink::ConnectionTypeNone);
    160     EXPECT_EQ(observer2.observedType(), blink::ConnectionTypeBluetooth);
    161 }
    162 
    163 TEST_F(NetworkStateNotifierTest, RemoveSoleObserver)
    164 {
    165     StateObserver observer1, observer2;
    166     m_notifier.addObserver(&observer1, executionContext());
    167     m_notifier.removeObserver(&observer1, executionContext());
    168 
    169     setType(blink::ConnectionTypeBluetooth);
    170     EXPECT_EQ(observer1.observedType(), blink::ConnectionTypeNone);
    171 }
    172 
    173 TEST_F(NetworkStateNotifierTest, AddObserverWhileNotifying)
    174 {
    175     StateObserver observer1, observer2;
    176     m_notifier.addObserver(&observer1, executionContext());
    177     addObserverOnNotification(&observer1, &observer2);
    178 
    179     setType(blink::ConnectionTypeBluetooth);
    180     EXPECT_EQ(observer1.observedType(), blink::ConnectionTypeBluetooth);
    181     EXPECT_EQ(observer2.observedType(), blink::ConnectionTypeBluetooth);
    182 }
    183 
    184 TEST_F(NetworkStateNotifierTest, RemoveSoleObserverWhileNotifying)
    185 {
    186     StateObserver observer1;
    187     m_notifier.addObserver(&observer1, executionContext());
    188     removeObserverOnNotification(&observer1, &observer1);
    189 
    190     setType(blink::ConnectionTypeBluetooth);
    191     EXPECT_EQ(observer1.observedType(), blink::ConnectionTypeBluetooth);
    192 
    193     setType(blink::ConnectionTypeEthernet);
    194     EXPECT_EQ(observer1.observedType(), blink::ConnectionTypeBluetooth);
    195 }
    196 
    197 TEST_F(NetworkStateNotifierTest, RemoveCurrentObserverWhileNotifying)
    198 {
    199     StateObserver observer1, observer2;
    200     m_notifier.addObserver(&observer1, executionContext());
    201     m_notifier.addObserver(&observer2, executionContext());
    202     removeObserverOnNotification(&observer1, &observer1);
    203 
    204     setType(blink::ConnectionTypeBluetooth);
    205     EXPECT_EQ(observer1.observedType(), blink::ConnectionTypeBluetooth);
    206     EXPECT_EQ(observer2.observedType(), blink::ConnectionTypeBluetooth);
    207 
    208     setType(blink::ConnectionTypeEthernet);
    209     EXPECT_EQ(observer1.observedType(), blink::ConnectionTypeBluetooth);
    210     EXPECT_EQ(observer2.observedType(), blink::ConnectionTypeEthernet);
    211 }
    212 
    213 TEST_F(NetworkStateNotifierTest, RemovePastObserverWhileNotifying)
    214 {
    215     StateObserver observer1, observer2;
    216     m_notifier.addObserver(&observer1, executionContext());
    217     m_notifier.addObserver(&observer2, executionContext());
    218     removeObserverOnNotification(&observer2, &observer1);
    219 
    220     setType(blink::ConnectionTypeBluetooth);
    221     EXPECT_EQ(observer1.observedType(), blink::ConnectionTypeBluetooth);
    222     EXPECT_EQ(observer2.observedType(), blink::ConnectionTypeBluetooth);
    223 
    224     setType(blink::ConnectionTypeEthernet);
    225     EXPECT_EQ(observer1.observedType(), blink::ConnectionTypeBluetooth);
    226     EXPECT_EQ(observer2.observedType(), blink::ConnectionTypeEthernet);
    227 }
    228 
    229 TEST_F(NetworkStateNotifierTest, RemoveFutureObserverWhileNotifying)
    230 {
    231     StateObserver observer1, observer2, observer3;
    232     m_notifier.addObserver(&observer1, executionContext());
    233     m_notifier.addObserver(&observer2, executionContext());
    234     m_notifier.addObserver(&observer3, executionContext());
    235     removeObserverOnNotification(&observer1, &observer2);
    236 
    237     setType(blink::ConnectionTypeBluetooth);
    238 
    239     EXPECT_EQ(observer1.observedType(), blink::ConnectionTypeBluetooth);
    240     EXPECT_EQ(observer2.observedType(), blink::ConnectionTypeNone);
    241     EXPECT_EQ(observer3.observedType(), blink::ConnectionTypeBluetooth);
    242 }
    243 
    244 TEST_F(NetworkStateNotifierTest, MultipleContextsAddObserver)
    245 {
    246     StateObserver observer1, observer2;
    247     m_notifier.addObserver(&observer1, executionContext());
    248     m_notifier.addObserver(&observer2, executionContext2());
    249 
    250     setType(blink::ConnectionTypeBluetooth);
    251     EXPECT_EQ(observer1.observedType(), blink::ConnectionTypeBluetooth);
    252     EXPECT_EQ(observer2.observedType(), blink::ConnectionTypeBluetooth);
    253 }
    254 
    255 TEST_F(NetworkStateNotifierTest, RemoveContext)
    256 {
    257     StateObserver observer1, observer2;
    258     m_notifier.addObserver(&observer1, executionContext());
    259     m_notifier.addObserver(&observer2, executionContext2());
    260     m_notifier.removeObserver(&observer2, executionContext2());
    261 
    262     setType(blink::ConnectionTypeBluetooth);
    263     EXPECT_EQ(observer1.observedType(), blink::ConnectionTypeBluetooth);
    264     EXPECT_EQ(observer2.observedType(), blink::ConnectionTypeNone);
    265 }
    266 
    267 TEST_F(NetworkStateNotifierTest, RemoveAllContexts)
    268 {
    269     StateObserver observer1, observer2;
    270     m_notifier.addObserver(&observer1, executionContext());
    271     m_notifier.addObserver(&observer2, executionContext2());
    272     m_notifier.removeObserver(&observer1, executionContext());
    273     m_notifier.removeObserver(&observer2, executionContext2());
    274 
    275     setType(blink::ConnectionTypeBluetooth);
    276     EXPECT_EQ(observer1.observedType(), blink::ConnectionTypeNone);
    277     EXPECT_EQ(observer2.observedType(), blink::ConnectionTypeNone);
    278 }
    279 
    280 } // namespace WebCore
    281