blob: 206a48d60db3a9a6a012fae9bd62225b094d7482 [file] [log] [blame]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ash/scanning/lorgnette_scanner_manager.h"
#include <cstdint>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/containers/flat_map.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "base/test/task_environment.h"
#include "chrome/browser/ash/scanning/zeroconf_scanner_detector.h"
#include "chrome/browser/ash/scanning/zeroconf_scanner_detector_utils.h"
#include "chrome/browser/local_discovery/service_discovery_client.h"
#include "chromeos/ash/components/dbus/lorgnette/lorgnette_service.pb.h"
#include "chromeos/ash/components/dbus/lorgnette_manager/fake_lorgnette_manager_client.h"
#include "chromeos/ash/components/dbus/lorgnette_manager/lorgnette_manager_client.h"
#include "chromeos/ash/components/scanning/scanner.h"
#include "net/base/ip_address.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
namespace ash {
namespace {
using local_discovery::ServiceDescription;
using ::testing::ElementsAreArray;
// Test device names for different types of lorgnette scanners.
constexpr char kLorgnetteNetworkIpDeviceName[] = "test:MX3100_192.168.0.3";
constexpr char kLorgnetteNetworkUrlDeviceName[] =
"http://testscanner.domain.org";
constexpr char kLorgnetteUsbDeviceName[] = "test:04A91752_94370B";
constexpr char kLorgnetteNetworkEpsonDeviceName[] = "epson2:net:192.168.0.3";
// A scanner name that does not correspond to a known scanner.
constexpr char kUnknownScannerName[] = "Unknown Scanner";
// Model which contains the manufacturer.
constexpr char kModelContainingManufacturer[] = "TEST Model X";
// Returns a ScannerInfo object with the given |name| and |model|, if provided.
lorgnette::ScannerInfo CreateLorgnetteScanner(
std::string name,
const std::string& model = "MX3100") {
lorgnette::ScannerInfo scanner;
scanner.set_name(name);
scanner.set_manufacturer("Test");
scanner.set_model(model);
scanner.set_type("Flatbed");
return scanner;
}
// Returns a ListScannersResponse containing a single ScannerInfo object created
// with the given |name| and |model|, if provided.
lorgnette::ListScannersResponse CreateListScannersResponse(
std::string name,
const std::string& model = "MX3100") {
lorgnette::ScannerInfo scanner = CreateLorgnetteScanner(name, model);
lorgnette::ListScannersResponse response;
*response.add_scanners() = std::move(scanner);
return response;
}
// Returns a zeroconf Scanner with the device name marked as |usable|.
Scanner CreateZeroconfScanner(bool usable = true) {
return CreateSaneScanner("Test MX3100",
ZeroconfScannerDetector::kEsclsServiceType, "",
net::IPAddress(192, 168, 0, 3), 5, usable)
.value();
}
// Returns a zeroconf Scanner with the Epsonds backend and the device name
// marked as |usable|
Scanner CreateNonEsclEpsonZeroconfScanner(bool usable = true) {
return CreateSaneScanner("EPSON TEST",
ZeroconfScannerDetector::kGenericScannerServiceType,
"", net::IPAddress(192, 168, 0, 3), 5, usable)
.value();
}
// Returns a zeroconf Scanner with an Epson name but ESCLs Service marked as
// |usable|.
Scanner CreateEsclEpsonZeroconfScanner(bool usable = true) {
return CreateSaneScanner("EPSON TEST",
ZeroconfScannerDetector::kEsclsServiceType, "",
net::IPAddress(192, 168, 0, 3), 5, usable)
.value();
}
// Returns a zeroconf Scanner with |scanner_name| and device name marked
// |usable|.
Scanner CreateScannerCustomName(const std::string& scanner_name,
bool usable = true) {
return CreateSaneScanner(scanner_name,
ZeroconfScannerDetector::kEsclsServiceType, "",
net::IPAddress(192, 168, 0, 3), 5, usable)
.value();
}
class FakeZeroconfScannerDetector final : public ZeroconfScannerDetector {
public:
FakeZeroconfScannerDetector() = default;
~FakeZeroconfScannerDetector() override = default;
void RegisterScannersDetectedCallback(
OnScannersDetectedCallback callback) override {
on_scanners_detected_callback_ = std::move(callback);
}
std::vector<Scanner> GetScanners() override {
std::vector<Scanner> scanners;
for (const auto& entry : scanners_)
scanners.push_back(entry.second);
return scanners;
}
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 {}
// Used to trigger on_scanners_detected_callback_ after adding the given
// |scanners| to the detected scanners.
void AddDetections(const std::vector<Scanner>& scanners) {
for (const auto& scanner : scanners)
scanners_[scanner.display_name] = scanner;
on_scanners_detected_callback_.Run(GetScanners());
}
// Used to trigger on_scanners_detected_callback_ after removing the given
// |scanners| from the detected scanners.
void RemoveDetections(const std::vector<Scanner>& scanners) {
for (const auto& scanner : scanners)
scanners_.erase(scanner.display_name);
on_scanners_detected_callback_.Run(GetScanners());
}
private:
base::flat_map<std::string, Scanner> scanners_;
OnScannersDetectedCallback on_scanners_detected_callback_;
};
} // namespace
class LorgnetteScannerManagerTest : public testing::Test {
public:
LorgnetteScannerManagerTest() {
run_loop_ = std::make_unique<base::RunLoop>();
LorgnetteManagerClient::InitializeFake();
auto fake_zeroconf_scanner_detector =
std::make_unique<FakeZeroconfScannerDetector>();
fake_zeroconf_scanner_detector_ = fake_zeroconf_scanner_detector.get();
lorgnette_scanner_manager_ = LorgnetteScannerManager::Create(
std::move(fake_zeroconf_scanner_detector));
// Set empty but successful capabilities response by default.
lorgnette::ScannerCapabilities capabilities;
GetLorgnetteManagerClient()->SetScannerCapabilitiesResponse(capabilities);
}
~LorgnetteScannerManagerTest() override {
LorgnetteManagerClient::Shutdown();
}
// Returns a FakeLorgnetteManagerClient with an empty but successful
// GetCapabilities response by default.
FakeLorgnetteManagerClient* GetLorgnetteManagerClient() {
return static_cast<FakeLorgnetteManagerClient*>(
LorgnetteManagerClient::Get());
}
// Calls LorgnetteScannerManager::GetScannerNames() and binds a callback to
// process the result.
void GetScannerNames() {
lorgnette_scanner_manager_->GetScannerNames(
base::BindOnce(&LorgnetteScannerManagerTest::GetScannerNamesCallback,
base::Unretained(this)));
}
// Calls LorgnetteScannerManager::GetScannerCapabilities() and binds a
// callback to process the result.
void GetScannerCapabilities(const std::string& scanner_name) {
lorgnette_scanner_manager_->GetScannerCapabilities(
scanner_name,
base::BindOnce(
&LorgnetteScannerManagerTest::GetScannerCapabilitiesCallback,
base::Unretained(this)));
}
// Calls LorgnetteScannerManager::IsRotateAlternate() and returns result.
bool GetRotateAlternate(const std::string& scanner_name,
const std::string& source_name) {
return lorgnette_scanner_manager_->IsRotateAlternate(scanner_name,
source_name);
}
// Calls LorgnetteScannerManager::Scan() and binds a callback to process the
// result.
void Scan(const std::string& scanner_name,
const lorgnette::ScanSettings& settings) {
lorgnette_scanner_manager_->Scan(
scanner_name, settings, base::NullCallback(),
base::BindRepeating(&LorgnetteScannerManagerTest::PageCallback,
base::Unretained(this)),
base::BindOnce(&LorgnetteScannerManagerTest::ScanCallback,
base::Unretained(this)));
}
// Calls LorgnetteScannerManager::CancelScan() and binds a callback to process
// the result.
void CancelScan() {
lorgnette_scanner_manager_->CancelScan(
base::BindOnce(&LorgnetteScannerManagerTest::CancelScanCallback,
base::Unretained(this)));
}
// Runs all tasks until the ThreadPool's non-delayed queues are empty.
void CompleteTasks() { task_environment_.RunUntilIdle(); }
// Runs run_loop_ until a callback calls Quit().
void WaitForResult() {
run_loop_->Run();
run_loop_ = std::make_unique<base::RunLoop>();
}
FakeZeroconfScannerDetector* fake_zeroconf_scanner_detector() {
return fake_zeroconf_scanner_detector_;
}
const std::vector<std::string>& scanner_names() const {
return scanner_names_;
}
absl::optional<lorgnette::ScannerCapabilities> scanner_capabilities() const {
return scanner_capabilities_;
}
std::vector<std::string> scan_data() const { return scan_data_; }
lorgnette::ScanFailureMode failure_mode() const { return failure_mode_; }
bool cancel_scan_success() const { return cancel_scan_success_; }
private:
// Handles the result of calling LorgnetteScannerManager::GetScannerNames().
void GetScannerNamesCallback(std::vector<std::string> scanner_names) {
scanner_names_ = scanner_names;
run_loop_->Quit();
}
void GetScannerCapabilitiesCallback(
const absl::optional<lorgnette::ScannerCapabilities>&
scanner_capabilities) {
scanner_capabilities_ = scanner_capabilities;
run_loop_->Quit();
}
// Handles receiving a page from LorgnetteScannerManager::Scan().
void PageCallback(std::string page_data, uint32_t /*page_number*/) {
scan_data_.push_back(page_data);
}
// Handles completion of LorgnetteScannerManager::Scan().
void ScanCallback(lorgnette::ScanFailureMode failure_mode) {
failure_mode_ = failure_mode;
run_loop_->Quit();
}
// Handles completion of LorgnetteScannerManager::CancelScan().
void CancelScanCallback(bool success) {
cancel_scan_success_ = success;
run_loop_->Quit();
}
base::test::TaskEnvironment task_environment_;
std::unique_ptr<base::RunLoop> run_loop_;
FakeZeroconfScannerDetector* fake_zeroconf_scanner_detector_;
std::unique_ptr<LorgnetteScannerManager> lorgnette_scanner_manager_;
std::vector<std::string> scanner_names_;
absl::optional<lorgnette::ScannerCapabilities> scanner_capabilities_;
lorgnette::ScanFailureMode failure_mode_ =
lorgnette::SCAN_FAILURE_MODE_NO_FAILURE;
bool cancel_scan_success_ = false;
std::vector<std::string> scan_data_;
};
// Test that no scanner names are returned when no scanners have been detected.
TEST_F(LorgnetteScannerManagerTest, NoScanners) {
GetScannerNames();
WaitForResult();
EXPECT_TRUE(scanner_names().empty());
}
// Test that no scanner names are returned when scanners are detected, but none
// return capabilities.
TEST_F(LorgnetteScannerManagerTest, NoScannersWithNoCap) {
GetLorgnetteManagerClient()->SetListScannersResponse(
CreateListScannersResponse(kLorgnetteNetworkIpDeviceName));
auto scanner = CreateZeroconfScanner();
fake_zeroconf_scanner_detector()->AddDetections({scanner});
auto epson_scanner = CreateNonEsclEpsonZeroconfScanner();
fake_zeroconf_scanner_detector()->AddDetections({epson_scanner});
GetLorgnetteManagerClient()->SetScannerCapabilitiesResponse(absl::nullopt);
GetScannerNames();
WaitForResult();
EXPECT_TRUE(scanner_names().empty());
}
// Test that the name of a detected zeroconf scanner can be retrieved.
TEST_F(LorgnetteScannerManagerTest, ZeroconfScanner) {
auto scanner = CreateZeroconfScanner();
fake_zeroconf_scanner_detector()->AddDetections({scanner});
CompleteTasks();
GetScannerNames();
WaitForResult();
EXPECT_THAT(scanner_names(), ElementsAreArray({scanner.display_name}));
}
// Test that the name of a detected Epson zeroconf scanner can be retrieved.
TEST_F(LorgnetteScannerManagerTest, NonEsclEpsonZeroconfScanner) {
auto scanner = CreateNonEsclEpsonZeroconfScanner();
fake_zeroconf_scanner_detector()->AddDetections({scanner});
CompleteTasks();
GetScannerNames();
WaitForResult();
EXPECT_THAT(scanner_names(), ElementsAreArray({scanner.display_name}));
}
// Test that the name of a detected ESCL Epson zeroconf scanner can be
// retrieved.
TEST_F(LorgnetteScannerManagerTest, EsclEpsonZeroconfScanner) {
auto scanner = CreateEsclEpsonZeroconfScanner();
fake_zeroconf_scanner_detector()->AddDetections({scanner});
CompleteTasks();
GetScannerNames();
WaitForResult();
EXPECT_THAT(scanner_names(), ElementsAreArray({scanner.display_name}));
}
// Test that the name of a detected non-ESCL zeroconf scanner does not generate
// a scanner if it is not an Epson.
TEST_F(LorgnetteScannerManagerTest, NonEsclNonEpsonZeroconfScanner) {
absl::optional<Scanner> scanner = CreateSaneScanner(
"Test MX3100", ZeroconfScannerDetector::kGenericScannerServiceType, "",
net::IPAddress(192, 168, 0, 3), 5, true);
EXPECT_FALSE(scanner.has_value());
}
// Test that the name of a detected lorgnette scanner can be retrieved.
TEST_F(LorgnetteScannerManagerTest, LorgnetteScanner) {
lorgnette::ListScannersResponse response =
CreateListScannersResponse(kLorgnetteNetworkIpDeviceName);
GetLorgnetteManagerClient()->SetListScannersResponse(response);
GetScannerNames();
WaitForResult();
const auto& scanner = response.scanners()[0];
std::string scanner_name = scanner.manufacturer() + " " + scanner.model();
EXPECT_THAT(scanner_names(), ElementsAreArray({scanner_name}));
}
// Test that two detected scanners with the same IP address are deduplicated and
// reported with single scanner name.
TEST_F(LorgnetteScannerManagerTest, DeduplicateScanner) {
GetLorgnetteManagerClient()->SetListScannersResponse(
CreateListScannersResponse(kLorgnetteNetworkIpDeviceName));
auto scanner = CreateZeroconfScanner();
fake_zeroconf_scanner_detector()->AddDetections({scanner});
auto epson_scanner = CreateNonEsclEpsonZeroconfScanner();
fake_zeroconf_scanner_detector()->AddDetections({epson_scanner});
auto escl_epson_scanner = CreateEsclEpsonZeroconfScanner();
fake_zeroconf_scanner_detector()->AddDetections({escl_epson_scanner});
CompleteTasks();
GetScannerNames();
WaitForResult();
EXPECT_THAT(scanner_names(), ElementsAreArray({epson_scanner.display_name,
scanner.display_name}));
}
// Test that two detected zeroconf Epson scanners and a lorgnette Epson scanner
// with the same IP address are deduplicated and reported with single scanner
// name.
TEST_F(LorgnetteScannerManagerTest, DeduplicateLorgnetteEpsonScanner) {
GetLorgnetteManagerClient()->SetListScannersResponse(
CreateListScannersResponse(kLorgnetteNetworkEpsonDeviceName,
"EPSON Test2"));
auto epson_scanner = CreateNonEsclEpsonZeroconfScanner();
fake_zeroconf_scanner_detector()->AddDetections({epson_scanner});
auto escl_epson_scanner = CreateEsclEpsonZeroconfScanner();
fake_zeroconf_scanner_detector()->AddDetections({escl_epson_scanner});
CompleteTasks();
GetScannerNames();
WaitForResult();
EXPECT_THAT(scanner_names(), ElementsAreArray({epson_scanner.display_name}));
}
// Test that two detected scanners with the same IP address are deduplicated and
// reported with single scanner name, while USB of the same model is reported
// separately.
TEST_F(LorgnetteScannerManagerTest, DeduplicateNetPlusUsbScanner) {
lorgnette::ListScannersResponse response;
lorgnette::ScannerInfo info =
CreateLorgnetteScanner(kLorgnetteUsbDeviceName, "MX3100");
*response.add_scanners() = std::move(info);
info = CreateLorgnetteScanner(kLorgnetteNetworkIpDeviceName, "MX3100");
*response.add_scanners() = std::move(info);
GetLorgnetteManagerClient()->SetListScannersResponse(response);
auto scanner = CreateZeroconfScanner();
fake_zeroconf_scanner_detector()->AddDetections({scanner});
CompleteTasks();
GetScannerNames();
WaitForResult();
EXPECT_THAT(scanner_names(),
ElementsAreArray(
{scanner.display_name, scanner.display_name + " (USB)"}));
}
// Test that a lorgnette scanner with a URL in the name gets reported as a
// network scanner instead of a USB scanner (i.e. USB is not in the returned
// scanner name).
TEST_F(LorgnetteScannerManagerTest, LorgnetteScannerWithUrl) {
lorgnette::ListScannersResponse response =
CreateListScannersResponse(kLorgnetteNetworkUrlDeviceName);
GetLorgnetteManagerClient()->SetListScannersResponse(response);
GetScannerNames();
WaitForResult();
auto& scanner = response.scanners()[0];
std::string scanner_name = scanner.manufacturer() + " " + scanner.model();
EXPECT_THAT(scanner_names(), ElementsAreArray({scanner_name}));
}
// Test that detecting a lorgnette USB scanner results in a scanner name ending
// with "(USB)."
TEST_F(LorgnetteScannerManagerTest, LorgnetteUSBScanner) {
lorgnette::ListScannersResponse response =
CreateListScannersResponse(kLorgnetteUsbDeviceName);
GetLorgnetteManagerClient()->SetListScannersResponse(response);
GetScannerNames();
WaitForResult();
auto& scanner = response.scanners()[0];
std::string scanner_name =
scanner.manufacturer() + " " + scanner.model() + " (USB)";
EXPECT_THAT(scanner_names(), ElementsAreArray({scanner_name}));
}
// Test that a lorgnette scanner whose model includes the manufacturer doesn't
// duplicate the manufacturer in the display name.
TEST_F(LorgnetteScannerManagerTest, LorgnetteScannerNoDuplicatedManufacturer) {
lorgnette::ListScannersResponse response = CreateListScannersResponse(
kLorgnetteNetworkIpDeviceName, kModelContainingManufacturer);
GetLorgnetteManagerClient()->SetListScannersResponse(response);
GetScannerNames();
WaitForResult();
const auto& scanner = response.scanners()[0];
EXPECT_THAT(scanner_names(), ElementsAreArray({scanner.model()}));
}
// Test that two lorgnette scanners with the same manufacturer and model are
// given unique names.
TEST_F(LorgnetteScannerManagerTest, UniqueScannerNames) {
lorgnette::ListScannersResponse response =
CreateListScannersResponse(kLorgnetteNetworkIpDeviceName);
lorgnette::ScannerInfo scanner =
CreateLorgnetteScanner(kLorgnetteNetworkIpDeviceName);
*response.add_scanners() = std::move(scanner);
GetLorgnetteManagerClient()->SetListScannersResponse(response);
GetScannerNames();
WaitForResult();
ASSERT_EQ(scanner_names().size(), 2u);
EXPECT_NE(scanner_names()[0], scanner_names()[1]);
}
// Test that removing a detected scanner removes it from the list of available
// scanners.
TEST_F(LorgnetteScannerManagerTest, RemoveScanner) {
auto scanner = CreateZeroconfScanner();
fake_zeroconf_scanner_detector()->AddDetections({scanner});
CompleteTasks();
GetScannerNames();
WaitForResult();
EXPECT_THAT(scanner_names(), ElementsAreArray({scanner.display_name}));
fake_zeroconf_scanner_detector()->RemoveDetections({scanner});
CompleteTasks();
GetScannerNames();
WaitForResult();
EXPECT_TRUE(scanner_names().empty());
}
// Test that getting capabilities fails when GetScannerNames() has never been
// called.
TEST_F(LorgnetteScannerManagerTest, GetCapsNoScanner) {
GetScannerCapabilities(kUnknownScannerName);
WaitForResult();
EXPECT_FALSE(scanner_capabilities());
}
// Test that getting capabilities fails when the scanner name does not
// correspond to a known scanner.
TEST_F(LorgnetteScannerManagerTest, GetCapsUnknownScanner) {
fake_zeroconf_scanner_detector()->AddDetections({CreateZeroconfScanner()});
CompleteTasks();
GetScannerNames();
WaitForResult();
GetScannerCapabilities(kUnknownScannerName);
WaitForResult();
EXPECT_FALSE(scanner_capabilities());
}
// Test that getting capabilities fails when there is no usable device name.
TEST_F(LorgnetteScannerManagerTest, GetCapsNoUsableDeviceName) {
auto scanner = CreateZeroconfScanner(/*usable=*/false);
fake_zeroconf_scanner_detector()->AddDetections({scanner});
CompleteTasks();
GetScannerNames();
WaitForResult();
GetScannerCapabilities(scanner.display_name);
WaitForResult();
EXPECT_FALSE(scanner_capabilities());
}
// Test that failing to get capabilities from lorgnette returns no capabilities.
TEST_F(LorgnetteScannerManagerTest, GetCapsFail) {
auto scanner = CreateZeroconfScanner();
fake_zeroconf_scanner_detector()->AddDetections({scanner});
CompleteTasks();
GetScannerNames();
WaitForResult();
GetLorgnetteManagerClient()->SetScannerCapabilitiesResponse(absl::nullopt);
GetScannerCapabilities(scanner.display_name);
WaitForResult();
EXPECT_FALSE(scanner_capabilities());
}
// Test that getting capabilities succeeds with a valid scanner name.
TEST_F(LorgnetteScannerManagerTest, GetCaps) {
auto scanner = CreateZeroconfScanner();
fake_zeroconf_scanner_detector()->AddDetections({scanner});
CompleteTasks();
lorgnette::ScannerCapabilities capabilities;
capabilities.add_resolutions(300);
capabilities.add_color_modes(lorgnette::MODE_COLOR);
GetLorgnetteManagerClient()->SetScannerCapabilitiesResponse(capabilities);
GetScannerNames();
WaitForResult();
GetScannerCapabilities(scanner.display_name);
WaitForResult();
ASSERT_TRUE(scanner_capabilities());
const auto caps = scanner_capabilities().value();
ASSERT_EQ(caps.resolutions_size(), 1);
EXPECT_EQ(caps.resolutions()[0], 300u);
EXPECT_EQ(caps.sources_size(), 0);
ASSERT_EQ(caps.color_modes_size(), 1);
EXPECT_EQ(caps.color_modes()[0], lorgnette::MODE_COLOR);
}
// Test that scanning fails when GetScannerNames() has never been called.
TEST_F(LorgnetteScannerManagerTest, NoScannersNames) {
lorgnette::ScanSettings settings;
Scan(kUnknownScannerName, settings);
WaitForResult();
EXPECT_EQ(scan_data().size(), 0u);
EXPECT_EQ(failure_mode(), lorgnette::SCAN_FAILURE_MODE_UNKNOWN);
}
// Test that scanning fails when the scanner name does not correspond to a known
// scanner.
TEST_F(LorgnetteScannerManagerTest, UnknownScannerName) {
fake_zeroconf_scanner_detector()->AddDetections({CreateZeroconfScanner()});
CompleteTasks();
GetScannerNames();
WaitForResult();
lorgnette::ScanSettings settings;
Scan(kUnknownScannerName, settings);
WaitForResult();
EXPECT_EQ(scan_data().size(), 0u);
EXPECT_EQ(failure_mode(), lorgnette::SCAN_FAILURE_MODE_UNKNOWN);
}
// Test that scanning fails when there is no usable device name.
TEST_F(LorgnetteScannerManagerTest, NoUsableDeviceName) {
auto scanner = CreateZeroconfScanner(/*usable=*/false);
fake_zeroconf_scanner_detector()->AddDetections({scanner});
CompleteTasks();
GetScannerNames();
WaitForResult();
lorgnette::ScanSettings settings;
Scan(scanner.display_name, settings);
WaitForResult();
EXPECT_EQ(scan_data().size(), 0u);
EXPECT_EQ(failure_mode(), lorgnette::SCAN_FAILURE_MODE_UNKNOWN);
}
// Test that images aren't rotated when scanner isn't an Epson scanner.
TEST_F(LorgnetteScannerManagerTest, ScanNotRotatedNonEpson) {
auto scanner = CreateZeroconfScanner();
fake_zeroconf_scanner_detector()->AddDetections({scanner});
CompleteTasks();
GetScannerNames();
WaitForResult();
EXPECT_FALSE(GetRotateAlternate(scanner.display_name, "ADF Duplex"));
}
// Test that images aren't rotated when scanner is a non-rotating Epson scanner.
TEST_F(LorgnetteScannerManagerTest, ScanNotRotatedEpsonException) {
auto scanner = CreateScannerCustomName("Epson WF-C579Ra");
fake_zeroconf_scanner_detector()->AddDetections({scanner});
CompleteTasks();
GetScannerNames();
WaitForResult();
EXPECT_FALSE(GetRotateAlternate(scanner.display_name, "ADF Duplex"));
}
// Test that images aren't rotated when scan request is non-ADF.
TEST_F(LorgnetteScannerManagerTest, ScanNotRotatedNonADF) {
auto scanner = CreateScannerCustomName("Epson XP-7100");
fake_zeroconf_scanner_detector()->AddDetections({scanner});
CompleteTasks();
GetScannerNames();
WaitForResult();
EXPECT_FALSE(GetRotateAlternate(scanner.display_name, "Flatbed"));
}
// Test that scanned images are rotated when scanner setup requires it.
TEST_F(LorgnetteScannerManagerTest, ScanRotated) {
auto scanner = CreateScannerCustomName("Epson XP-7100");
fake_zeroconf_scanner_detector()->AddDetections({scanner});
CompleteTasks();
GetScannerNames();
WaitForResult();
EXPECT_TRUE(GetRotateAlternate(scanner.display_name, "ADF Duplex"));
}
// Test that scanning succeeds with a valid scanner name.
TEST_F(LorgnetteScannerManagerTest, ScanOnePage) {
auto scanner = CreateZeroconfScanner();
fake_zeroconf_scanner_detector()->AddDetections({scanner});
CompleteTasks();
GetScannerNames();
WaitForResult();
std::vector<std::string> pages = {"TestScanData"};
GetLorgnetteManagerClient()->SetScanResponse(pages);
lorgnette::ScanSettings settings;
Scan(scanner.display_name, settings);
WaitForResult();
ASSERT_EQ(scan_data().size(), 1u);
EXPECT_EQ(scan_data()[0], "TestScanData");
EXPECT_EQ(failure_mode(), lorgnette::SCAN_FAILURE_MODE_NO_FAILURE);
}
TEST_F(LorgnetteScannerManagerTest, ScanMultiplePages) {
auto scanner = CreateZeroconfScanner();
fake_zeroconf_scanner_detector()->AddDetections({scanner});
CompleteTasks();
GetScannerNames();
WaitForResult();
std::vector<std::string> pages = {"TestPageOne", "TestPageTwo",
"TestPageThree"};
GetLorgnetteManagerClient()->SetScanResponse(pages);
lorgnette::ScanSettings settings;
Scan(scanner.display_name, settings);
WaitForResult();
ASSERT_EQ(scan_data().size(), 3u);
EXPECT_EQ(scan_data()[0], "TestPageOne");
EXPECT_EQ(scan_data()[1], "TestPageTwo");
EXPECT_EQ(scan_data()[2], "TestPageThree");
EXPECT_EQ(failure_mode(), lorgnette::SCAN_FAILURE_MODE_NO_FAILURE);
}
// Test that requesting to cancel the current scan job returns the success
// result.
TEST_F(LorgnetteScannerManagerTest, CancelScan) {
auto scanner = CreateZeroconfScanner();
fake_zeroconf_scanner_detector()->AddDetections({scanner});
CompleteTasks();
GetScannerNames();
WaitForResult();
CancelScan();
WaitForResult();
EXPECT_TRUE(cancel_scan_success());
}
} // namespace ash