blob: a165b71874ffbb0586e5d8d1b824714ca62ee5e3 [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/bind.h"
#include "chrome/browser/local_discovery/privet_device_lister_impl.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using testing::SaveArg;
using testing::_;
namespace local_discovery {
namespace {
class MockServiceResolver;
class MockServiceWatcher;
class ServiceDiscoveryMockDelegate {
public:
virtual void ServiceWatcherStarted(const std::string& service_type,
MockServiceWatcher* watcher) = 0;
virtual void ServiceResolverStarted(const std::string& service_type,
MockServiceResolver* resolver) = 0;
};
class MockServiceWatcher : public ServiceWatcher {
public:
MockServiceWatcher(const std::string& service_type,
const ServiceWatcher::UpdatedCallback& callback,
ServiceDiscoveryMockDelegate* mock_delegate)
: started_(false), service_type_(service_type), callback_(callback),
mock_delegate_(mock_delegate) {
}
virtual ~MockServiceWatcher() {
}
virtual void Start() {
DCHECK(!started_);
started_ = true;
mock_delegate_->ServiceWatcherStarted(service_type_, this);
}
MOCK_METHOD1(DiscoverNewServices, void(bool force_update));
MOCK_METHOD1(SetActivelyRefreshServices, void(
bool actively_refresh_services));
virtual std::string GetServiceType() const {
return service_type_;
}
bool started() {
return started_;
}
ServiceWatcher::UpdatedCallback callback() {
return callback_;
}
private:
bool started_;
std::string service_type_;
ServiceWatcher::UpdatedCallback callback_;
ServiceDiscoveryMockDelegate* mock_delegate_;
};
class MockServiceResolver : public ServiceResolver {
public:
MockServiceResolver(const std::string& service_name,
const ServiceResolver::ResolveCompleteCallback& callback,
ServiceDiscoveryMockDelegate* mock_delegate)
: started_resolving_(false), service_name_(service_name),
callback_(callback), mock_delegate_(mock_delegate) {
}
~MockServiceResolver() override {}
void StartResolving() override {
started_resolving_ = true;
mock_delegate_->ServiceResolverStarted(service_name_, this);
}
bool IsResolving() const {
return started_resolving_;
}
std::string GetName() const override { return service_name_; }
const ServiceResolver::ResolveCompleteCallback& callback() {
return callback_; }
private:
bool started_resolving_;
std::string service_name_;
ServiceResolver::ResolveCompleteCallback callback_;
ServiceDiscoveryMockDelegate* mock_delegate_;
};
class MockServiceDiscoveryClient : public ServiceDiscoveryClient {
public:
explicit MockServiceDiscoveryClient(
ServiceDiscoveryMockDelegate* mock_delegate)
: mock_delegate_(mock_delegate) {
}
~MockServiceDiscoveryClient() override {}
// Create a service watcher object listening for DNS-SD service announcements
// on service type |service_type|.
scoped_ptr<ServiceWatcher> CreateServiceWatcher(
const std::string& service_type,
const ServiceWatcher::UpdatedCallback& callback) override {
return make_scoped_ptr(
new MockServiceWatcher(service_type, callback, mock_delegate_));
}
// Create a service resolver object for getting detailed service information
// for the service called |service_name|.
scoped_ptr<ServiceResolver> CreateServiceResolver(
const std::string& service_name,
const ServiceResolver::ResolveCompleteCallback& callback) override {
return make_scoped_ptr(
new MockServiceResolver(service_name, callback, mock_delegate_));
}
// Not used in this test.
scoped_ptr<LocalDomainResolver> CreateLocalDomainResolver(
const std::string& domain,
net::AddressFamily address_family,
const LocalDomainResolver::IPAddressCallback& callback) override {
NOTREACHED();
return scoped_ptr<LocalDomainResolver>();
}
private:
ServiceDiscoveryMockDelegate* mock_delegate_;
};
class MockServiceDiscoveryMockDelegate : public ServiceDiscoveryMockDelegate {
public:
MOCK_METHOD2(ServiceWatcherStarted, void(const std::string& service_type,
MockServiceWatcher* watcher));
MOCK_METHOD2(ServiceResolverStarted, void(const std::string& service_type,
MockServiceResolver* resolver));
};
class MockDeviceListerDelegate : public PrivetDeviceLister::Delegate {
public:
MockDeviceListerDelegate() {
}
virtual ~MockDeviceListerDelegate() {
}
MOCK_METHOD3(DeviceChanged, void(bool added,
const std::string& name,
const DeviceDescription& description));
MOCK_METHOD1(DeviceRemoved, void(const std::string& name));
MOCK_METHOD0(DeviceCacheFlushed, void());
};
class PrivetDeviceListerTest : public testing::Test {
public:
PrivetDeviceListerTest() : mock_client_(&mock_delegate_) {
}
~PrivetDeviceListerTest() override {
}
void SetUp() override {
example_attrs_.push_back("tXtvers=1");
example_attrs_.push_back("ty=My Printer");
example_attrs_.push_back("nOte=This is my Printer");
example_attrs_.push_back("CS=ONlInE");
example_attrs_.push_back("id=");
service_description_.service_name = "myprinter._privet._tcp.local";
service_description_.address = net::HostPortPair("myprinter.local", 6006);
service_description_.metadata = example_attrs_;
service_description_.last_seen = base::Time() +
base::TimeDelta::FromSeconds(5);
service_description_.ip_address.push_back(1);
service_description_.ip_address.push_back(2);
service_description_.ip_address.push_back(3);
service_description_.ip_address.push_back(4);
}
protected:
testing::StrictMock<MockServiceDiscoveryMockDelegate> mock_delegate_;
MockServiceDiscoveryClient mock_client_;
MockDeviceListerDelegate delegate_;
std::vector<std::string> example_attrs_;
ServiceDescription service_description_;
};
TEST_F(PrivetDeviceListerTest, SimpleUpdateTest) {
DeviceDescription outgoing_description;
MockServiceWatcher* service_watcher;
MockServiceResolver* service_resolver;
EXPECT_CALL(mock_delegate_,
ServiceWatcherStarted("_privet._tcp.local", _))
.WillOnce(SaveArg<1>(&service_watcher));
PrivetDeviceListerImpl privet_lister(&mock_client_, &delegate_);
privet_lister.Start();
testing::Mock::VerifyAndClear(&mock_delegate_);
EXPECT_CALL(mock_delegate_,
ServiceResolverStarted("myprinter._privet._tcp.local", _))
.WillOnce(SaveArg<1>(&service_resolver));
service_watcher->callback().Run(ServiceWatcher::UPDATE_ADDED,
"myprinter._privet._tcp.local");
testing::Mock::VerifyAndClear(&mock_delegate_);
EXPECT_CALL(delegate_, DeviceChanged(true,
"myprinter._privet._tcp.local",
_))
.WillOnce(SaveArg<2>(&outgoing_description));
service_resolver->callback().Run(ServiceResolver::STATUS_SUCCESS,
service_description_);
EXPECT_EQ(service_description_.address.host(),
outgoing_description.address.host());
EXPECT_EQ(service_description_.address.port(),
outgoing_description.address.port());
EXPECT_EQ("My Printer", outgoing_description.name);
EXPECT_EQ("This is my Printer", outgoing_description.description);
EXPECT_EQ("", outgoing_description.id);
EXPECT_CALL(delegate_, DeviceRemoved("myprinter._privet._tcp.local"));
service_watcher->callback().Run(ServiceWatcher::UPDATE_REMOVED,
"myprinter._privet._tcp.local");
}
TEST_F(PrivetDeviceListerTest, MultipleUpdatesPostResolve) {
MockServiceWatcher* service_watcher;
MockServiceResolver* service_resolver;
EXPECT_CALL(mock_delegate_,
ServiceWatcherStarted("_privet._tcp.local", _))
.WillOnce(SaveArg<1>(&service_watcher));
PrivetDeviceListerImpl privet_lister(&mock_client_, &delegate_);
privet_lister.Start();
testing::Mock::VerifyAndClear(&mock_delegate_);
EXPECT_CALL(mock_delegate_,
ServiceResolverStarted("myprinter._privet._tcp.local", _))
.WillOnce(SaveArg<1>(&service_resolver));
service_watcher->callback().Run(ServiceWatcher::UPDATE_CHANGED,
"myprinter._privet._tcp.local");
testing::Mock::VerifyAndClear(&mock_delegate_);
EXPECT_CALL(delegate_, DeviceChanged(false,
"myprinter._privet._tcp.local",
_));
service_resolver->callback().Run(ServiceResolver::STATUS_SUCCESS,
service_description_);
EXPECT_CALL(mock_delegate_,
ServiceResolverStarted("myprinter._privet._tcp.local", _));
service_watcher->callback().Run(ServiceWatcher::UPDATE_CHANGED,
"myprinter._privet._tcp.local");
testing::Mock::VerifyAndClear(&mock_delegate_);
}
// Check that the device lister does not create a still-working resolver
TEST_F(PrivetDeviceListerTest, MultipleUpdatesPreResolve) {
MockServiceWatcher* service_watcher;
EXPECT_CALL(mock_delegate_,
ServiceWatcherStarted("_privet._tcp.local", _))
.WillOnce(SaveArg<1>(&service_watcher));
PrivetDeviceListerImpl privet_lister(&mock_client_, &delegate_);
privet_lister.Start();
testing::Mock::VerifyAndClear(&mock_delegate_);
EXPECT_CALL(mock_delegate_,
ServiceResolverStarted("myprinter._privet._tcp.local", _))
.Times(1);
service_watcher->callback().Run(ServiceWatcher::UPDATE_CHANGED,
"myprinter._privet._tcp.local");
service_watcher->callback().Run(ServiceWatcher::UPDATE_CHANGED,
"myprinter._privet._tcp.local");
}
TEST_F(PrivetDeviceListerTest, DiscoverNewDevices) {
MockServiceWatcher* service_watcher;
EXPECT_CALL(mock_delegate_,
ServiceWatcherStarted("_privet._tcp.local", _))
.WillOnce(SaveArg<1>(&service_watcher));
PrivetDeviceListerImpl privet_lister(&mock_client_, &delegate_);
privet_lister.Start();
testing::Mock::VerifyAndClear(&mock_delegate_);
EXPECT_CALL(*service_watcher, DiscoverNewServices(false));
privet_lister.DiscoverNewDevices(false);
}
} // namespace
} // namespace local_discovery