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") {
if (enable_service_discovery) {
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.h",
]
......
// 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