privet_device_lister_unittest.cc revision a3f7b4e666c476898878fa745f637129375cd889
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 "base/bind.h"
6#include "chrome/browser/local_discovery/privet_device_lister_impl.h"
7#include "testing/gmock/include/gmock/gmock.h"
8#include "testing/gtest/include/gtest/gtest.h"
9
10using testing::SaveArg;
11using testing::_;
12
13namespace local_discovery {
14
15namespace {
16
17class MockServiceResolver;
18class MockServiceWatcher;
19
20class ServiceDiscoveryMockDelegate {
21 public:
22  virtual void ServiceWatcherStarted(const std::string& service_type,
23                                     MockServiceWatcher* watcher) = 0;
24  virtual void ServiceResolverStarted(const std::string& service_type,
25                                      MockServiceResolver* resolver) = 0;
26};
27
28class MockServiceWatcher : public ServiceWatcher {
29 public:
30  MockServiceWatcher(const std::string& service_type,
31                     const ServiceWatcher::UpdatedCallback& callback,
32                     ServiceDiscoveryMockDelegate* mock_delegate)
33      : started_(false), service_type_(service_type),  callback_(callback),
34        mock_delegate_(mock_delegate) {
35  }
36
37  virtual ~MockServiceWatcher() {
38  }
39
40  virtual void Start() {
41    DCHECK(!started_);
42    started_ = true;
43    mock_delegate_->ServiceWatcherStarted(service_type_, this);
44  }
45
46  MOCK_METHOD1(DiscoverNewServices, void(bool force_update));
47
48  virtual std::string GetServiceType() const {
49    return service_type_;
50  }
51
52  bool started() {
53    return started_;
54  }
55
56  ServiceWatcher::UpdatedCallback callback() {
57    return callback_;
58  }
59
60 private:
61  bool started_;
62  std::string service_type_;
63  ServiceWatcher::UpdatedCallback callback_;
64  ServiceDiscoveryMockDelegate* mock_delegate_;
65};
66
67class MockServiceResolver : public ServiceResolver {
68 public:
69  MockServiceResolver(const std::string& service_name,
70                      const ServiceResolver::ResolveCompleteCallback& callback,
71                      ServiceDiscoveryMockDelegate* mock_delegate)
72      : started_resolving_(false), service_name_(service_name),
73        callback_(callback), mock_delegate_(mock_delegate) {
74  }
75
76  virtual ~MockServiceResolver() {
77  }
78
79  virtual void StartResolving() OVERRIDE {
80    started_resolving_ = true;
81    mock_delegate_->ServiceResolverStarted(service_name_, this);
82  }
83
84  bool IsResolving() const {
85    return started_resolving_;
86  }
87
88  virtual std::string GetName() const OVERRIDE {
89    return service_name_;
90  }
91
92  const ServiceResolver::ResolveCompleteCallback& callback() {
93    return callback_; }
94
95 private:
96  bool started_resolving_;
97  std::string service_name_;
98  ServiceResolver::ResolveCompleteCallback callback_;
99  ServiceDiscoveryMockDelegate* mock_delegate_;
100};
101
102class MockServiceDiscoveryClient : public ServiceDiscoveryClient {
103 public:
104  explicit MockServiceDiscoveryClient(
105      ServiceDiscoveryMockDelegate* mock_delegate)
106      : mock_delegate_(mock_delegate) {
107  }
108
109  virtual ~MockServiceDiscoveryClient() {
110  }
111
112  // Create a service watcher object listening for DNS-SD service announcements
113  // on service type |service_type|.
114  virtual scoped_ptr<ServiceWatcher> CreateServiceWatcher(
115      const std::string& service_type,
116      const ServiceWatcher::UpdatedCallback& callback) OVERRIDE {
117    scoped_ptr<MockServiceWatcher> mock_service_watcher(
118        new MockServiceWatcher(service_type, callback, mock_delegate_));
119    return mock_service_watcher.PassAs<ServiceWatcher>();
120  }
121
122  // Create a service resolver object for getting detailed service information
123  // for the service called |service_name|.
124  virtual scoped_ptr<ServiceResolver> CreateServiceResolver(
125      const std::string& service_name,
126      const ServiceResolver::ResolveCompleteCallback& callback) OVERRIDE {
127    scoped_ptr<MockServiceResolver> mock_service_resolver(
128        new MockServiceResolver(service_name, callback, mock_delegate_));
129    return mock_service_resolver.PassAs<ServiceResolver>();
130  }
131
132  // Not used in this test.
133  virtual scoped_ptr<LocalDomainResolver> CreateLocalDomainResolver(
134    const std::string& domain,
135    net::AddressFamily address_family,
136    const LocalDomainResolver::IPAddressCallback& callback) OVERRIDE {
137    NOTREACHED();
138    return scoped_ptr<LocalDomainResolver>();
139  }
140
141 private:
142  ServiceDiscoveryMockDelegate* mock_delegate_;
143};
144
145class MockServiceDiscoveryMockDelegate : public ServiceDiscoveryMockDelegate {
146 public:
147  MOCK_METHOD2(ServiceWatcherStarted, void(const std::string& service_type,
148                                           MockServiceWatcher* watcher));
149  MOCK_METHOD2(ServiceResolverStarted, void(const std::string& service_type,
150                                            MockServiceResolver* resolver));
151};
152
153class MockDeviceListerDelegate : public PrivetDeviceLister::Delegate {
154 public:
155  MockDeviceListerDelegate() {
156  }
157
158  virtual ~MockDeviceListerDelegate() {
159  }
160
161  MOCK_METHOD3(DeviceChanged, void(bool added,
162                                   const std::string& name,
163                                   const DeviceDescription& description));
164
165  MOCK_METHOD1(DeviceRemoved, void(const std::string& name));
166};
167
168class PrivetDeviceListerTest : public testing::Test {
169 public:
170  PrivetDeviceListerTest() : mock_client_(&mock_delegate_) {
171  }
172
173  virtual ~PrivetDeviceListerTest() {
174  }
175
176  virtual void SetUp() OVERRIDE {
177    example_attrs_.push_back("tXtvers=1");
178    example_attrs_.push_back("ty=My Printer");
179    example_attrs_.push_back("nOte=This is my Printer");
180    example_attrs_.push_back("CS=ONlInE");
181    example_attrs_.push_back("id=");
182
183    service_description_.service_name = "myprinter._privet._tcp.local";
184    service_description_.address = net::HostPortPair("myprinter.local", 6006);
185    service_description_.metadata = example_attrs_;
186    service_description_.last_seen = base::Time() +
187        base::TimeDelta::FromSeconds(5);
188    service_description_.ip_address.push_back(1);
189    service_description_.ip_address.push_back(2);
190    service_description_.ip_address.push_back(3);
191    service_description_.ip_address.push_back(4);
192  }
193
194 protected:
195  testing::StrictMock<MockServiceDiscoveryMockDelegate> mock_delegate_;
196  MockServiceDiscoveryClient mock_client_;
197  MockDeviceListerDelegate delegate_;
198  std::vector<std::string> example_attrs_;
199  ServiceDescription service_description_;
200};
201
202TEST_F(PrivetDeviceListerTest, SimpleUpdateTest) {
203  DeviceDescription outgoing_description;
204
205  MockServiceWatcher* service_watcher;
206  MockServiceResolver* service_resolver;
207
208  EXPECT_CALL(mock_delegate_,
209              ServiceWatcherStarted("_privet._tcp.local", _))
210      .WillOnce(SaveArg<1>(&service_watcher));
211  PrivetDeviceListerImpl privet_lister(&mock_client_, &delegate_);
212  privet_lister.Start();
213  testing::Mock::VerifyAndClear(&mock_delegate_);
214
215  EXPECT_CALL(mock_delegate_,
216              ServiceResolverStarted("myprinter._privet._tcp.local", _))
217      .WillOnce(SaveArg<1>(&service_resolver));
218  service_watcher->callback().Run(ServiceWatcher::UPDATE_ADDED,
219                                  "myprinter._privet._tcp.local");
220  testing::Mock::VerifyAndClear(&mock_delegate_);
221
222  EXPECT_CALL(delegate_, DeviceChanged(true,
223                                       "myprinter._privet._tcp.local",
224                                       _))
225              .WillOnce(SaveArg<2>(&outgoing_description));
226
227  service_resolver->callback().Run(ServiceResolver::STATUS_SUCCESS,
228                                   service_description_);
229
230  EXPECT_EQ(service_description_.address.host(),
231            outgoing_description.address.host());
232  EXPECT_EQ(service_description_.address.port(),
233            outgoing_description.address.port());
234  EXPECT_EQ(service_description_.ip_address, outgoing_description.ip_address);
235  EXPECT_EQ(service_description_.last_seen, outgoing_description.last_seen);
236  EXPECT_EQ("My Printer", outgoing_description.name);
237  EXPECT_EQ("This is my Printer", outgoing_description.description);
238  EXPECT_EQ("", outgoing_description.id);
239  EXPECT_EQ(DeviceDescription::ONLINE, outgoing_description.connection_state);
240
241  EXPECT_CALL(delegate_, DeviceRemoved("myprinter._privet._tcp.local"));
242
243  service_watcher->callback().Run(ServiceWatcher::UPDATE_REMOVED,
244                                  "myprinter._privet._tcp.local");
245}
246
247TEST_F(PrivetDeviceListerTest, MultipleUpdatesPostResolve) {
248  MockServiceWatcher* service_watcher;
249  MockServiceResolver* service_resolver;
250
251  EXPECT_CALL(mock_delegate_,
252              ServiceWatcherStarted("_privet._tcp.local", _))
253      .WillOnce(SaveArg<1>(&service_watcher));
254  PrivetDeviceListerImpl privet_lister(&mock_client_, &delegate_);
255  privet_lister.Start();
256  testing::Mock::VerifyAndClear(&mock_delegate_);
257
258  EXPECT_CALL(mock_delegate_,
259              ServiceResolverStarted("myprinter._privet._tcp.local", _))
260      .WillOnce(SaveArg<1>(&service_resolver));
261
262  service_watcher->callback().Run(ServiceWatcher::UPDATE_CHANGED,
263                                  "myprinter._privet._tcp.local");
264  testing::Mock::VerifyAndClear(&mock_delegate_);
265
266  EXPECT_CALL(delegate_, DeviceChanged(false,
267                                       "myprinter._privet._tcp.local",
268                                       _));
269  service_resolver->callback().Run(ServiceResolver::STATUS_SUCCESS,
270                                   service_description_);
271
272  EXPECT_CALL(mock_delegate_,
273              ServiceResolverStarted("myprinter._privet._tcp.local", _));
274  service_watcher->callback().Run(ServiceWatcher::UPDATE_CHANGED,
275                                  "myprinter._privet._tcp.local");
276  testing::Mock::VerifyAndClear(&mock_delegate_);
277}
278
279// Check that the device lister does not create a still-working resolver
280TEST_F(PrivetDeviceListerTest, MultipleUpdatesPreResolve) {
281  MockServiceWatcher* service_watcher;
282
283  EXPECT_CALL(mock_delegate_,
284              ServiceWatcherStarted("_privet._tcp.local", _))
285      .WillOnce(SaveArg<1>(&service_watcher));
286  PrivetDeviceListerImpl privet_lister(&mock_client_, &delegate_);
287  privet_lister.Start();
288  testing::Mock::VerifyAndClear(&mock_delegate_);
289
290  EXPECT_CALL(mock_delegate_,
291              ServiceResolverStarted("myprinter._privet._tcp.local", _))
292      .Times(1);
293  service_watcher->callback().Run(ServiceWatcher::UPDATE_CHANGED,
294                                  "myprinter._privet._tcp.local");
295  service_watcher->callback().Run(ServiceWatcher::UPDATE_CHANGED,
296                                  "myprinter._privet._tcp.local");
297}
298
299TEST_F(PrivetDeviceListerTest, DiscoverNewDevices) {
300  MockServiceWatcher* service_watcher;
301
302  EXPECT_CALL(mock_delegate_,
303              ServiceWatcherStarted("_privet._tcp.local", _))
304      .WillOnce(SaveArg<1>(&service_watcher));
305  PrivetDeviceListerImpl privet_lister(&mock_client_, &delegate_);
306  privet_lister.Start();
307  testing::Mock::VerifyAndClear(&mock_delegate_);
308
309  EXPECT_CALL(*service_watcher, DiscoverNewServices(false));
310  privet_lister.DiscoverNewDevices(false);
311}
312
313
314}  // namespace
315
316}  // namespace local_discovery
317