| // Copyright 2023 The ChromiumOS Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <algorithm> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include <gtest/gtest.h> |
| #include <gmock/gmock.h> |
| |
| #include <base/files/scoped_temp_dir.h> |
| #include <base/files/file_util.h> |
| #include <base/files/file_path.h> |
| #include <base/strings/stringprintf.h> |
| #include <base/test/task_environment.h> |
| #include <chromeos/dbus/printscanmgr/dbus-constants.h> |
| #include <mojo/public/cpp/bindings/remote.h> |
| #include <printscanmgr/proto_bindings/printscanmgr_service.pb.h> |
| |
| #include "printscanmgr/daemon/cups_tool.h" |
| #include "printscanmgr/executor/mock_executor.h" |
| #include "printscanmgr/mojom/executor.mojom.h" |
| |
| using ::testing::_; |
| using ::testing::Invoke; |
| using ::testing::Return; |
| using ::testing::StrictMock; |
| using ::testing::WithArg; |
| |
| namespace printscanmgr { |
| |
| namespace { |
| |
| constexpr std::string_view kMinimalPPDContent(R"PPD(*PPD-Adobe: "4.3" |
| *FormatVersion: "4.3" |
| *FileVersion: "1.0" |
| *LanguageVersion: English |
| *LanguageEncoding: ISOLatin1 |
| *PCFileName: "SAMPLE.PPD" |
| *Product: "(Sample)" |
| *PSVersion: "(1) 1" |
| *ModelName: "Sample" |
| *ShortNickName: "Sample" |
| *NickName: "Sample" |
| *Manufacturer: "Sample" |
| *OpenUI *PageSize: PickOne |
| *DefaultPageSize: A4 |
| *PageSize A4/A4: "<</PageSize[595.20 841.68]>>setpagedevice" |
| *CloseUI: *PageSize |
| *OpenUI *PageRegion: PickOne |
| *DefaultPageRegion: A4 |
| *PageRegion A4/A4: "<</PageRegion[595.20 841.68]>>setpagedevice" |
| *CloseUI: *PageRegion |
| *DefaultImageableArea: A4 |
| *ImageableArea A4/A4: "8.40 8.40 586.80 833.28" |
| *DefaultPaperDimension: A4 |
| *PaperDimension A4/A4: "595.20 841.68" |
| )PPD"); |
| |
| // Constructs a CupsAddAutoConfiguredPrinterRequest from `name` and `uri`. |
| CupsAddAutoConfiguredPrinterRequest |
| ConstructCupsAddAutoConfiguredPrinterRequest(const std::string& name, |
| const std::string& uri) { |
| CupsAddAutoConfiguredPrinterRequest request; |
| request.set_name(name); |
| request.set_uri(uri); |
| return request; |
| } |
| |
| // Constructs a CupsAddManuallyConfiguredPrinterRequest from `name`, `uri` and |
| // `ppd_contents`. |
| CupsAddManuallyConfiguredPrinterRequest |
| ConstructCupsAddManuallyConfiguredPrinterRequest( |
| const std::string& name, |
| const std::string& uri, |
| const std::vector<uint8_t>& ppd_contents) { |
| CupsAddManuallyConfiguredPrinterRequest request; |
| request.set_name(name); |
| request.set_uri(uri); |
| request.set_ppd_contents( |
| std::string(ppd_contents.begin(), ppd_contents.end())); |
| return request; |
| } |
| |
| // Constructs a CupsRemovePrinterRequest from `name`. |
| CupsRemovePrinterRequest ConstructCupsRemovePrinterRequest( |
| const std::string& name) { |
| CupsRemovePrinterRequest request; |
| request.set_name(name); |
| return request; |
| } |
| |
| // Constructs a CupsRetrievePpdRequest from `name`. |
| CupsRetrievePpdRequest ConstructCupsRetrievePpdRequest( |
| const std::string& name) { |
| CupsRetrievePpdRequest request; |
| request.set_name(name); |
| return request; |
| } |
| |
| } // namespace |
| |
| class FakeLpTools : public LpTools { |
| public: |
| FakeLpTools() { CHECK(ppd_dir_.CreateUniqueTempDir()); } |
| |
| int Lpadmin(const std::vector<std::string>& arg_list, |
| const std::optional<std::string>& language, |
| const std::vector<uint8_t>* std_input) override { |
| return lpadmin_result_; |
| } |
| |
| // Return 1 if lpstat_output_ is empty, else populate output (if non-null) and |
| // return 0. |
| int Lpstat(const std::vector<std::string>& arg_list, |
| std::string* output) override { |
| if (lpstat_output_.empty()) { |
| return 1; |
| } |
| |
| if (output != nullptr) { |
| *output = lpstat_output_; |
| } |
| |
| return 0; |
| } |
| |
| int CupsTestPpd(const std::vector<uint8_t>&) const override { |
| return cupstestppd_result_; |
| } |
| |
| bool CupsUriHelper(const std::string& uri) const override { |
| return urihelper_result_; |
| } |
| |
| int RunCommand(const std::string& command, |
| const std::vector<std::string>& arg_list, |
| const std::vector<uint8_t>* std_input = nullptr, |
| std::string* out = nullptr) const override { |
| return runcommand_result_; |
| } |
| |
| // The following methods allow the user to setup the fake object to return the |
| // desired results. |
| |
| void SetLpstatOutput(const std::string& data) { lpstat_output_ = data; } |
| |
| void SetCupsTestPPDResult(int result) { cupstestppd_result_ = result; } |
| |
| void SetCupsUriHelperResult(bool result) { urihelper_result_ = result; } |
| |
| void SetRunCommandResult(int result) { runcommand_result_ = result; } |
| |
| void SetLpadminResult(int result) { lpadmin_result_ = result; } |
| |
| // Create some valid output for lpstat based on `printerName`. |
| void CreateValidLpstatOutput(const std::string& printerName) { |
| const std::string lpstatOutput = base::StringPrintf( |
| R"(printer %s is idle. |
| Form mounted: |
| Content types: any |
| Printer types: unknown |
| Description: %s |
| Alerts: none |
| Connection: direct |
| Interface: %s/%s.ppd |
| On fault: no alert |
| After fault: continue |
| Users allowed: |
| (all) |
| Forms allowed: |
| (none) |
| Banner required |
| Charset sets: |
| (none) |
| Default pitch: |
| Default page size: |
| Default port settings: |
| )", |
| printerName.c_str(), printerName.c_str(), |
| ppd_dir_.GetPath().value().c_str(), printerName.c_str()); |
| |
| SetLpstatOutput(lpstatOutput); |
| } |
| |
| private: |
| std::string lpstat_output_; |
| base::ScopedTempDir ppd_dir_; |
| int cupstestppd_result_{0}; |
| bool urihelper_result_{true}; |
| int runcommand_result_{0}; |
| int lpadmin_result_{0}; |
| }; |
| |
| TEST(CupsToolTest, RetrievePpd) { |
| // Test the case where everything works as expected. |
| base::test::SingleThreadTaskEnvironment task_environment; |
| |
| // Create a fake lp tools object and configure it so we know what results we |
| // should expect from CupsTool. |
| std::unique_ptr<FakeLpTools> lptools = std::make_unique<FakeLpTools>(); |
| |
| const std::string printerName("test-printer"); |
| lptools->CreateValidLpstatOutput(printerName); |
| |
| // Create our ppd string that will get returned by the executor. |
| const std::string ppdContents = "Test data in PPD file"; |
| |
| StrictMock<MockExecutor> mock_executor; |
| EXPECT_CALL(mock_executor, GetPpdFile(printerName + ".ppd", _)) |
| .WillOnce( |
| WithArg<1>(Invoke([&](mojom::Executor::GetPpdFileCallback callback) { |
| std::move(callback).Run(/*file_contents=*/ppdContents, |
| /*success=*/true); |
| }))); |
| |
| mojo::Remote<mojom::Executor> remote; |
| remote.Bind(mock_executor.pending_remote()); |
| CupsTool cupsTool(remote.get()); |
| cupsTool.SetLpToolsForTesting(std::move(lptools)); |
| |
| CupsRetrievePpdResponse response = |
| cupsTool.RetrievePpd(ConstructCupsRetrievePpdRequest(printerName)); |
| |
| EXPECT_EQ(ppdContents, response.ppd()); |
| } |
| |
| TEST(CupsToolTest, EmptyStringFromExecutor) { |
| // Test the case where the executor returns an empty string. |
| base::test::SingleThreadTaskEnvironment task_environment; |
| |
| std::unique_ptr<FakeLpTools> lptools = std::make_unique<FakeLpTools>(); |
| |
| const std::string printerName("test-printer"); |
| lptools->CreateValidLpstatOutput(printerName); |
| |
| // Create an empty ppd string that will get returned by the executor. |
| const std::string ppdContents(""); |
| |
| StrictMock<MockExecutor> mock_executor; |
| EXPECT_CALL(mock_executor, GetPpdFile(printerName + ".ppd", _)) |
| .WillOnce( |
| WithArg<1>(Invoke([&](mojom::Executor::GetPpdFileCallback callback) { |
| std::move(callback).Run(/*file_contents=*/ppdContents, |
| /*success=*/true); |
| }))); |
| |
| mojo::Remote<mojom::Executor> remote; |
| remote.Bind(mock_executor.pending_remote()); |
| CupsTool cupsTool(remote.get()); |
| cupsTool.SetLpToolsForTesting(std::move(lptools)); |
| CupsRetrievePpdResponse response = |
| cupsTool.RetrievePpd(ConstructCupsRetrievePpdRequest(printerName)); |
| |
| EXPECT_TRUE(response.ppd().empty()); |
| } |
| |
| TEST(CupsToolTest, ExecutorCallFails) { |
| // Test the case where lpstat works as expected, but the PPD file does not |
| // exist. |
| base::test::SingleThreadTaskEnvironment task_environment; |
| |
| std::unique_ptr<FakeLpTools> lptools = std::make_unique<FakeLpTools>(); |
| |
| const std::string printerName("test-printer"); |
| lptools->CreateValidLpstatOutput(printerName); |
| |
| StrictMock<MockExecutor> mock_executor; |
| EXPECT_CALL(mock_executor, GetPpdFile(printerName + ".ppd", _)) |
| .WillOnce( |
| WithArg<1>(Invoke([&](mojom::Executor::GetPpdFileCallback callback) { |
| std::move(callback).Run(/*file_contents=*/"", |
| /*success=*/false); |
| }))); |
| |
| mojo::Remote<mojom::Executor> remote; |
| remote.Bind(mock_executor.pending_remote()); |
| CupsTool cupsTool(remote.get()); |
| cupsTool.SetLpToolsForTesting(std::move(lptools)); |
| |
| CupsRetrievePpdResponse response = |
| cupsTool.RetrievePpd(ConstructCupsRetrievePpdRequest(printerName)); |
| |
| EXPECT_TRUE(response.ppd().empty()); |
| } |
| |
| TEST(CupsToolTest, LpstatError) { |
| // Test the case where there is an error running lpstat |
| base::test::SingleThreadTaskEnvironment task_environment; |
| |
| std::unique_ptr<FakeLpTools> lptools = std::make_unique<FakeLpTools>(); |
| |
| // Since we have not specified the lpstat output, our fake object will return |
| // an error from running lpstat. |
| |
| MockExecutor mock_executor; |
| mojo::Remote<mojom::Executor> remote; |
| remote.Bind(mock_executor.pending_remote()); |
| CupsTool cupsTool(remote.get()); |
| cupsTool.SetLpToolsForTesting(std::move(lptools)); |
| |
| CupsRetrievePpdResponse response = |
| cupsTool.RetrievePpd(ConstructCupsRetrievePpdRequest("printer")); |
| |
| EXPECT_TRUE(response.ppd().empty()); |
| } |
| |
| TEST(CupsToolTest, LpstatNoPrinter) { |
| // Test the case where lpstat runs but doesn't return the printer we are |
| // looking for. |
| base::test::SingleThreadTaskEnvironment task_environment; |
| |
| std::unique_ptr<FakeLpTools> lptools = std::make_unique<FakeLpTools>(); |
| |
| const std::string printerName("test-printer"); |
| lptools->SetLpstatOutput("lpstat data not containing our printer name"); |
| |
| MockExecutor mock_executor; |
| mojo::Remote<mojom::Executor> remote; |
| remote.Bind(mock_executor.pending_remote()); |
| CupsTool cupsTool(remote.get()); |
| cupsTool.SetLpToolsForTesting(std::move(lptools)); |
| |
| CupsRetrievePpdResponse response = |
| cupsTool.RetrievePpd(ConstructCupsRetrievePpdRequest(printerName)); |
| |
| EXPECT_TRUE(response.ppd().empty()); |
| } |
| |
| TEST(CupsToolTest, InvalidPPDTooSmall) { |
| base::test::SingleThreadTaskEnvironment task_environment; |
| |
| std::vector<uint8_t> empty_ppd; |
| |
| MockExecutor mock_executor; |
| mojo::Remote<mojom::Executor> remote; |
| remote.Bind(mock_executor.pending_remote()); |
| CupsTool cups(remote.get()); |
| CupsAddManuallyConfiguredPrinterResponse response = |
| cups.AddManuallyConfiguredPrinter( |
| ConstructCupsAddManuallyConfiguredPrinterRequest("test", "ipp://", |
| empty_ppd)); |
| EXPECT_EQ(response.result(), |
| AddPrinterResult::ADD_PRINTER_RESULT_CUPS_INVALID_PPD); |
| } |
| |
| TEST(CupsToolTest, InvalidPPDBadGzip) { |
| base::test::SingleThreadTaskEnvironment task_environment; |
| |
| // Make the PPD look like it's gzipped. |
| std::vector<uint8_t> bad_ppd(kMinimalPPDContent.begin(), |
| kMinimalPPDContent.end()); |
| bad_ppd[0] = 0x1f; |
| bad_ppd[1] = 0x8b; |
| |
| MockExecutor mock_executor; |
| mojo::Remote<mojom::Executor> remote; |
| remote.Bind(mock_executor.pending_remote()); |
| CupsTool cups(remote.get()); |
| CupsAddManuallyConfiguredPrinterResponse response = |
| cups.AddManuallyConfiguredPrinter( |
| ConstructCupsAddManuallyConfiguredPrinterRequest("test", "ipp://", |
| bad_ppd)); |
| EXPECT_EQ(response.result(), |
| AddPrinterResult::ADD_PRINTER_RESULT_CUPS_INVALID_PPD); |
| } |
| |
| TEST(CupsToolTest, InvalidPPDBadContents) { |
| base::test::SingleThreadTaskEnvironment task_environment; |
| |
| // Corrupt a valid PPD so it won't validate. |
| std::vector<uint8_t> bad_ppd(kMinimalPPDContent.begin(), |
| kMinimalPPDContent.end()); |
| bad_ppd[0] = 'X'; |
| bad_ppd[1] = 'Y'; |
| bad_ppd[2] = 'Z'; |
| |
| std::unique_ptr<FakeLpTools> lptools = std::make_unique<FakeLpTools>(); |
| lptools->SetCupsTestPPDResult(4); // Typical failure exit code. |
| |
| MockExecutor mock_executor; |
| mojo::Remote<mojom::Executor> remote; |
| remote.Bind(mock_executor.pending_remote()); |
| CupsTool cups(remote.get()); |
| cups.SetLpToolsForTesting(std::move(lptools)); |
| |
| CupsAddManuallyConfiguredPrinterResponse response = |
| cups.AddManuallyConfiguredPrinter( |
| ConstructCupsAddManuallyConfiguredPrinterRequest("test", "ipp://", |
| bad_ppd)); |
| EXPECT_EQ(response.result(), |
| AddPrinterResult::ADD_PRINTER_RESULT_CUPS_INVALID_PPD); |
| } |
| |
| TEST(CupsToolTest, ManualMissingURI) { |
| base::test::SingleThreadTaskEnvironment task_environment; |
| |
| std::vector<uint8_t> good_ppd(kMinimalPPDContent.begin(), |
| kMinimalPPDContent.end()); |
| |
| std::unique_ptr<FakeLpTools> lptools = std::make_unique<FakeLpTools>(); |
| lptools->SetCupsTestPPDResult(0); // Successful validation. |
| |
| MockExecutor mock_executor; |
| mojo::Remote<mojom::Executor> remote; |
| remote.Bind(mock_executor.pending_remote()); |
| CupsTool cups(remote.get()); |
| cups.SetLpToolsForTesting(std::move(lptools)); |
| |
| CupsAddManuallyConfiguredPrinterResponse response = |
| cups.AddManuallyConfiguredPrinter( |
| ConstructCupsAddManuallyConfiguredPrinterRequest("test", /*uri=*/"", |
| good_ppd)); |
| EXPECT_EQ(response.result(), |
| AddPrinterResult::ADD_PRINTER_RESULT_CUPS_BAD_URI); |
| } |
| |
| TEST(CupsToolTest, ManualMissingName) { |
| base::test::SingleThreadTaskEnvironment task_environment; |
| |
| std::vector<uint8_t> good_ppd(kMinimalPPDContent.begin(), |
| kMinimalPPDContent.end()); |
| |
| std::unique_ptr<FakeLpTools> lptools = std::make_unique<FakeLpTools>(); |
| lptools->SetCupsTestPPDResult(0); // Successful validation. |
| lptools->SetCupsUriHelperResult(true); // URI validated. |
| |
| MockExecutor mock_executor; |
| mojo::Remote<mojom::Executor> remote; |
| remote.Bind(mock_executor.pending_remote()); |
| CupsTool cups(remote.get()); |
| cups.SetLpToolsForTesting(std::move(lptools)); |
| |
| CupsAddManuallyConfiguredPrinterResponse response = |
| cups.AddManuallyConfiguredPrinter( |
| ConstructCupsAddManuallyConfiguredPrinterRequest( |
| /*name=*/"", "ipp://127.0.0.1:631/ipp/print", good_ppd)); |
| EXPECT_EQ(response.result(), AddPrinterResult::ADD_PRINTER_RESULT_CUPS_FATAL); |
| } |
| |
| TEST(CupsToolTest, ManualUnknownError) { |
| base::test::SingleThreadTaskEnvironment task_environment; |
| |
| std::vector<uint8_t> good_ppd(kMinimalPPDContent.begin(), |
| kMinimalPPDContent.end()); |
| |
| std::unique_ptr<FakeLpTools> lptools = std::make_unique<FakeLpTools>(); |
| lptools->SetCupsTestPPDResult(0); // Successful validation. |
| lptools->SetCupsUriHelperResult(true); // URI validated. |
| lptools->SetLpadminResult(1); |
| |
| MockExecutor mock_executor; |
| mojo::Remote<mojom::Executor> remote; |
| remote.Bind(mock_executor.pending_remote()); |
| CupsTool cups(remote.get()); |
| cups.SetLpToolsForTesting(std::move(lptools)); |
| |
| CupsAddManuallyConfiguredPrinterResponse response = |
| cups.AddManuallyConfiguredPrinter( |
| ConstructCupsAddManuallyConfiguredPrinterRequest( |
| "test", "ipp://127.0.0.1:631/ipp/print", good_ppd)); |
| EXPECT_EQ(response.result(), |
| AddPrinterResult::ADD_PRINTER_RESULT_CUPS_LPADMIN_FAILURE); |
| } |
| |
| TEST(CupsToolTest, ManualInvalidPpdDuringLpadmin) { |
| base::test::SingleThreadTaskEnvironment task_environment; |
| |
| std::vector<uint8_t> good_ppd(kMinimalPPDContent.begin(), |
| kMinimalPPDContent.end()); |
| |
| std::unique_ptr<FakeLpTools> lptools = std::make_unique<FakeLpTools>(); |
| lptools->SetCupsTestPPDResult(0); // Successful validation. |
| lptools->SetCupsUriHelperResult(true); // URI validated. |
| lptools->SetLpadminResult(5); |
| |
| MockExecutor mock_executor; |
| mojo::Remote<mojom::Executor> remote; |
| remote.Bind(mock_executor.pending_remote()); |
| CupsTool cups(remote.get()); |
| cups.SetLpToolsForTesting(std::move(lptools)); |
| |
| CupsAddManuallyConfiguredPrinterResponse response = |
| cups.AddManuallyConfiguredPrinter( |
| ConstructCupsAddManuallyConfiguredPrinterRequest( |
| "test", "ipp://127.0.0.1:631/ipp/print", good_ppd)); |
| EXPECT_EQ(response.result(), |
| AddPrinterResult::ADD_PRINTER_RESULT_CUPS_INVALID_PPD); |
| } |
| |
| TEST(CupsToolTest, ManualNotAutoConf) { |
| base::test::SingleThreadTaskEnvironment task_environment; |
| |
| std::vector<uint8_t> good_ppd(kMinimalPPDContent.begin(), |
| kMinimalPPDContent.end()); |
| |
| std::unique_ptr<FakeLpTools> lptools = std::make_unique<FakeLpTools>(); |
| lptools->SetCupsTestPPDResult(0); // Successful validation. |
| lptools->SetCupsUriHelperResult(true); // URI validated. |
| lptools->SetLpadminResult(9); |
| |
| MockExecutor mock_executor; |
| mojo::Remote<mojom::Executor> remote; |
| remote.Bind(mock_executor.pending_remote()); |
| CupsTool cups(remote.get()); |
| cups.SetLpToolsForTesting(std::move(lptools)); |
| |
| CupsAddManuallyConfiguredPrinterResponse response = |
| cups.AddManuallyConfiguredPrinter( |
| ConstructCupsAddManuallyConfiguredPrinterRequest( |
| "test", "ipp://127.0.0.1:631/ipp/print", good_ppd)); |
| EXPECT_EQ(response.result(), AddPrinterResult::ADD_PRINTER_RESULT_CUPS_FATAL); |
| } |
| |
| TEST(CupsToolTest, ManualUnhandledError) { |
| base::test::SingleThreadTaskEnvironment task_environment; |
| |
| std::vector<uint8_t> good_ppd(kMinimalPPDContent.begin(), |
| kMinimalPPDContent.end()); |
| |
| std::unique_ptr<FakeLpTools> lptools = std::make_unique<FakeLpTools>(); |
| lptools->SetCupsTestPPDResult(0); // Successful validation. |
| lptools->SetCupsUriHelperResult(true); // URI validated. |
| lptools->SetLpadminResult(100); // Error code without CUPS equivalent. |
| |
| MockExecutor mock_executor; |
| mojo::Remote<mojom::Executor> remote; |
| remote.Bind(mock_executor.pending_remote()); |
| CupsTool cups(remote.get()); |
| cups.SetLpToolsForTesting(std::move(lptools)); |
| |
| CupsAddManuallyConfiguredPrinterResponse response = |
| cups.AddManuallyConfiguredPrinter( |
| ConstructCupsAddManuallyConfiguredPrinterRequest( |
| "test", "ipp://127.0.0.1:631/ipp/print", good_ppd)); |
| EXPECT_EQ(response.result(), AddPrinterResult::ADD_PRINTER_RESULT_CUPS_FATAL); |
| } |
| |
| TEST(CupsToolTest, AutoMissingURI) { |
| base::test::SingleThreadTaskEnvironment task_environment; |
| |
| MockExecutor mock_executor; |
| mojo::Remote<mojom::Executor> remote; |
| remote.Bind(mock_executor.pending_remote()); |
| CupsTool cups(remote.get()); |
| CupsAddAutoConfiguredPrinterResponse response = cups.AddAutoConfiguredPrinter( |
| ConstructCupsAddAutoConfiguredPrinterRequest("test", /*uri=*/"")); |
| EXPECT_EQ(response.result(), AddPrinterResult::ADD_PRINTER_RESULT_CUPS_FATAL); |
| } |
| |
| TEST(CupsToolTest, AutoMissingName) { |
| base::test::SingleThreadTaskEnvironment task_environment; |
| |
| std::unique_ptr<FakeLpTools> lptools = std::make_unique<FakeLpTools>(); |
| lptools->SetCupsUriHelperResult(true); // URI validated. |
| |
| MockExecutor mock_executor; |
| mojo::Remote<mojom::Executor> remote; |
| remote.Bind(mock_executor.pending_remote()); |
| CupsTool cups(remote.get()); |
| cups.SetLpToolsForTesting(std::move(lptools)); |
| |
| CupsAddAutoConfiguredPrinterResponse response = cups.AddAutoConfiguredPrinter( |
| ConstructCupsAddAutoConfiguredPrinterRequest( |
| /*name=*/"", "ipp://127.0.0.1:631/ipp/print")); |
| EXPECT_EQ(response.result(), AddPrinterResult::ADD_PRINTER_RESULT_CUPS_FATAL); |
| } |
| |
| TEST(CupsToolTest, AutoUnreasonableUri) { |
| base::test::SingleThreadTaskEnvironment task_environment; |
| |
| std::unique_ptr<FakeLpTools> lptools = std::make_unique<FakeLpTools>(); |
| lptools->SetCupsUriHelperResult(false); // Unreasonable URI. |
| |
| MockExecutor mock_executor; |
| mojo::Remote<mojom::Executor> remote; |
| remote.Bind(mock_executor.pending_remote()); |
| CupsTool cups(remote.get()); |
| cups.SetLpToolsForTesting(std::move(lptools)); |
| |
| CupsAddAutoConfiguredPrinterResponse response = cups.AddAutoConfiguredPrinter( |
| ConstructCupsAddAutoConfiguredPrinterRequest( |
| /*name=*/"", "ipp://127.0.0.1:631/ipp/print")); |
| EXPECT_EQ(response.result(), |
| AddPrinterResult::ADD_PRINTER_RESULT_CUPS_BAD_URI); |
| } |
| |
| TEST(CupsToolTest, AddAutoConfiguredPrinter) { |
| base::test::SingleThreadTaskEnvironment task_environment; |
| |
| std::unique_ptr<FakeLpTools> lptools = std::make_unique<FakeLpTools>(); |
| lptools->SetCupsUriHelperResult(true); // URI validated. |
| |
| MockExecutor mock_executor; |
| mojo::Remote<mojom::Executor> remote; |
| remote.Bind(mock_executor.pending_remote()); |
| CupsTool cups(remote.get()); |
| cups.SetLpToolsForTesting(std::move(lptools)); |
| |
| CupsAddAutoConfiguredPrinterResponse response = cups.AddAutoConfiguredPrinter( |
| ConstructCupsAddAutoConfiguredPrinterRequest( |
| "test", "ipp://127.0.0.1:631/ipp/print")); |
| EXPECT_EQ(response.result(), AddPrinterResult::ADD_PRINTER_RESULT_SUCCESS); |
| } |
| |
| TEST(CupsToolTest, AutoUnknownError) { |
| base::test::SingleThreadTaskEnvironment task_environment; |
| |
| std::unique_ptr<FakeLpTools> lptools = std::make_unique<FakeLpTools>(); |
| lptools->SetCupsUriHelperResult(true); // URI validated. |
| lptools->SetLpadminResult(1); |
| |
| MockExecutor mock_executor; |
| mojo::Remote<mojom::Executor> remote; |
| remote.Bind(mock_executor.pending_remote()); |
| CupsTool cups(remote.get()); |
| cups.SetLpToolsForTesting(std::move(lptools)); |
| |
| CupsAddAutoConfiguredPrinterResponse response = cups.AddAutoConfiguredPrinter( |
| ConstructCupsAddAutoConfiguredPrinterRequest( |
| "test", "ipp://127.0.0.1:631/ipp/print")); |
| EXPECT_EQ(response.result(), |
| AddPrinterResult::ADD_PRINTER_RESULT_CUPS_AUTOCONF_FAILURE); |
| } |
| |
| TEST(CupsToolTest, AutoFatalError) { |
| base::test::SingleThreadTaskEnvironment task_environment; |
| |
| std::unique_ptr<FakeLpTools> lptools = std::make_unique<FakeLpTools>(); |
| lptools->SetCupsUriHelperResult(true); // URI validated. |
| lptools->SetLpadminResult(2); |
| |
| MockExecutor mock_executor; |
| mojo::Remote<mojom::Executor> remote; |
| remote.Bind(mock_executor.pending_remote()); |
| CupsTool cups(remote.get()); |
| cups.SetLpToolsForTesting(std::move(lptools)); |
| |
| CupsAddAutoConfiguredPrinterResponse response = cups.AddAutoConfiguredPrinter( |
| ConstructCupsAddAutoConfiguredPrinterRequest( |
| "test", "ipp://127.0.0.1:631/ipp/print")); |
| EXPECT_EQ(response.result(), AddPrinterResult::ADD_PRINTER_RESULT_CUPS_FATAL); |
| } |
| |
| TEST(CupsToolTest, AutoIoError) { |
| base::test::SingleThreadTaskEnvironment task_environment; |
| |
| std::unique_ptr<FakeLpTools> lptools = std::make_unique<FakeLpTools>(); |
| lptools->SetCupsUriHelperResult(true); // URI validated. |
| lptools->SetLpadminResult(3); |
| |
| MockExecutor mock_executor; |
| mojo::Remote<mojom::Executor> remote; |
| remote.Bind(mock_executor.pending_remote()); |
| CupsTool cups(remote.get()); |
| cups.SetLpToolsForTesting(std::move(lptools)); |
| |
| CupsAddAutoConfiguredPrinterResponse response = cups.AddAutoConfiguredPrinter( |
| ConstructCupsAddAutoConfiguredPrinterRequest( |
| "test", "ipp://127.0.0.1:631/ipp/print")); |
| EXPECT_EQ(response.result(), |
| AddPrinterResult::ADD_PRINTER_RESULT_CUPS_IO_ERROR); |
| } |
| |
| TEST(CupsToolTest, AutoMemoryAllocError) { |
| base::test::SingleThreadTaskEnvironment task_environment; |
| |
| std::unique_ptr<FakeLpTools> lptools = std::make_unique<FakeLpTools>(); |
| lptools->SetCupsUriHelperResult(true); // URI validated. |
| lptools->SetLpadminResult(4); |
| |
| MockExecutor mock_executor; |
| mojo::Remote<mojom::Executor> remote; |
| remote.Bind(mock_executor.pending_remote()); |
| CupsTool cups(remote.get()); |
| cups.SetLpToolsForTesting(std::move(lptools)); |
| |
| CupsAddAutoConfiguredPrinterResponse response = cups.AddAutoConfiguredPrinter( |
| ConstructCupsAddAutoConfiguredPrinterRequest( |
| "test", "ipp://127.0.0.1:631/ipp/print")); |
| EXPECT_EQ(response.result(), |
| AddPrinterResult::ADD_PRINTER_RESULT_CUPS_MEMORY_ALLOC_ERROR); |
| } |
| |
| TEST(CupsToolTest, AutoInvalidPpd) { |
| base::test::SingleThreadTaskEnvironment task_environment; |
| |
| std::unique_ptr<FakeLpTools> lptools = std::make_unique<FakeLpTools>(); |
| lptools->SetCupsUriHelperResult(true); // URI validated. |
| lptools->SetLpadminResult(5); |
| |
| MockExecutor mock_executor; |
| mojo::Remote<mojom::Executor> remote; |
| remote.Bind(mock_executor.pending_remote()); |
| CupsTool cups(remote.get()); |
| cups.SetLpToolsForTesting(std::move(lptools)); |
| |
| CupsAddAutoConfiguredPrinterResponse response = cups.AddAutoConfiguredPrinter( |
| ConstructCupsAddAutoConfiguredPrinterRequest( |
| "test", "ipp://127.0.0.1:631/ipp/print")); |
| EXPECT_EQ(response.result(), AddPrinterResult::ADD_PRINTER_RESULT_CUPS_FATAL); |
| } |
| |
| TEST(CupsToolTest, AutoServerUnreachable) { |
| base::test::SingleThreadTaskEnvironment task_environment; |
| |
| std::unique_ptr<FakeLpTools> lptools = std::make_unique<FakeLpTools>(); |
| lptools->SetCupsUriHelperResult(true); // URI validated. |
| lptools->SetLpadminResult(6); |
| |
| MockExecutor mock_executor; |
| mojo::Remote<mojom::Executor> remote; |
| remote.Bind(mock_executor.pending_remote()); |
| CupsTool cups(remote.get()); |
| cups.SetLpToolsForTesting(std::move(lptools)); |
| |
| CupsAddAutoConfiguredPrinterResponse response = cups.AddAutoConfiguredPrinter( |
| ConstructCupsAddAutoConfiguredPrinterRequest( |
| "test", "ipp://127.0.0.1:631/ipp/print")); |
| EXPECT_EQ(response.result(), AddPrinterResult::ADD_PRINTER_RESULT_CUPS_FATAL); |
| } |
| |
| TEST(CupsToolTest, AutoPrinterUnreachable) { |
| base::test::SingleThreadTaskEnvironment task_environment; |
| |
| std::unique_ptr<FakeLpTools> lptools = std::make_unique<FakeLpTools>(); |
| lptools->SetCupsUriHelperResult(true); // URI validated. |
| lptools->SetLpadminResult(7); |
| |
| MockExecutor mock_executor; |
| mojo::Remote<mojom::Executor> remote; |
| remote.Bind(mock_executor.pending_remote()); |
| CupsTool cups(remote.get()); |
| cups.SetLpToolsForTesting(std::move(lptools)); |
| |
| CupsAddAutoConfiguredPrinterResponse response = cups.AddAutoConfiguredPrinter( |
| ConstructCupsAddAutoConfiguredPrinterRequest( |
| "test", "ipp://127.0.0.1:631/ipp/print")); |
| EXPECT_EQ(response.result(), |
| AddPrinterResult::ADD_PRINTER_RESULT_CUPS_PRINTER_UNREACHABLE); |
| } |
| |
| TEST(CupsToolTest, AutoPrinterWrongResponse) { |
| base::test::SingleThreadTaskEnvironment task_environment; |
| |
| std::unique_ptr<FakeLpTools> lptools = std::make_unique<FakeLpTools>(); |
| lptools->SetCupsUriHelperResult(true); // URI validated. |
| lptools->SetLpadminResult(8); |
| |
| MockExecutor mock_executor; |
| mojo::Remote<mojom::Executor> remote; |
| remote.Bind(mock_executor.pending_remote()); |
| CupsTool cups(remote.get()); |
| cups.SetLpToolsForTesting(std::move(lptools)); |
| |
| CupsAddAutoConfiguredPrinterResponse response = cups.AddAutoConfiguredPrinter( |
| ConstructCupsAddAutoConfiguredPrinterRequest( |
| "test", "ipp://127.0.0.1:631/ipp/print")); |
| EXPECT_EQ(response.result(), |
| AddPrinterResult::ADD_PRINTER_RESULT_CUPS_PRINTER_WRONG_RESPONSE); |
| } |
| |
| TEST(CupsToolTest, AutoPrinterNotAutoConf) { |
| base::test::SingleThreadTaskEnvironment task_environment; |
| |
| std::unique_ptr<FakeLpTools> lptools = std::make_unique<FakeLpTools>(); |
| lptools->SetCupsUriHelperResult(true); // URI validated. |
| lptools->SetLpadminResult(9); |
| |
| MockExecutor mock_executor; |
| mojo::Remote<mojom::Executor> remote; |
| remote.Bind(mock_executor.pending_remote()); |
| CupsTool cups(remote.get()); |
| cups.SetLpToolsForTesting(std::move(lptools)); |
| |
| CupsAddAutoConfiguredPrinterResponse response = cups.AddAutoConfiguredPrinter( |
| ConstructCupsAddAutoConfiguredPrinterRequest( |
| "test", "ipp://127.0.0.1:631/ipp/print")); |
| EXPECT_EQ(response.result(), |
| AddPrinterResult::ADD_PRINTER_RESULT_CUPS_PRINTER_NOT_AUTOCONF); |
| } |
| |
| TEST(CupsToolTest, FoomaticPPD) { |
| base::test::SingleThreadTaskEnvironment task_environment; |
| |
| // Make the PPD look like it has a foomatic-rip filter. |
| constexpr std::string_view kFoomaticLine( |
| R"foo(*cupsFilter: "application/vnd.cups-pdf 0 foomatic-rip")foo"); |
| std::vector<uint8_t> foomatic_ppd(kMinimalPPDContent.begin(), |
| kMinimalPPDContent.end()); |
| std::copy(kFoomaticLine.begin(), kFoomaticLine.end(), |
| std::back_inserter(foomatic_ppd)); |
| |
| std::unique_ptr<FakeLpTools> lptools = std::make_unique<FakeLpTools>(); |
| lptools->SetRunCommandResult(0); |
| |
| MockExecutor mock_executor; |
| mojo::Remote<mojom::Executor> remote; |
| remote.Bind(mock_executor.pending_remote()); |
| CupsTool cups(remote.get()); |
| cups.SetLpToolsForTesting(std::move(lptools)); |
| |
| CupsAddManuallyConfiguredPrinterResponse response = |
| cups.AddManuallyConfiguredPrinter( |
| ConstructCupsAddManuallyConfiguredPrinterRequest("test", "ipp://", |
| foomatic_ppd)); |
| EXPECT_EQ(response.result(), AddPrinterResult::ADD_PRINTER_RESULT_SUCCESS); |
| } |
| |
| TEST(CupsToolTest, FoomaticError) { |
| base::test::SingleThreadTaskEnvironment task_environment; |
| |
| // Make the PPD look like it has a foomatic-rip filter. |
| constexpr std::string_view kFoomaticLine( |
| R"foo(*cupsFilter: "application/vnd.cups-pdf 0 foomatic-rip")foo"); |
| std::vector<uint8_t> foomatic_ppd(kMinimalPPDContent.begin(), |
| kMinimalPPDContent.end()); |
| std::copy(kFoomaticLine.begin(), kFoomaticLine.end(), |
| std::back_inserter(foomatic_ppd)); |
| |
| std::unique_ptr<FakeLpTools> lptools = std::make_unique<FakeLpTools>(); |
| lptools->SetRunCommandResult(-1); |
| |
| MockExecutor mock_executor; |
| mojo::Remote<mojom::Executor> remote; |
| remote.Bind(mock_executor.pending_remote()); |
| CupsTool cups(remote.get()); |
| cups.SetLpToolsForTesting(std::move(lptools)); |
| CupsAddManuallyConfiguredPrinterResponse response = |
| cups.AddManuallyConfiguredPrinter( |
| ConstructCupsAddManuallyConfiguredPrinterRequest("test", "ipp://", |
| foomatic_ppd)); |
| EXPECT_EQ(response.result(), |
| AddPrinterResult::ADD_PRINTER_RESULT_CUPS_INVALID_PPD); |
| } |
| |
| TEST(CupsToolTest, RemovePrinter) { |
| base::test::SingleThreadTaskEnvironment task_environment; |
| |
| std::unique_ptr<FakeLpTools> lptools = std::make_unique<FakeLpTools>(); |
| |
| MockExecutor mock_executor; |
| mojo::Remote<mojom::Executor> remote; |
| remote.Bind(mock_executor.pending_remote()); |
| CupsTool cups(remote.get()); |
| cups.SetLpToolsForTesting(std::move(lptools)); |
| |
| // Our FakeLpTools always returns 0 for lpadmin calls, so we expect this to |
| // pass. |
| CupsRemovePrinterResponse response = |
| cups.RemovePrinter(ConstructCupsRemovePrinterRequest("printer-name")); |
| EXPECT_EQ(response.result(), true); |
| } |
| |
| } // namespace printscanmgr |