blob: 657cb28d6901735ac3accddfb43c72c2c0c50fd2 [file] [log] [blame]
// 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 <stdint.h>
#include <algorithm>
#include <memory>
#include <string>
#include <utility>
#include "base/bind.h"
#include "base/callback.h"
#include "base/check_op.h"
#include "base/memory/scoped_refptr.h"
#include "base/optional.h"
#include "base/run_loop.h"
#include "chrome/browser/printing/print_backend_service_test_impl.h"
#include "chrome/services/printing/public/mojom/print_backend_service.mojom.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "content/public/test/browser_test.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "printing/backend/print_backend.h"
#include "printing/backend/test_print_backend.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace printing {
using ::testing::UnorderedElementsAreArray;
namespace {
constexpr char kDefaultPrinterName[] = "default-test-printer";
constexpr char kAnotherPrinterName[] = "another-test-printer";
constexpr char kInvalidPrinterName[] = "invalid-test-printer";
const PrinterBasicInfo kDefaultPrinterInfo(
/*printer_name=*/kDefaultPrinterName,
/*display_name=*/"default test printer",
/*printer_description=*/"Default printer for testing.",
/*printer_status=*/0,
/*is_default=*/true,
/*options=*/{});
const PrinterBasicInfo kAnotherPrinterInfo(
/*printer_name=*/kAnotherPrinterName,
/*display_name=*/"another test printer",
/*printer_description=*/"Another printer for testing.",
/*printer_status=*/5,
/*is_default=*/false,
/*options=*/{});
constexpr int32_t kCopiesMax = 123;
} // namespace
class PrintBackendBrowserTest : public InProcessBrowserTest {
public:
PrintBackendBrowserTest() = default;
~PrintBackendBrowserTest() override = default;
void LaunchUninitialized() {
print_backend_service_ =
PrintBackendServiceTestImpl::LaunchUninitialized(remote_);
}
// Initialize and load the backend service with some test print drivers.
void LaunchService() {
print_backend_service_ = PrintBackendServiceTestImpl::LaunchForTesting(
remote_, test_print_backend_);
}
// Load the test backend with a default printer driver.
void AddDefaultPrinter() {
// Only explicitly specify capabilities that we pay attention to in the
// tests.
auto default_caps = std::make_unique<PrinterSemanticCapsAndDefaults>();
default_caps->copies_max = kCopiesMax;
test_print_backend_->AddValidPrinter(
kDefaultPrinterName, std::move(default_caps),
std::make_unique<PrinterBasicInfo>(kDefaultPrinterInfo));
}
// Load the test backend with another (non-default) printer.
void AddAnotherPrinter() {
test_print_backend_->AddValidPrinter(
kAnotherPrinterName, std::make_unique<PrinterSemanticCapsAndDefaults>(),
std::make_unique<PrinterBasicInfo>(kAnotherPrinterInfo));
}
// Public callbacks used by tests.
void OnDidEnumeratePrinters(base::Optional<PrinterList>* capture_printer_list,
const base::Optional<PrinterList>& printer_list) {
*capture_printer_list = printer_list;
CheckForQuit();
}
void OnDidGetDefaultPrinterName(
base::Optional<std::string>* capture_printer_name,
const base::Optional<std::string>& printer_name) {
*capture_printer_name = printer_name;
CheckForQuit();
}
void OnDidGetPrinterSemanticCapsAndDefaults(
base::Optional<PrinterSemanticCapsAndDefaults>* capture_printer_caps,
const base::Optional<PrinterSemanticCapsAndDefaults>& printer_caps) {
*capture_printer_caps = printer_caps;
CheckForQuit();
}
void OnDidFetchCapabilities(
base::Optional<PrinterBasicInfo>* capture_printer_info,
base::Optional<PrinterSemanticCapsAndDefaults::Papers>*
capture_user_defined_papers,
base::Optional<PrinterSemanticCapsAndDefaults>* capture_printer_caps,
const base::Optional<PrinterBasicInfo>& printer_info,
const base::Optional<PrinterSemanticCapsAndDefaults::Papers>&
user_defined_papers,
const base::Optional<PrinterSemanticCapsAndDefaults>& printer_caps) {
*capture_printer_info = printer_info;
*capture_user_defined_papers = user_defined_papers;
*capture_printer_caps = printer_caps;
CheckForQuit();
}
// The following are helper functions for having a wait loop in the test and
// exit when expected messages are received. Expect to only have to wait for
// one message.
void WaitUntilCallbackReceived() {
// If callback happened before getting here, then no need to wait.
if (!received_message_) {
base::RunLoop run_loop;
quit_callback_ = run_loop.QuitClosure();
run_loop.Run();
}
// Reset for possible subsequent test.
received_message_ = false;
}
void CheckForQuit() {
received_message_ = true;
if (quit_callback_)
std::move(quit_callback_).Run();
}
// Get the print backend service being tested.
mojom::PrintBackendService* GetPrintBackendService() const {
return print_backend_service_.get();
}
private:
bool received_message_ = false;
base::OnceClosure quit_callback_;
mojo::Remote<mojom::PrintBackendService> remote_;
scoped_refptr<TestPrintBackend> test_print_backend_ =
base::MakeRefCounted<TestPrintBackend>();
std::unique_ptr<PrintBackendServiceTestImpl> print_backend_service_;
};
// A print backend service requires initialization prior to being used for a
// query/command. Verify that a query fails if one tries to use a new service
// without having performed initialization.
IN_PROC_BROWSER_TEST_F(PrintBackendBrowserTest, FailWithoutInit) {
// Launch the service, but without initializing to desired locale.
LaunchUninitialized();
base::Optional<std::string> default_printer_name;
base::Optional<PrinterSemanticCapsAndDefaults> printer_caps;
// Safe to use base::Unretained(this) since waiting locally on the callback
// forces a shorter lifetime than `this`.
GetPrintBackendService()->GetDefaultPrinterName(
base::BindOnce(&PrintBackendBrowserTest::OnDidGetDefaultPrinterName,
base::Unretained(this), &default_printer_name));
WaitUntilCallbackReceived();
EXPECT_FALSE(default_printer_name.has_value());
GetPrintBackendService()->GetPrinterSemanticCapsAndDefaults(
kDefaultPrinterName,
base::BindOnce(
&PrintBackendBrowserTest::OnDidGetPrinterSemanticCapsAndDefaults,
base::Unretained(this), &printer_caps));
WaitUntilCallbackReceived();
EXPECT_FALSE(printer_caps.has_value());
}
IN_PROC_BROWSER_TEST_F(PrintBackendBrowserTest, EnumeratePrinters) {
LaunchService();
AddDefaultPrinter();
AddAnotherPrinter();
const PrinterList kPrinterListExpected = {kDefaultPrinterInfo,
kAnotherPrinterInfo};
// Safe to use base::Unretained(this) since waiting locally on the callback
// forces a shorter lifetime than `this`.
base::Optional<PrinterList> printer_list;
GetPrintBackendService()->EnumeratePrinters(
base::BindOnce(&PrintBackendBrowserTest::OnDidEnumeratePrinters,
base::Unretained(this), &printer_list));
WaitUntilCallbackReceived();
ASSERT_TRUE(printer_list.has_value());
EXPECT_THAT(printer_list.value(),
UnorderedElementsAreArray(kPrinterListExpected));
}
IN_PROC_BROWSER_TEST_F(PrintBackendBrowserTest, GetDefaultPrinterName) {
LaunchService();
AddDefaultPrinter();
base::Optional<std::string> default_printer_name;
// Safe to use base::Unretained(this) since waiting locally on the callback
// forces a shorter lifetime than `this`.
GetPrintBackendService()->GetDefaultPrinterName(
base::BindOnce(&PrintBackendBrowserTest::OnDidGetDefaultPrinterName,
base::Unretained(this), &default_printer_name));
WaitUntilCallbackReceived();
ASSERT_TRUE(default_printer_name.has_value());
EXPECT_EQ(default_printer_name.value(), kDefaultPrinterName);
}
IN_PROC_BROWSER_TEST_F(PrintBackendBrowserTest,
GetPrinterSemanticCapsAndDefaults) {
LaunchService();
AddDefaultPrinter();
base::Optional<PrinterSemanticCapsAndDefaults> printer_caps;
// Safe to use base::Unretained(this) since waiting locally on the callback
// forces a shorter lifetime than `this`.
GetPrintBackendService()->GetPrinterSemanticCapsAndDefaults(
kDefaultPrinterName,
base::BindOnce(
&PrintBackendBrowserTest::OnDidGetPrinterSemanticCapsAndDefaults,
base::Unretained(this), &printer_caps));
WaitUntilCallbackReceived();
ASSERT_TRUE(printer_caps.has_value());
EXPECT_EQ(printer_caps.value().copies_max, kCopiesMax);
// Requesting for an invalid printer should not return capabilities.
GetPrintBackendService()->GetPrinterSemanticCapsAndDefaults(
kInvalidPrinterName,
base::BindOnce(
&PrintBackendBrowserTest::OnDidGetPrinterSemanticCapsAndDefaults,
base::Unretained(this), &printer_caps));
WaitUntilCallbackReceived();
EXPECT_FALSE(printer_caps.has_value());
}
IN_PROC_BROWSER_TEST_F(PrintBackendBrowserTest, FetchCapabilities) {
LaunchService();
AddDefaultPrinter();
base::Optional<PrinterBasicInfo> printer_info;
base::Optional<PrinterSemanticCapsAndDefaults::Papers> user_defined_papers;
base::Optional<PrinterSemanticCapsAndDefaults> printer_caps;
// Safe to use base::Unretained(this) since waiting locally on the callback
// forces a shorter lifetime than `this`.
GetPrintBackendService()->FetchCapabilities(
kDefaultPrinterName,
base::BindOnce(&PrintBackendBrowserTest::OnDidFetchCapabilities,
base::Unretained(this), &printer_info,
&user_defined_papers, &printer_caps));
WaitUntilCallbackReceived();
ASSERT_TRUE(printer_info.has_value());
EXPECT_TRUE(user_defined_papers.has_value());
ASSERT_TRUE(printer_caps.has_value());
EXPECT_TRUE(printer_info.value().is_default);
EXPECT_EQ(printer_caps.value().copies_max, kCopiesMax);
// Requesting for an invalid printer should not return capabilities.
GetPrintBackendService()->FetchCapabilities(
kInvalidPrinterName,
base::BindOnce(&PrintBackendBrowserTest::OnDidFetchCapabilities,
base::Unretained(this), &printer_info,
&user_defined_papers, &printer_caps));
WaitUntilCallbackReceived();
EXPECT_FALSE(printer_info.has_value());
EXPECT_FALSE(user_defined_papers.has_value());
EXPECT_FALSE(printer_caps.has_value());
}
} // namespace printing