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
11namespace extensions {
12
13class MockDnsSdDeviceLister : public DnsSdDeviceLister {
14 public:
15  MockDnsSdDeviceLister() : DnsSdDeviceLister(NULL, NULL, "") {}
16  virtual ~MockDnsSdDeviceLister() {}
17
18  virtual void Discover(bool force_update) OVERRIDE {}
19};
20
21class 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
59class MockDnsSdObserver : public DnsSdRegistry::DnsSdObserver {
60 public:
61  MOCK_METHOD2(OnDnsSdEvent, void(const std::string&,
62                                  const DnsSdRegistry::DnsSdServiceList&));
63};
64
65class 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.
82TEST_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.
98TEST_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.
129TEST_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.
152TEST_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.
176TEST_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.
205TEST_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