Commit 21239546 authored by Jesse Schettler's avatar Jesse Schettler Committed by Commit Bot

Move FakeServiceDiscoveryDeviceLister

Move this class to its own .cc/.h files so it can be used in unit tests
for other ServiceDiscoveryDeviceLister::Delegates.

Also, move MakeServiceDescription() out of
FakeServiceDiscoveryDeviceLister since it is specific to printers. This
allows other tests to create their own ServiceDescriptions and pass them
into Announce().

Bug: None
Change-Id: I01f6e65c75b3a38819c74fac18f8034a8b62cac6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2300833Reviewed-by: default avatarLei Zhang <thestig@chromium.org>
Commit-Queue: Jesse Schettler <jschettler@chromium.org>
Cr-Commit-Position: refs/heads/master@{#790578}
parent cea5edf5
...@@ -6240,6 +6240,8 @@ static_library("test_support") { ...@@ -6240,6 +6240,8 @@ static_library("test_support") {
if (enable_service_discovery) { if (enable_service_discovery) {
sources += [ sources += [
"local_discovery/fake_service_discovery_device_lister.cc",
"local_discovery/fake_service_discovery_device_lister.h",
"local_discovery/test_service_discovery_client.cc", "local_discovery/test_service_discovery_client.cc",
"local_discovery/test_service_discovery_client.h", "local_discovery/test_service_discovery_client.h",
] ]
......
...@@ -6,24 +6,26 @@ ...@@ -6,24 +6,26 @@
#include <algorithm> #include <algorithm>
#include <functional> #include <functional>
#include <map>
#include <memory>
#include <random> #include <random>
#include <set>
#include <string> #include <string>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "base/bind.h" #include "base/bind.h"
#include "base/stl_util.h"
#include "base/strings/strcat.h" #include "base/strings/strcat.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "base/test/task_environment.h" #include "base/test/task_environment.h"
#include "base/time/time.h" #include "chrome/browser/local_discovery/fake_service_discovery_device_lister.h"
#include "chrome/browser/local_discovery/service_discovery_device_lister.h" #include "chrome/browser/local_discovery/service_discovery_device_lister.h"
#include "net/base/ip_address.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
namespace chromeos { namespace chromeos {
namespace { namespace {
using local_discovery::FakeServiceDiscoveryDeviceLister;
using local_discovery::ServiceDescription; using local_discovery::ServiceDescription;
using local_discovery::ServiceDiscoveryDeviceLister; using local_discovery::ServiceDiscoveryDeviceLister;
...@@ -64,11 +66,10 @@ enum class ServiceType { ...@@ -64,11 +66,10 @@ enum class ServiceType {
kSocket, // Socket kSocket, // Socket
}; };
// This corresponds to FakeServiceDeviceLister::MakeServiceDescription. Given // This corresponds to MakeServiceDescription() below. Given the same name (and
// the same name (and the correct service type) this generates the // the correct service type), this generates the DetectedPrinter record we
// DetectedPrinter record we expect from ZeroconfPrinterDetector when // expect from ZeroconfPrinterDetector when it gets that ServiceDescription.
// it gets that ServiceDescription. This needs to be kept in sync // This needs to be kept in sync with MakeServiceDescription().
// with FakeServiceDeviceLister::MakeServiceDescription.
PrinterDetector::DetectedPrinter MakeExpectedPrinter(const std::string& name, PrinterDetector::DetectedPrinter MakeExpectedPrinter(const std::string& name,
ServiceType service_type) { ServiceType service_type) {
PrinterDetector::DetectedPrinter detected; PrinterDetector::DetectedPrinter detected;
...@@ -117,196 +118,27 @@ PrinterDetector::DetectedPrinter MakeExpectedPrinter(const std::string& name, ...@@ -117,196 +118,27 @@ PrinterDetector::DetectedPrinter MakeExpectedPrinter(const std::string& name,
return detected; return detected;
} }
// This is a thin wrapper around Delegate that defers callbacks until // Creates a deterministic ServiceDescription based on the service name and
// the actual delegate is initialized, then calls all deferred callbacks. Once // type. See the note on MakeExpectedPrinter() above. This must be kept in sync
// the actual delegate is initialized, this just becomes a simple passthrough. // with MakeExpectedPrinter().
class DeferringDelegate : public ServiceDiscoveryDeviceLister::Delegate { ServiceDescription MakeServiceDescription(const std::string& name,
public: const std::string& service_type) {
void OnDeviceChanged(const std::string& service_type, ServiceDescription sd;
bool added, sd.service_name = base::StrCat({name, ".", service_type});
const ServiceDescription& service_description) override { sd.metadata.push_back(base::StrCat({"ty=", name, "_ty"}));
if (actual_) { sd.metadata.push_back(base::StrCat({"product=(", name, "_product)"}));
actual_->OnDeviceChanged(service_type, added, service_description); if (GetUsbFor(name)) {
} else { sd.metadata.push_back(base::StrCat({"usb_MFG=", name, "_usb_MFG"}));
deferred_callbacks_.push_back(base::BindOnce( sd.metadata.push_back(base::StrCat({"usb_MDL=", name, "_usb_MDL"}));
&DeferringDelegate::OnDeviceChanged, base::Unretained(this),
service_type, added, service_description));
}
}
// Not guaranteed to be called after OnDeviceChanged.
void OnDeviceRemoved(const std::string& service_type,
const std::string& service_name) override {
if (actual_) {
actual_->OnDeviceRemoved(service_type, service_name);
} else {
deferred_callbacks_.push_back(
base::BindOnce(&DeferringDelegate::OnDeviceRemoved,
base::Unretained(this), service_type, service_name));
}
}
void OnDeviceCacheFlushed(const std::string& service_type) override {
if (actual_) {
actual_->OnDeviceCacheFlushed(service_type);
} else {
deferred_callbacks_.push_back(
base::BindOnce(&DeferringDelegate::OnDeviceCacheFlushed,
base::Unretained(this), service_type));
}
}
void SetActual(ServiceDiscoveryDeviceLister::Delegate* actual) {
CHECK(!actual_);
actual_ = actual;
for (auto& cb : deferred_callbacks_) {
std::move(cb).Run();
}
deferred_callbacks_.clear();
}
private:
std::vector<base::OnceCallback<void()>> deferred_callbacks_;
ServiceDiscoveryDeviceLister::Delegate* actual_ = nullptr;
};
// A fake ServiceDiscoveryDeviceLister. This provides an implementation
// of ServiceDiscoveryDeviceLister that tests can use to trigger addition
// and removal of devices.
//
// There's some hackery here to handle constructor order constraints. There's a
// circular dependency in that ZeroconfPrinterDetector (which is a device lister
// delegate) needs its device lister set to be supplied at construction time,
// and each device lister needs to know about its delegate for callbacks. Thus
// we use DeferringDelegate to queue callbacks triggered before we have the
// delegate reference in this class, and invoke those queued callbacks when the
// Delegate is set.
class FakeServiceDiscoveryDeviceLister : public ServiceDiscoveryDeviceLister {
public:
FakeServiceDiscoveryDeviceLister(base::TaskRunner* task_runner,
const std::string& service_type)
: task_runner_(task_runner), service_type_(service_type) {}
~FakeServiceDiscoveryDeviceLister() override = default;
// The only thing we care about with Start() is that it's called before
// DiscoverNewDevices.
void Start() override {
if (start_called_) {
ADD_FAILURE() << "Start called multiple times";
}
start_called_ = true;
}
// When DiscoverNewDevices is called, all updates we've queued up until this
// point are invoked.
void DiscoverNewDevices() override {
if (!start_called_) {
ADD_FAILURE() << "DiscoverNewDevices called before Start";
}
discovery_started_ = true;
for (const auto& update : queued_updates_) {
SendUpdate(update);
}
queued_updates_.clear();
}
const std::string& service_type() const override { return service_type_; }
void SetDelegate(ServiceDiscoveryDeviceLister::Delegate* delegate) {
deferring_delegate_.SetActual(delegate);
}
// Announce a new service or update it if we've seen it before and already
// announced it. If discovery hasn't started yet, queue the description
// to be sent when discovery is started.
void Announce(const std::string& name) {
ServiceDescription description = MakeServiceDescription(name);
if (!discovery_started_) {
queued_updates_.push_back(description);
} else {
SendUpdate(description);
}
}
void Remove(const std::string& name) {
std::string service_name = base::StrCat({name, ".", service_type_});
announced_services_.erase(service_name);
CHECK(task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&ServiceDiscoveryDeviceLister::Delegate::OnDeviceRemoved,
base::Unretained(&deferring_delegate_), service_type_,
service_name)));
}
// Simulate an event that clears downstream caches and the lister.
void Clear() {
announced_services_.clear();
discovery_started_ = false;
CHECK(task_runner_->PostTask(
FROM_HERE,
base::BindOnce(
&ServiceDiscoveryDeviceLister::Delegate::OnDeviceCacheFlushed,
base::Unretained(&deferring_delegate_), service_type_)));
}
// Create a deterministic ServiceDescription based on the name and this
// lister's service_type. See the note on MakeExpectedPrinter, above. This
// is a member function instead of a free function because the service_type_
// impacts some of the fields. This must be kept in sync with
// MakeExpectedPrinter.
ServiceDescription MakeServiceDescription(const std::string& name) {
ServiceDescription sd;
sd.service_name = base::StrCat({name, ".", service_type_});
sd.metadata.push_back(base::StrCat({"ty=", name, "_ty"}));
sd.metadata.push_back(base::StrCat({"product=(", name, "_product)"}));
if (GetUsbFor(name)) {
sd.metadata.push_back(base::StrCat({"usb_MFG=", name, "_usb_MFG"}));
sd.metadata.push_back(base::StrCat({"usb_MDL=", name, "_usb_MDL"}));
}
sd.metadata.push_back(base::StrCat({"rp=", name, "_rp"}));
sd.metadata.push_back(base::StrCat({"note=", name, "_note"}));
sd.metadata.push_back(base::StrCat({"UUID=", name, "_UUID"}));
sd.address.set_host(base::StrCat({name, ".local"}));
sd.ip_address = GetIPAddressFor(name);
sd.address.set_port(GetPortFor(name));
return sd;
}
bool discovery_started() { return discovery_started_; }
private:
void SendUpdate(const ServiceDescription& description) {
bool is_new;
if (!base::Contains(announced_services_, description.service_name)) {
is_new = true;
announced_services_.insert(description.service_name);
} else {
is_new = false;
}
CHECK(task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&ServiceDiscoveryDeviceLister::Delegate::OnDeviceChanged,
base::Unretained(&deferring_delegate_), service_type_,
is_new, description)));
} }
base::TaskRunner* task_runner_; sd.metadata.push_back(base::StrCat({"rp=", name, "_rp"}));
sd.metadata.push_back(base::StrCat({"note=", name, "_note"}));
// Services which have previously posted an update, and therefore are no sd.metadata.push_back(base::StrCat({"UUID=", name, "_UUID"}));
// longer 'new' for the purposes of the OnDeviceChanged callback. sd.address.set_host(base::StrCat({name, ".local"}));
std::set<std::string> announced_services_; sd.ip_address = GetIPAddressFor(name);
sd.address.set_port(GetPortFor(name));
// Updates added to the class before discovery started. return sd;
std::vector<ServiceDescription> queued_updates_; }
// Has Start() been called?
bool start_called_ = false;
// Has DiscoverNewDevices been called?
bool discovery_started_ = false;
std::string service_type_;
DeferringDelegate deferring_delegate_;
};
class ZeroconfPrinterDetectorTest : public testing::Test { class ZeroconfPrinterDetectorTest : public testing::Test {
public: public:
...@@ -463,35 +295,40 @@ class ZeroconfPrinterDetectorTest : public testing::Test { ...@@ -463,35 +295,40 @@ class ZeroconfPrinterDetectorTest : public testing::Test {
// Very basic stuff, one printer of each protocol we support. // Very basic stuff, one printer of each protocol we support.
TEST_F(ZeroconfPrinterDetectorTest, SingleIppPrinter) { TEST_F(ZeroconfPrinterDetectorTest, SingleIppPrinter) {
ipp_lister_->Announce("Printer1"); ipp_lister_->Announce(MakeServiceDescription(
"Printer1", ZeroconfPrinterDetector::kIppServiceName));
CreateDetector(); CreateDetector();
CompleteTasks(); CompleteTasks();
ExpectPrintersAre({MakeExpectedPrinter("Printer1", ServiceType::kIpp)}); ExpectPrintersAre({MakeExpectedPrinter("Printer1", ServiceType::kIpp)});
} }
TEST_F(ZeroconfPrinterDetectorTest, SingleIppsPrinter) { TEST_F(ZeroconfPrinterDetectorTest, SingleIppsPrinter) {
ipps_lister_->Announce("Printer2"); ipps_lister_->Announce(MakeServiceDescription(
"Printer2", ZeroconfPrinterDetector::kIppsServiceName));
CreateDetector(); CreateDetector();
CompleteTasks(); CompleteTasks();
ExpectPrintersAre({MakeExpectedPrinter("Printer2", ServiceType::kIpps)}); ExpectPrintersAre({MakeExpectedPrinter("Printer2", ServiceType::kIpps)});
} }
TEST_F(ZeroconfPrinterDetectorTest, SingleIppEverywherePrinter) { TEST_F(ZeroconfPrinterDetectorTest, SingleIppEverywherePrinter) {
ippe_lister_->Announce("Printer3"); ippe_lister_->Announce(MakeServiceDescription(
"Printer3", ZeroconfPrinterDetector::kIppEverywhereServiceName));
CreateDetector(); CreateDetector();
CompleteTasks(); CompleteTasks();
ExpectPrintersAre({MakeExpectedPrinter("Printer3", ServiceType::kIppE)}); ExpectPrintersAre({MakeExpectedPrinter("Printer3", ServiceType::kIppE)});
} }
TEST_F(ZeroconfPrinterDetectorTest, SingleIppsEverywherePrinter) { TEST_F(ZeroconfPrinterDetectorTest, SingleIppsEverywherePrinter) {
ippse_lister_->Announce("Printer4"); ippse_lister_->Announce(MakeServiceDescription(
"Printer4", ZeroconfPrinterDetector::kIppsEverywhereServiceName));
CreateDetector(); CreateDetector();
CompleteTasks(); CompleteTasks();
ExpectPrintersAre({MakeExpectedPrinter("Printer4", ServiceType::kIppsE)}); ExpectPrintersAre({MakeExpectedPrinter("Printer4", ServiceType::kIppsE)});
} }
TEST_F(ZeroconfPrinterDetectorTest, SingleSocketPrinter) { TEST_F(ZeroconfPrinterDetectorTest, SingleSocketPrinter) {
socket_lister_->Announce("Printer5"); socket_lister_->Announce(MakeServiceDescription(
"Printer5", ZeroconfPrinterDetector::kSocketServiceName));
CreateDetector(); CreateDetector();
CompleteTasks(); CompleteTasks();
ExpectPrintersAre({MakeExpectedPrinter("Printer5", ServiceType::kSocket)}); ExpectPrintersAre({MakeExpectedPrinter("Printer5", ServiceType::kSocket)});
...@@ -501,7 +338,8 @@ TEST_F(ZeroconfPrinterDetectorTest, SingleSocketPrinter) { ...@@ -501,7 +338,8 @@ TEST_F(ZeroconfPrinterDetectorTest, SingleSocketPrinter) {
TEST_F(ZeroconfPrinterDetectorTest, AnnounceAfterDetectorCreation) { TEST_F(ZeroconfPrinterDetectorTest, AnnounceAfterDetectorCreation) {
CreateDetector(); CreateDetector();
CompleteTasks(); CompleteTasks();
ippse_lister_->Announce("Printer4"); ippse_lister_->Announce(MakeServiceDescription(
"Printer4", ZeroconfPrinterDetector::kIppsEverywhereServiceName));
CompleteTasks(); CompleteTasks();
ExpectPrintersAre({MakeExpectedPrinter("Printer4", ServiceType::kIppsE)}); ExpectPrintersAre({MakeExpectedPrinter("Printer4", ServiceType::kIppsE)});
} }
...@@ -509,7 +347,8 @@ TEST_F(ZeroconfPrinterDetectorTest, AnnounceAfterDetectorCreation) { ...@@ -509,7 +347,8 @@ TEST_F(ZeroconfPrinterDetectorTest, AnnounceAfterDetectorCreation) {
// Test that we use the same printer ID regardless of which service type it // Test that we use the same printer ID regardless of which service type it
// comes to us from. // comes to us from.
TEST_F(ZeroconfPrinterDetectorTest, StableIds) { TEST_F(ZeroconfPrinterDetectorTest, StableIds) {
ipp_lister_->Announce("Printer1"); ipp_lister_->Announce(MakeServiceDescription(
"Printer1", ZeroconfPrinterDetector::kIppServiceName));
CreateDetector(); CreateDetector();
CompleteTasks(); CompleteTasks();
ASSERT_FALSE(printers_found_callbacks_.empty()); ASSERT_FALSE(printers_found_callbacks_.empty());
...@@ -522,7 +361,8 @@ TEST_F(ZeroconfPrinterDetectorTest, StableIds) { ...@@ -522,7 +361,8 @@ TEST_F(ZeroconfPrinterDetectorTest, StableIds) {
ipp_lister_->Remove("Printer1"); ipp_lister_->Remove("Printer1");
CompleteTasks(); CompleteTasks();
ASSERT_TRUE(printers_found_callbacks_.back().empty()); ASSERT_TRUE(printers_found_callbacks_.back().empty());
ipps_lister_->Announce("Printer1"); ipps_lister_->Announce(MakeServiceDescription(
"Printer1", ZeroconfPrinterDetector::kIppsServiceName));
CompleteTasks(); CompleteTasks();
ASSERT_EQ(1U, printers_found_callbacks_.back().size()); ASSERT_EQ(1U, printers_found_callbacks_.back().size());
// Id should be the same. // Id should be the same.
...@@ -532,7 +372,8 @@ TEST_F(ZeroconfPrinterDetectorTest, StableIds) { ...@@ -532,7 +372,8 @@ TEST_F(ZeroconfPrinterDetectorTest, StableIds) {
ipps_lister_->Remove("Printer1"); ipps_lister_->Remove("Printer1");
CompleteTasks(); CompleteTasks();
ASSERT_TRUE(printers_found_callbacks_.back().empty()); ASSERT_TRUE(printers_found_callbacks_.back().empty());
ippe_lister_->Announce("Printer1"); ippe_lister_->Announce(MakeServiceDescription(
"Printer1", ZeroconfPrinterDetector::kIppEverywhereServiceName));
CompleteTasks(); CompleteTasks();
ASSERT_EQ(1U, printers_found_callbacks_.back().size()); ASSERT_EQ(1U, printers_found_callbacks_.back().size());
// Id should be the same. // Id should be the same.
...@@ -543,7 +384,8 @@ TEST_F(ZeroconfPrinterDetectorTest, StableIds) { ...@@ -543,7 +384,8 @@ TEST_F(ZeroconfPrinterDetectorTest, StableIds) {
ippe_lister_->Remove("Printer1"); ippe_lister_->Remove("Printer1");
CompleteTasks(); CompleteTasks();
ASSERT_TRUE(printers_found_callbacks_.back().empty()); ASSERT_TRUE(printers_found_callbacks_.back().empty());
ippse_lister_->Announce("Printer1"); ippse_lister_->Announce(MakeServiceDescription(
"Printer1", ZeroconfPrinterDetector::kIppsEverywhereServiceName));
CompleteTasks(); CompleteTasks();
ASSERT_EQ(1U, printers_found_callbacks_.back().size()); ASSERT_EQ(1U, printers_found_callbacks_.back().size());
// Id should be the same. // Id should be the same.
...@@ -553,7 +395,8 @@ TEST_F(ZeroconfPrinterDetectorTest, StableIds) { ...@@ -553,7 +395,8 @@ TEST_F(ZeroconfPrinterDetectorTest, StableIds) {
ippse_lister_->Remove("Printer1"); ippse_lister_->Remove("Printer1");
CompleteTasks(); CompleteTasks();
ASSERT_TRUE(printers_found_callbacks_.back().empty()); ASSERT_TRUE(printers_found_callbacks_.back().empty());
socket_lister_->Announce("Printer1"); socket_lister_->Announce(MakeServiceDescription(
"Printer1", ZeroconfPrinterDetector::kSocketServiceName));
CompleteTasks(); CompleteTasks();
ASSERT_EQ(1U, printers_found_callbacks_.back().size()); ASSERT_EQ(1U, printers_found_callbacks_.back().size());
// Id should be the same. // Id should be the same.
...@@ -562,11 +405,16 @@ TEST_F(ZeroconfPrinterDetectorTest, StableIds) { ...@@ -562,11 +405,16 @@ TEST_F(ZeroconfPrinterDetectorTest, StableIds) {
// Test a basic removal. // Test a basic removal.
TEST_F(ZeroconfPrinterDetectorTest, Removal) { TEST_F(ZeroconfPrinterDetectorTest, Removal) {
ipp_lister_->Announce("Printer5"); ipp_lister_->Announce(MakeServiceDescription(
ipp_lister_->Announce("Printer6"); "Printer5", ZeroconfPrinterDetector::kIppServiceName));
ipp_lister_->Announce("Printer7"); ipp_lister_->Announce(MakeServiceDescription(
ipp_lister_->Announce("Printer8"); "Printer6", ZeroconfPrinterDetector::kIppServiceName));
ipp_lister_->Announce("Printer9"); ipp_lister_->Announce(MakeServiceDescription(
"Printer7", ZeroconfPrinterDetector::kIppServiceName));
ipp_lister_->Announce(MakeServiceDescription(
"Printer8", ZeroconfPrinterDetector::kIppServiceName));
ipp_lister_->Announce(MakeServiceDescription(
"Printer9", ZeroconfPrinterDetector::kIppServiceName));
CreateDetector(); CreateDetector();
CompleteTasks(); CompleteTasks();
ExpectPrintersAre({MakeExpectedPrinter("Printer5", ServiceType::kIpp), ExpectPrintersAre({MakeExpectedPrinter("Printer5", ServiceType::kIpp),
...@@ -587,11 +435,16 @@ TEST_F(ZeroconfPrinterDetectorTest, Removal) { ...@@ -587,11 +435,16 @@ TEST_F(ZeroconfPrinterDetectorTest, Removal) {
// are IPPS-E, IPP-E, IPPS, IPP. // are IPPS-E, IPP-E, IPPS, IPP.
TEST_F(ZeroconfPrinterDetectorTest, ServiceTypePriorities) { TEST_F(ZeroconfPrinterDetectorTest, ServiceTypePriorities) {
// Advertise on all 4 services. // Advertise on all 4 services.
ipp_lister_->Announce("Printer5"); ipp_lister_->Announce(MakeServiceDescription(
ipps_lister_->Announce("Printer5"); "Printer5", ZeroconfPrinterDetector::kIppServiceName));
ippe_lister_->Announce("Printer5"); ipps_lister_->Announce(MakeServiceDescription(
ippse_lister_->Announce("Printer5"); "Printer5", ZeroconfPrinterDetector::kIppsServiceName));
socket_lister_->Announce("Printer5"); ippe_lister_->Announce(MakeServiceDescription(
"Printer5", ZeroconfPrinterDetector::kIppEverywhereServiceName));
ippse_lister_->Announce(MakeServiceDescription(
"Printer5", ZeroconfPrinterDetector::kIppsEverywhereServiceName));
socket_lister_->Announce(MakeServiceDescription(
"Printer5", ZeroconfPrinterDetector::kSocketServiceName));
CreateDetector(); CreateDetector();
CompleteTasks(); CompleteTasks();
// IPPS-E is highest priority. // IPPS-E is highest priority.
...@@ -624,16 +477,26 @@ TEST_F(ZeroconfPrinterDetectorTest, ServiceTypePriorities) { ...@@ -624,16 +477,26 @@ TEST_F(ZeroconfPrinterDetectorTest, ServiceTypePriorities) {
// Test that cache flushes appropriately remove entries. // Test that cache flushes appropriately remove entries.
TEST_F(ZeroconfPrinterDetectorTest, CacheFlushes) { TEST_F(ZeroconfPrinterDetectorTest, CacheFlushes) {
ipp_lister_->Announce("Printer6"); ipp_lister_->Announce(MakeServiceDescription(
ipp_lister_->Announce("Printer7"); "Printer6", ZeroconfPrinterDetector::kIppServiceName));
ipps_lister_->Announce("Printer7"); ipp_lister_->Announce(MakeServiceDescription(
ipps_lister_->Announce("Printer8"); "Printer7", ZeroconfPrinterDetector::kIppServiceName));
ippe_lister_->Announce("Printer8"); ipps_lister_->Announce(MakeServiceDescription(
ippe_lister_->Announce("Printer9"); "Printer7", ZeroconfPrinterDetector::kIppsServiceName));
ippse_lister_->Announce("Printer9"); ipps_lister_->Announce(MakeServiceDescription(
ippse_lister_->Announce("Printer10"); "Printer8", ZeroconfPrinterDetector::kIppsServiceName));
socket_lister_->Announce("Printer10"); ippe_lister_->Announce(MakeServiceDescription(
socket_lister_->Announce("Printer11"); "Printer8", ZeroconfPrinterDetector::kIppEverywhereServiceName));
ippe_lister_->Announce(MakeServiceDescription(
"Printer9", ZeroconfPrinterDetector::kIppEverywhereServiceName));
ippse_lister_->Announce(MakeServiceDescription(
"Printer9", ZeroconfPrinterDetector::kIppsEverywhereServiceName));
ippse_lister_->Announce(MakeServiceDescription(
"Printer10", ZeroconfPrinterDetector::kIppsEverywhereServiceName));
socket_lister_->Announce(MakeServiceDescription(
"Printer10", ZeroconfPrinterDetector::kSocketServiceName));
socket_lister_->Announce(MakeServiceDescription(
"Printer11", ZeroconfPrinterDetector::kSocketServiceName));
CreateDetector(); CreateDetector();
CompleteTasks(); CompleteTasks();
...@@ -654,7 +517,8 @@ TEST_F(ZeroconfPrinterDetectorTest, CacheFlushes) { ...@@ -654,7 +517,8 @@ TEST_F(ZeroconfPrinterDetectorTest, CacheFlushes) {
EXPECT_TRUE(ipps_lister_->discovery_started()); EXPECT_TRUE(ipps_lister_->discovery_started());
// Just for kicks, announce something new at this point. // Just for kicks, announce something new at this point.
ipps_lister_->Announce("Printer12"); ipps_lister_->Announce(MakeServiceDescription(
"Printer12", ZeroconfPrinterDetector::kIppsServiceName));
CompleteTasks(); CompleteTasks();
ExpectPrintersAre({MakeExpectedPrinter("Printer12", ServiceType::kIpps)}); ExpectPrintersAre({MakeExpectedPrinter("Printer12", ServiceType::kIpps)});
...@@ -669,12 +533,18 @@ TEST_F(ZeroconfPrinterDetectorTest, CacheFlushes) { ...@@ -669,12 +533,18 @@ TEST_F(ZeroconfPrinterDetectorTest, CacheFlushes) {
// Test some general traffic with a mix of everything we expect to handle. // Test some general traffic with a mix of everything we expect to handle.
TEST_F(ZeroconfPrinterDetectorTest, GeneralMixedTraffic) { TEST_F(ZeroconfPrinterDetectorTest, GeneralMixedTraffic) {
ipp_lister_->Announce("Printer12"); ipp_lister_->Announce(MakeServiceDescription(
ipps_lister_->Announce("Printer12"); "Printer12", ZeroconfPrinterDetector::kIppServiceName));
ipps_lister_->Announce("Printer13"); ipps_lister_->Announce(MakeServiceDescription(
ippse_lister_->Announce("Printer14"); "Printer12", ZeroconfPrinterDetector::kIppsServiceName));
ipps_lister_->Announce("Printer15"); ipps_lister_->Announce(MakeServiceDescription(
socket_lister_->Announce("Printer16"); "Printer13", ZeroconfPrinterDetector::kIppsServiceName));
ippse_lister_->Announce(MakeServiceDescription(
"Printer14", ZeroconfPrinterDetector::kIppsEverywhereServiceName));
ipps_lister_->Announce(MakeServiceDescription(
"Printer15", ZeroconfPrinterDetector::kIppsServiceName));
socket_lister_->Announce(MakeServiceDescription(
"Printer16", ZeroconfPrinterDetector::kSocketServiceName));
CreateDetector(); CreateDetector();
CompleteTasks(); CompleteTasks();
...@@ -684,8 +554,10 @@ TEST_F(ZeroconfPrinterDetectorTest, GeneralMixedTraffic) { ...@@ -684,8 +554,10 @@ TEST_F(ZeroconfPrinterDetectorTest, GeneralMixedTraffic) {
MakeExpectedPrinter("Printer15", ServiceType::kIpps), MakeExpectedPrinter("Printer15", ServiceType::kIpps),
MakeExpectedPrinter("Printer16", ServiceType::kSocket)}); MakeExpectedPrinter("Printer16", ServiceType::kSocket)});
ippe_lister_->Announce("Printer13"); ippe_lister_->Announce(MakeServiceDescription(
ipp_lister_->Announce("Printer17"); "Printer13", ZeroconfPrinterDetector::kIppEverywhereServiceName));
ipp_lister_->Announce(MakeServiceDescription(
"Printer17", ZeroconfPrinterDetector::kIppServiceName));
CompleteTasks(); CompleteTasks();
ExpectPrintersAre({MakeExpectedPrinter("Printer12", ServiceType::kIpps), ExpectPrintersAre({MakeExpectedPrinter("Printer12", ServiceType::kIpps),
MakeExpectedPrinter("Printer13", ServiceType::kIppE), MakeExpectedPrinter("Printer13", ServiceType::kIppE),
...@@ -705,7 +577,8 @@ TEST_F(ZeroconfPrinterDetectorTest, GeneralMixedTraffic) { ...@@ -705,7 +577,8 @@ TEST_F(ZeroconfPrinterDetectorTest, GeneralMixedTraffic) {
TEST_F(ZeroconfPrinterDetectorTest, DestroyedWithTasksPending) { TEST_F(ZeroconfPrinterDetectorTest, DestroyedWithTasksPending) {
CreateDetector(); CreateDetector();
// Cause a callback to be queued. // Cause a callback to be queued.
ipp_lister_->Announce("TestPrinter"); ipp_lister_->Announce(MakeServiceDescription(
"TestPrinter", ZeroconfPrinterDetector::kIppServiceName));
// Run listers but don't run the delayed tasks. // Run listers but don't run the delayed tasks.
task_environment_.RunUntilIdle(); task_environment_.RunUntilIdle();
......
// Copyright 2020 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 "chrome/browser/local_discovery/fake_service_discovery_device_lister.h"
#include <utility>
#include "base/bind.h"
#include "base/check.h"
#include "base/location.h"
#include "base/stl_util.h"
#include "base/strings/strcat.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace local_discovery {
DeferringDelegate::DeferringDelegate() = default;
DeferringDelegate::~DeferringDelegate() = default;
void DeferringDelegate::OnDeviceChanged(
const std::string& service_type,
bool added,
const ServiceDescription& service_description) {
if (actual_) {
actual_->OnDeviceChanged(service_type, added, service_description);
} else {
deferred_callbacks_.push_back(base::BindOnce(
&DeferringDelegate::OnDeviceChanged, base::Unretained(this),
service_type, added, service_description));
}
}
void DeferringDelegate::OnDeviceRemoved(const std::string& service_type,
const std::string& service_name) {
if (actual_) {
actual_->OnDeviceRemoved(service_type, service_name);
} else {
deferred_callbacks_.push_back(
base::BindOnce(&DeferringDelegate::OnDeviceRemoved,
base::Unretained(this), service_type, service_name));
}
}
void DeferringDelegate::OnDeviceCacheFlushed(const std::string& service_type) {
if (actual_) {
actual_->OnDeviceCacheFlushed(service_type);
} else {
deferred_callbacks_.push_back(
base::BindOnce(&DeferringDelegate::OnDeviceCacheFlushed,
base::Unretained(this), service_type));
}
}
void DeferringDelegate::SetActual(
ServiceDiscoveryDeviceLister::Delegate* actual) {
CHECK(!actual_);
actual_ = actual;
for (auto& cb : deferred_callbacks_)
std::move(cb).Run();
deferred_callbacks_.clear();
}
FakeServiceDiscoveryDeviceLister::FakeServiceDiscoveryDeviceLister(
base::TaskRunner* task_runner,
const std::string& service_type)
: task_runner_(task_runner), service_type_(service_type) {}
FakeServiceDiscoveryDeviceLister::~FakeServiceDiscoveryDeviceLister() = default;
void FakeServiceDiscoveryDeviceLister::Start() {
if (start_called_)
ADD_FAILURE() << "Start called multiple times";
start_called_ = true;
}
void FakeServiceDiscoveryDeviceLister::DiscoverNewDevices() {
if (!start_called_)
ADD_FAILURE() << "DiscoverNewDevices called before Start";
discovery_started_ = true;
for (const auto& update : queued_updates_)
SendUpdate(update);
queued_updates_.clear();
}
const std::string& FakeServiceDiscoveryDeviceLister::service_type() const {
return service_type_;
}
void FakeServiceDiscoveryDeviceLister::SetDelegate(
ServiceDiscoveryDeviceLister::Delegate* delegate) {
deferring_delegate_.SetActual(delegate);
}
void FakeServiceDiscoveryDeviceLister::Announce(
const ServiceDescription& description) {
if (description.service_type() != service_type_)
return;
if (!discovery_started_)
queued_updates_.push_back(description);
else
SendUpdate(description);
}
void FakeServiceDiscoveryDeviceLister::Remove(const std::string& name) {
std::string service_name = base::StrCat({name, ".", service_type_});
announced_services_.erase(service_name);
CHECK(task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&ServiceDiscoveryDeviceLister::Delegate::OnDeviceRemoved,
base::Unretained(&deferring_delegate_), service_type_,
service_name)));
}
void FakeServiceDiscoveryDeviceLister::Clear() {
announced_services_.clear();
discovery_started_ = false;
CHECK(task_runner_->PostTask(
FROM_HERE,
base::BindOnce(
&ServiceDiscoveryDeviceLister::Delegate::OnDeviceCacheFlushed,
base::Unretained(&deferring_delegate_), service_type_)));
}
bool FakeServiceDiscoveryDeviceLister::discovery_started() {
return discovery_started_;
}
void FakeServiceDiscoveryDeviceLister::SendUpdate(
const ServiceDescription& description) {
bool is_new;
if (!base::Contains(announced_services_, description.service_name)) {
is_new = true;
announced_services_.insert(description.service_name);
} else {
is_new = false;
}
CHECK(task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&ServiceDiscoveryDeviceLister::Delegate::OnDeviceChanged,
base::Unretained(&deferring_delegate_), service_type_,
is_new, description)));
}
} // namespace local_discovery
// Copyright 2020 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.
#ifndef CHROME_BROWSER_LOCAL_DISCOVERY_FAKE_SERVICE_DISCOVERY_DEVICE_LISTER_H_
#define CHROME_BROWSER_LOCAL_DISCOVERY_FAKE_SERVICE_DISCOVERY_DEVICE_LISTER_H_
#include <set>
#include <string>
#include <vector>
#include "base/callback.h"
#include "base/task_runner.h"
#include "chrome/browser/local_discovery/service_discovery_client.h"
#include "chrome/browser/local_discovery/service_discovery_device_lister.h"
namespace local_discovery {
// This is a thin wrapper around Delegate that defers callbacks until the actual
// delegate is initialized and then calls all deferred callbacks. Once the
// actual delegate is initialized, this just becomes a simple passthrough.
class DeferringDelegate : public ServiceDiscoveryDeviceLister::Delegate {
public:
DeferringDelegate();
~DeferringDelegate();
// ServiceDiscoveryDeviceLister::Delegate:
void OnDeviceChanged(const std::string& service_type,
bool added,
const ServiceDescription& service_description) override;
void OnDeviceRemoved(const std::string& service_type,
const std::string& service_name) override;
void OnDeviceCacheFlushed(const std::string& service_type) override;
// Sets the delegate that callbacks should be called on.
void SetActual(ServiceDiscoveryDeviceLister::Delegate* actual);
private:
std::vector<base::OnceCallback<void()>> deferred_callbacks_;
ServiceDiscoveryDeviceLister::Delegate* actual_ = nullptr;
};
// A fake ServiceDiscoveryDeviceLister. This provides an implementation of
// ServiceDiscoveryDeviceLister that tests can use to trigger the addition and
// removal of devices.
//
// There's some hackery here to handle constructor order constraints. There's a
// circular dependency in that device lister delegate implementations need their
// device lister set to be supplied at construction time, and each device lister
// needs to know about its delegate for callbacks. Thus, a DeferringDelegate is
// used to queue callbacks triggered before the class has the delegate
// reference, and those queued callbacks are invoked when the delegate is set.
class FakeServiceDiscoveryDeviceLister final
: public ServiceDiscoveryDeviceLister {
public:
FakeServiceDiscoveryDeviceLister(base::TaskRunner* task_runner,
const std::string& service_type);
~FakeServiceDiscoveryDeviceLister() override;
// ServiceDiscoveryDeviceLister:
void Start() override;
void DiscoverNewDevices() override;
const std::string& service_type() const override;
// Sets the delegate of this lister.
void SetDelegate(ServiceDiscoveryDeviceLister::Delegate* delegate);
// Announces a new service or updates it if it's been seen before and already
// announced. If discovery hasn't started yet, the description is queued to be
// sent when discovery is started. If the description's service type does not
// match the lister's service type, the service is not announced.
void Announce(const ServiceDescription& description);
// Removes the service specified by |name|.
void Remove(const std::string& name);
// Simulates an event that clears downstream caches and the lister.
void Clear();
// Indicates whether discovery has started.
bool discovery_started();
private:
// Helper function that sends an update to the delegate via the
// OnDeviceChanged callback.
void SendUpdate(const ServiceDescription& description);
// Used to post tasks for the delegate callbacks.
base::TaskRunner* task_runner_;
// Services which have previously posted an update and therefore are no
// longer 'new' for the purposes of the OnDeviceChanged callback.
std::set<std::string> announced_services_;
// Updates added to the class before discovery started.
std::vector<ServiceDescription> queued_updates_;
// Has Start() been called?
bool start_called_ = false;
// Has DiscoverNewDevices() been called?
bool discovery_started_ = false;
// The service type of this lister.
std::string service_type_;
// The delegate of this lister.
DeferringDelegate deferring_delegate_;
};
} // namespace local_discovery
#endif // CHROME_BROWSER_LOCAL_DISCOVERY_FAKE_SERVICE_DISCOVERY_DEVICE_LISTER_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment