| // Copyright 2018 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 <cups/cups.h> |
| |
| #include <map> |
| #include <string> |
| #include <utility> |
| |
| #include "base/bind.h" |
| #include "base/containers/contains.h" |
| #include "base/guid.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/test/task_environment.h" |
| #include "chrome/services/cups_proxy/fake_cups_proxy_service_delegate.h" |
| #include "chrome/services/cups_proxy/printer_installer.h" |
| #include "printing/backend/cups_ipp_helper.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace cups_proxy { |
| namespace { |
| |
| using Printer = chromeos::Printer; |
| |
| // Generated via base::GenerateGUID. |
| const char kGenericGUID[] = "fd4c5f2e-7549-43d5-b931-9bf4e4f1bf51"; |
| |
| // Faked delegate gives control over PrinterInstaller's printing stack |
| // dependencies. |
| class FakeServiceDelegate : public FakeCupsProxyServiceDelegate { |
| public: |
| FakeServiceDelegate() = default; |
| ~FakeServiceDelegate() override = default; |
| |
| void AddPrinter(const Printer& printer) { |
| installed_printers_.insert({printer.id(), false}); |
| } |
| |
| void FailSetupPrinter() { fail_printer_setup_ = true; } |
| |
| // Service delegate overrides. |
| bool IsPrinterInstalled(const Printer& printer) override { |
| if (!base::Contains(installed_printers_, printer.id())) { |
| return false; |
| } |
| |
| return installed_printers_.at(printer.id()); |
| } |
| |
| void PrinterInstalled(const Printer& printer) override { |
| DCHECK(base::Contains(installed_printers_, printer.id())); |
| installed_printers_[printer.id()] = true; |
| } |
| |
| absl::optional<Printer> GetPrinter(const std::string& id) override { |
| if (!base::Contains(installed_printers_, id)) { |
| return absl::nullopt; |
| } |
| |
| return Printer(id); |
| } |
| |
| void SetupPrinter(const Printer& printer, |
| SetupPrinterCallback callback) override { |
| if (fail_printer_setup_) { |
| return std::move(callback).Run(false); |
| } |
| |
| // PrinterInstaller is expected to have checked if |printer| is already |
| // installed before trying setup. |
| if (IsPrinterInstalled(printer)) { |
| return std::move(callback).Run(false); |
| } |
| |
| // Install printer. |
| return std::move(callback).Run(true); |
| } |
| |
| private: |
| std::map<std::string, bool> installed_printers_; |
| |
| // Conditions whether calls to SetupPrinter succeed. |
| bool fail_printer_setup_ = false; |
| }; |
| |
| class PrinterInstallerTest : public testing::Test { |
| public: |
| PrinterInstallerTest() : weak_factory_(this) { |
| delegate_ = std::make_unique<FakeServiceDelegate>(); |
| printer_installer_ = std::make_unique<PrinterInstaller>(delegate_.get()); |
| } |
| |
| ~PrinterInstallerTest() override = default; |
| |
| InstallPrinterResult RunInstallPrinter(std::string printer_id) { |
| InstallPrinterResult ret; |
| |
| base::RunLoop run_loop; |
| printer_installer_->InstallPrinter( |
| printer_id, base::BindOnce(&PrinterInstallerTest::OnRunInstallPrinter, |
| weak_factory_.GetWeakPtr(), |
| run_loop.QuitClosure(), &ret)); |
| |
| run_loop.Run(); |
| return ret; |
| } |
| |
| protected: |
| base::test::TaskEnvironment task_environment_; |
| |
| void OnRunInstallPrinter(base::OnceClosure finish_cb, |
| InstallPrinterResult* ret, |
| InstallPrinterResult result) { |
| *ret = result; |
| std::move(finish_cb).Run(); |
| } |
| |
| // Backend fake driving the PrinterInstaller. |
| std::unique_ptr<FakeServiceDelegate> delegate_; |
| |
| // The class being tested. This must be declared after the fakes, as its |
| // initialization must come after that of the fakes. |
| std::unique_ptr<PrinterInstaller> printer_installer_; |
| |
| base::WeakPtrFactory<PrinterInstallerTest> weak_factory_; |
| }; |
| |
| // Standard install known printer workflow. |
| TEST_F(PrinterInstallerTest, SimpleSanityTest) { |
| Printer to_install(kGenericGUID); |
| delegate_->AddPrinter(to_install); |
| |
| auto ret = RunInstallPrinter(kGenericGUID); |
| EXPECT_EQ(ret, InstallPrinterResult::kSuccess); |
| EXPECT_TRUE(delegate_->IsPrinterInstalled(to_install)); |
| } |
| |
| // Should fail to install an unknown(previously unseen) printer. |
| TEST_F(PrinterInstallerTest, UnknownPrinter) { |
| Printer to_install(kGenericGUID); |
| |
| auto ret = RunInstallPrinter(kGenericGUID); |
| EXPECT_EQ(ret, InstallPrinterResult::kUnknownPrinterFound); |
| EXPECT_FALSE(delegate_->IsPrinterInstalled(to_install)); |
| } |
| |
| // Ensure we never setup a printer that's already installed. |
| TEST_F(PrinterInstallerTest, InstallPrinterTwice) { |
| Printer to_install(kGenericGUID); |
| delegate_->AddPrinter(to_install); |
| |
| auto ret = RunInstallPrinter(kGenericGUID); |
| EXPECT_EQ(ret, InstallPrinterResult::kSuccess); |
| |
| // |printer_installer_| should notice printer is already installed and bail |
| // out. If it attempts setup, FakeServiceDelegate will fail the request. |
| ret = RunInstallPrinter(kGenericGUID); |
| EXPECT_EQ(ret, InstallPrinterResult::kSuccess); |
| } |
| |
| // Checks for correct response to failed SetupPrinter call. |
| TEST_F(PrinterInstallerTest, SetupPrinterFailure) { |
| Printer to_install(kGenericGUID); |
| delegate_->AddPrinter(to_install); |
| delegate_->FailSetupPrinter(); |
| |
| auto ret = RunInstallPrinter(kGenericGUID); |
| EXPECT_EQ(ret, InstallPrinterResult::kPrinterInstallationFailure); |
| EXPECT_FALSE(delegate_->IsPrinterInstalled(to_install)); |
| } |
| |
| } // namespace |
| } // namespace cups_proxy |