Home | History | Annotate | Download | only in mdns
      1 // Copyright 2013 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 "chrome/browser/extensions/api/mdns/dns_sd_registry.h"
      6 #include "chrome/browser/extensions/api/mdns/dns_sd_delegate.h"
      7 #include "chrome/browser/extensions/api/mdns/dns_sd_device_lister.h"
      8 #include "testing/gmock/include/gmock/gmock.h"
      9 #include "testing/gtest/include/gtest/gtest.h"
     10 
     11 namespace extensions {
     12 
     13 class MockDnsSdDeviceLister : public DnsSdDeviceLister {
     14  public:
     15   MockDnsSdDeviceLister() : DnsSdDeviceLister(NULL, NULL, "") {}
     16   virtual ~MockDnsSdDeviceLister() {}
     17 
     18   virtual void Discover(bool force_update) OVERRIDE {}
     19 };
     20 
     21 class TestDnsSdRegistry : public DnsSdRegistry {
     22  public:
     23   TestDnsSdRegistry() : DnsSdRegistry(NULL), delegate_(NULL) {}
     24   virtual ~TestDnsSdRegistry() {}
     25 
     26   MockDnsSdDeviceLister* GetListerForService(const std::string& service_type) {
     27     return listers_[service_type];
     28   }
     29 
     30   int GetServiceListenerCount(const std::string& service_type) {
     31     if (service_data_map_.find(service_type) == service_data_map_.end())
     32       return 0;
     33 
     34     return service_data_map_[service_type].get()->GetListenerCount();
     35   }
     36 
     37   DnsSdDelegate* GetDelegate() {
     38     return delegate_;
     39   }
     40 
     41  protected:
     42   virtual DnsSdDeviceLister* CreateDnsSdDeviceLister(
     43       DnsSdDelegate* delegate,
     44       const std::string& service_type,
     45       local_discovery::ServiceDiscoverySharedClient* discovery_client)
     46           OVERRIDE {
     47     delegate_ = delegate;
     48     MockDnsSdDeviceLister* lister = new MockDnsSdDeviceLister();
     49     listers_[service_type] = lister;
     50     return lister;
     51   };
     52 
     53  private:
     54   std::map<std::string, MockDnsSdDeviceLister*> listers_;
     55   // The last delegate used or NULL.
     56   DnsSdDelegate* delegate_;
     57 };
     58 
     59 class MockDnsSdObserver : public DnsSdRegistry::DnsSdObserver {
     60  public:
     61   MOCK_METHOD2(OnDnsSdEvent, void(const std::string&,
     62                                   const DnsSdRegistry::DnsSdServiceList&));
     63 };
     64 
     65 class DnsSdRegistryTest : public testing::Test {
     66  public:
     67   DnsSdRegistryTest() {}
     68   virtual ~DnsSdRegistryTest() {}
     69 
     70   virtual void SetUp() OVERRIDE {
     71     registry_.reset(new TestDnsSdRegistry());
     72     registry_->AddObserver(&observer_);
     73   }
     74 
     75  protected:
     76   scoped_ptr<TestDnsSdRegistry> registry_;
     77   MockDnsSdObserver observer_;
     78 };
     79 
     80 // Tests registering 2 listeners and removing one. The device lister should
     81 // not be destroyed.
     82 TEST_F(DnsSdRegistryTest, RegisterUnregisterListeners) {
     83   const std::string service_type = "_testing._tcp.local";
     84 
     85   EXPECT_CALL(observer_, OnDnsSdEvent(service_type,
     86       DnsSdRegistry::DnsSdServiceList())).Times(2);
     87 
     88   registry_->RegisterDnsSdListener(service_type);
     89   registry_->RegisterDnsSdListener(service_type);
     90   registry_->UnregisterDnsSdListener(service_type);
     91   EXPECT_EQ(1, registry_->GetServiceListenerCount(service_type));
     92 
     93   registry_->UnregisterDnsSdListener(service_type);
     94   EXPECT_EQ(0, registry_->GetServiceListenerCount(service_type));
     95 }
     96 
     97 // Tests registering a listener and receiving an added and updated event.
     98 TEST_F(DnsSdRegistryTest, AddAndUpdate) {
     99   const std::string service_type = "_testing._tcp.local";
    100   const std::string ip_address1 = "192.168.0.100";
    101   const std::string ip_address2 = "192.168.0.101";
    102 
    103   DnsSdService service;
    104   service.service_name = "_myDevice." + service_type;
    105   service.ip_address = ip_address1;
    106 
    107   DnsSdRegistry::DnsSdServiceList service_list;
    108 
    109   EXPECT_CALL(observer_, OnDnsSdEvent(service_type, service_list));
    110 
    111   // Add first service.
    112   service_list.push_back(service);
    113   EXPECT_CALL(observer_, OnDnsSdEvent(service_type, service_list));
    114 
    115   // Clear services and add same one with different IP address.
    116   service_list.clear();
    117   service.ip_address = ip_address2;
    118   service_list.push_back(service);
    119   EXPECT_CALL(observer_, OnDnsSdEvent(service_type, service_list));
    120 
    121   registry_->RegisterDnsSdListener(service_type);
    122   service.ip_address = ip_address1;
    123   registry_->GetDelegate()->ServiceChanged(service_type, true, service);
    124   service.ip_address = ip_address2;
    125   registry_->GetDelegate()->ServiceChanged(service_type, false, service);
    126 }
    127 
    128 // Tests registering a listener and receiving an added and removed event.
    129 TEST_F(DnsSdRegistryTest, AddAndRemove) {
    130   const std::string service_type = "_testing._tcp.local";
    131 
    132   DnsSdService service;
    133   service.service_name = "_myDevice." + service_type;
    134   service.ip_address = "192.168.0.100";
    135 
    136   DnsSdRegistry::DnsSdServiceList service_list;
    137   // Expect to be called twice with empty list (once on register, once after
    138   // removing).
    139   EXPECT_CALL(observer_, OnDnsSdEvent(service_type, service_list)).Times(2);
    140   service_list.push_back(service);
    141   // Expect to be called twice with 1 item (once after adding, once after adding
    142   // again after removal).
    143   EXPECT_CALL(observer_, OnDnsSdEvent(service_type, service_list)).Times(2);
    144 
    145   registry_->RegisterDnsSdListener(service_type);
    146   registry_->GetDelegate()->ServiceChanged(service_type, true, service);
    147   registry_->GetDelegate()->ServiceRemoved(service_type, service.service_name);
    148   registry_->GetDelegate()->ServiceChanged(service_type, true, service);
    149 }
    150 
    151 // Tests adding multiple services.
    152 TEST_F(DnsSdRegistryTest, AddMultipleServices) {
    153   const std::string service_type = "_testing._tcp.local";
    154 
    155   DnsSdService service;
    156   service.service_name = "_myDevice." + service_type;
    157   service.ip_address = "192.168.0.100";
    158 
    159   DnsSdService service2;
    160   service.service_name = "_myDevice2." + service_type;
    161   service.ip_address = "192.168.0.101";
    162 
    163   DnsSdRegistry::DnsSdServiceList service_list;
    164   EXPECT_CALL(observer_, OnDnsSdEvent(service_type, service_list));
    165   service_list.push_back(service);
    166   EXPECT_CALL(observer_, OnDnsSdEvent(service_type, service_list));
    167   service_list.push_back(service2);
    168   EXPECT_CALL(observer_, OnDnsSdEvent(service_type, service_list));
    169 
    170   registry_->RegisterDnsSdListener(service_type);
    171   registry_->GetDelegate()->ServiceChanged(service_type, true, service);
    172   registry_->GetDelegate()->ServiceChanged(service_type, true, service2);
    173 }
    174 
    175 // Tests adding multiple services and handling a flush event.
    176 TEST_F(DnsSdRegistryTest, FlushCache) {
    177   testing::InSequence s;
    178   const std::string service_type = "_testing._tcp.local";
    179 
    180   DnsSdService service;
    181   service.service_name = "_myDevice." + service_type;
    182   service.ip_address = "192.168.0.100";
    183 
    184   DnsSdService service2;
    185   service.service_name = "_myDevice2." + service_type;
    186   service.ip_address = "192.168.0.101";
    187 
    188   DnsSdRegistry::DnsSdServiceList service_list;
    189   EXPECT_CALL(observer_, OnDnsSdEvent(service_type, service_list));
    190   service_list.push_back(service);
    191   EXPECT_CALL(observer_, OnDnsSdEvent(service_type, service_list));
    192   service_list.push_back(service2);
    193   EXPECT_CALL(observer_, OnDnsSdEvent(service_type, service_list));
    194   service_list.clear();
    195   EXPECT_CALL(observer_, OnDnsSdEvent(service_type, service_list));
    196 
    197   registry_->RegisterDnsSdListener(service_type);
    198   registry_->GetDelegate()->ServiceChanged(service_type, true, service);
    199   registry_->GetDelegate()->ServiceChanged(service_type, true, service2);
    200   registry_->GetDelegate()->ServicesFlushed(service_type);
    201 }
    202 
    203 // Tests receiving an update from the DnsSdDelegate that does not change the
    204 // service object does not notify the observer.
    205 TEST_F(DnsSdRegistryTest, UpdateOnlyIfChanged) {
    206   const std::string service_type = "_testing._tcp.local";
    207   const std::string ip_address = "192.168.0.100";
    208 
    209   DnsSdService service;
    210   service.service_name = "_myDevice." + service_type;
    211   service.ip_address = ip_address;
    212 
    213   DnsSdRegistry::DnsSdServiceList service_list;
    214   EXPECT_CALL(observer_, OnDnsSdEvent(service_type, service_list));
    215 
    216   // Expect service_list with initial service.
    217   service_list.push_back(service);
    218   EXPECT_CALL(observer_, OnDnsSdEvent(service_type, service_list));
    219 
    220   // Expect service_list with updated service.
    221   service_list.clear();
    222   service.ip_address = "192.168.0.101";
    223   service_list.push_back(service);
    224   EXPECT_CALL(observer_, OnDnsSdEvent(service_type, service_list));
    225   // No more calls to observer_.
    226 
    227   registry_->RegisterDnsSdListener(service_type);
    228   service.ip_address = "192.168.0.100";
    229   registry_->GetDelegate()->ServiceChanged(service_type, true, service);
    230   // Update with changed ip address.
    231   service.ip_address = "192.168.0.101";
    232   registry_->GetDelegate()->ServiceChanged(service_type, false, service);
    233   // Update with no changes to the service.
    234   registry_->GetDelegate()->ServiceChanged(service_type, false, service);
    235 }
    236 
    237 }  // namespace extensions
    238