#include "printing/backend/cups_ipp_helper.h"
#include <cups/cups.h>
#include <map>
#include <memory>
#include <string_view>
#include "base/memory/raw_ptr.h"
#include "base/notreached.h"
#include "base/test/metrics/histogram_tester.h"
#include "build/build_config.h"
#include "printing/backend/cups_ipp_constants.h"
#include "printing/backend/mock_cups_printer.h"
#include "printing/backend/print_backend_utils.h"
#include "printing/mojom/print.mojom.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace printing {
Pointwise;
UnorderedPointwise;
MATCHER(AdvancedCapabilityName, "") { … }
MATCHER(EqualsMediaColEntry, "") { … }
class MockCupsPrinterWithMarginsAndAttributes : public MockCupsPrinter { … };
class PrintBackendCupsIppHelperTest : public ::testing::Test { … };
ipp_attribute_t* MakeInteger(ipp_t* ipp, int value) { … }
ipp_attribute_t* MakeIntCollection(ipp_t* ipp, const std::vector<int>& values) { … }
ipp_attribute_t* MakeRange(ipp_t* ipp, int lower_bound, int upper_bound) { … }
ipp_attribute_t* MakeString(ipp_t* ipp, const char* value) { … }
ipp_attribute_t* MakeStringCollection(ipp_t* ipp,
const std::vector<const char*>& strings) { … }
struct media_info { … };
bool MediaColDbEntryEquals(ipp_t* db_entry, media_info info) { … }
std::vector<ipp_t*> GetMediaColEntries(ipp_attribute_t* media_col_db) { … }
ScopedIppPtr MakeMediaCol(const media_info& info) { … }
ipp_attribute_t* MakeMediaColDefault(ipp_t* ipp, const media_info& info) { … }
ipp_attribute_t* MakeMediaColDatabase(ipp_t* ipp,
const std::vector<media_info>& media) { … }
TEST_F(PrintBackendCupsIppHelperTest, DefaultPaper) { … }
TEST_F(PrintBackendCupsIppHelperTest, CopiesCapable) { … }
TEST_F(PrintBackendCupsIppHelperTest, CopiesNotCapable) { … }
TEST_F(PrintBackendCupsIppHelperTest, ColorPrinter) { … }
TEST_F(PrintBackendCupsIppHelperTest, BWPrinter) { … }
TEST_F(PrintBackendCupsIppHelperTest, DuplexSupported) { … }
TEST_F(PrintBackendCupsIppHelperTest, DuplexNotSupported) { … }
TEST_F(PrintBackendCupsIppHelperTest, MediaTypes) { … }
TEST_F(PrintBackendCupsIppHelperTest, DefaultMediaTypeNotSupported) { … }
TEST_F(PrintBackendCupsIppHelperTest, A4PaperSupported) { … }
#if BUILDFLAG(IS_MAC)
TEST_F(PrintBackendCupsIppHelperTest, NearA4PaperDetected) {
printer_->SetMediaColDatabase(
MakeMediaColDatabase(ipp_, {{20990, 29704, 10, 10, 10, 10, {}}}));
PrinterSemanticCapsAndDefaults caps;
CapsAndDefaultsFromPrinter(*printer_, &caps);
ASSERT_EQ(1U, caps.papers.size());
PrinterSemanticCapsAndDefaults::Paper paper = caps.papers[0];
EXPECT_EQ(210000, paper.size_um().width());
EXPECT_EQ(297000, paper.size_um().height());
}
TEST_F(PrintBackendCupsIppHelperTest, NonStandardPaperUnchanged) {
printer_->SetMediaColDatabase(
MakeMediaColDatabase(ipp_, {{20800, 29500, 10, 10, 10, 10, {}}}));
PrinterSemanticCapsAndDefaults caps;
CapsAndDefaultsFromPrinter(*printer_, &caps);
ASSERT_EQ(1U, caps.papers.size());
PrinterSemanticCapsAndDefaults::Paper paper = caps.papers[0];
EXPECT_EQ(208000, paper.size_um().width());
EXPECT_EQ(295000, paper.size_um().height());
}
#endif
TEST_F(PrintBackendCupsIppHelperTest, CustomPaperSupported) { … }
TEST_F(PrintBackendCupsIppHelperTest, CustomPaperWithZeroMinHeight) { … }
TEST_F(PrintBackendCupsIppHelperTest, CustomPaperWithInvalidHeight) { … }
TEST_F(PrintBackendCupsIppHelperTest, CustomPaperWithInvalidWidth) { … }
TEST_F(PrintBackendCupsIppHelperTest, LegalPaperDefault) { … }
TEST_F(PrintBackendCupsIppHelperTest, OmitPapersWithInvalidSizes) { … }
TEST_F(PrintBackendCupsIppHelperTest, IncludePapersWithSizeRanges) { … }
TEST_F(PrintBackendCupsIppHelperTest, HandleBorderlessVariants) { … }
TEST_F(PrintBackendCupsIppHelperTest, NoDuplicateSizes) { … }
TEST_F(PrintBackendCupsIppHelperTest, FilterMediaColSizesNominal) { … }
TEST_F(PrintBackendCupsIppHelperTest,
FilterMediaColSizesVariableWidthAndHeight) { … }
TEST_F(PrintBackendCupsIppHelperTest, FilterMediaColSizesVariableWidth) { … }
TEST_F(PrintBackendCupsIppHelperTest, FilterMediaColSizesVariableHeight) { … }
TEST_F(PrintBackendCupsIppHelperTest, FilterMediaColSizesSameVariableHeight) { … }
TEST_F(PrintBackendCupsIppHelperTest, FilterMediaColSizesSingleVariableEntry) { … }
TEST_F(PrintBackendCupsIppHelperTest, FilterMediaColSizesInvalidWidth) { … }
TEST_F(PrintBackendCupsIppHelperTest,
FilterMediaColSizesMultipleVariableEntries) { … }
TEST_F(PrintBackendCupsIppHelperTest,
FilterMediaColSizesMultipleVariableEntriesOverlap) { … }
TEST_F(PrintBackendCupsIppHelperTest,
FilterMediaColSizesMultipleVariableEntriesOverlapOutsideRange) { … }
TEST_F(PrintBackendCupsIppHelperTest,
OverrideUnavailableCanonDefaultMediaType) { … }
TEST_F(PrintBackendCupsIppHelperTest,
OverrideUnavailableCanonDefaultMediaTypeStationeryUnavailable) { … }
#if BUILDFLAG(IS_CHROMEOS)
TEST_F(PrintBackendCupsIppHelperTest, PinSupported) {
printer_->SetSupportedOptions("job-password", MakeInteger(ipp_, 4));
printer_->SetSupportedOptions("job-password-encryption",
MakeStringCollection(ipp_, {"none"}));
PrinterSemanticCapsAndDefaults caps;
CapsAndDefaultsFromPrinter(*printer_, &caps);
EXPECT_TRUE(caps.pin_supported);
}
TEST_F(PrintBackendCupsIppHelperTest, PinNotSupported) {
PrinterSemanticCapsAndDefaults caps;
CapsAndDefaultsFromPrinter(*printer_, &caps);
EXPECT_FALSE(caps.pin_supported);
}
TEST_F(PrintBackendCupsIppHelperTest, PinEncryptionNotSupported) {
printer_->SetSupportedOptions("job-password", MakeInteger(ipp_, 4));
PrinterSemanticCapsAndDefaults caps;
CapsAndDefaultsFromPrinter(*printer_, &caps);
EXPECT_FALSE(caps.pin_supported);
}
TEST_F(PrintBackendCupsIppHelperTest, PinTooShort) {
printer_->SetSupportedOptions("job-password", MakeInteger(ipp_, 3));
printer_->SetSupportedOptions("job-password-encryption",
MakeStringCollection(ipp_, {"none"}));
PrinterSemanticCapsAndDefaults caps;
CapsAndDefaultsFromPrinter(*printer_, &caps);
EXPECT_FALSE(caps.pin_supported);
}
TEST_F(PrintBackendCupsIppHelperTest, AdvancedCaps) {
base::HistogramTester histograms;
printer_->SetSupportedOptions(
"job-creation-attributes",
MakeStringCollection(
ipp_, {"copies", "confirmation-sheet-print", "finishings",
"job-message-to-operator", "output-bin", "print-quality"}));
printer_->SetSupportedOptions("finishings",
MakeIntCollection(ipp_, {3, 7, 10}));
printer_->SetSupportedOptions(
"output-bin", MakeStringCollection(ipp_, {"face-down", "face-up"}));
printer_->SetSupportedOptions("print-quality",
MakeIntCollection(ipp_, {3, 4, 5}));
PrinterSemanticCapsAndDefaults caps;
CapsAndDefaultsFromPrinter(*printer_, &caps);
ASSERT_EQ(6u, caps.advanced_capabilities.size());
EXPECT_EQ("confirmation-sheet-print", caps.advanced_capabilities[0].name);
EXPECT_EQ(AdvancedCapability::Type::kBoolean,
caps.advanced_capabilities[0].type);
EXPECT_EQ("finishings/7", caps.advanced_capabilities[1].name);
EXPECT_EQ(AdvancedCapability::Type::kBoolean,
caps.advanced_capabilities[1].type);
EXPECT_EQ("finishings/10", caps.advanced_capabilities[2].name);
EXPECT_EQ(AdvancedCapability::Type::kBoolean,
caps.advanced_capabilities[2].type);
EXPECT_EQ("job-message-to-operator", caps.advanced_capabilities[3].name);
EXPECT_EQ(AdvancedCapability::Type::kString,
caps.advanced_capabilities[3].type);
EXPECT_EQ("output-bin", caps.advanced_capabilities[4].name);
EXPECT_EQ(AdvancedCapability::Type::kString,
caps.advanced_capabilities[4].type);
EXPECT_EQ(2u, caps.advanced_capabilities[4].values.size());
EXPECT_EQ("print-quality", caps.advanced_capabilities[5].name);
EXPECT_EQ(AdvancedCapability::Type::kString,
caps.advanced_capabilities[5].type);
EXPECT_EQ(3u, caps.advanced_capabilities[5].values.size());
histograms.ExpectUniqueSample("Printing.CUPS.IppAttributesCount", 5, 1);
}
TEST_F(PrintBackendCupsIppHelperTest, MediaSource) {
printer_->SetSupportedOptions(
"media-source",
MakeStringCollection(ipp_, {"top", "main", "auto", "tray-3", "tray-4"}));
PrinterSemanticCapsAndDefaults caps;
CapsAndDefaultsFromPrinter(*printer_, &caps);
ASSERT_EQ(1u, caps.advanced_capabilities.size());
const AdvancedCapability& cap = caps.advanced_capabilities[0];
EXPECT_EQ("media-source", cap.name);
EXPECT_EQ(AdvancedCapability::Type::kString, cap.type);
EXPECT_THAT(cap.values,
Pointwise(AdvancedCapabilityName(),
{"top", "main", "auto", "tray-3", "tray-4"}));
}
#endif
}