chromium/printing/backend/cups_ipp_helper_unittest.cc

// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#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;

// Matches the name field to a string.
MATCHER(AdvancedCapabilityName, "") {}

// Compares an ipp_t* db entry from a media-col-database to a media_info
// object.
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 {};

// Return true if `db_entry` matches the data specified in `info`
// (`keyword_attrs` are not checked).
bool MediaColDbEntryEquals(ipp_t* db_entry, media_info info) {}

// Returns a vector with pointers to all the entries in `media_col_db`.
// `media_col_db` maintains ownership of the returned values.
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  // BUILDFLAG(IS_MAC)

TEST_F(PrintBackendCupsIppHelperTest, CustomPaperSupported) {}

TEST_F(PrintBackendCupsIppHelperTest, CustomPaperWithZeroMinHeight) {}

TEST_F(PrintBackendCupsIppHelperTest, CustomPaperWithInvalidHeight) {}

TEST_F(PrintBackendCupsIppHelperTest, CustomPaperWithInvalidWidth) {}

TEST_F(PrintBackendCupsIppHelperTest, LegalPaperDefault) {}

// Tests that CapsAndDefaultsFromPrinter() does not propagate papers with
// invalid sizes or margins to the Chromium print backend.
TEST_F(PrintBackendCupsIppHelperTest, OmitPapersWithInvalidSizes) {}

// Tests that CapsAndDefaultsFromPrinter() will propagate custom size ranges
// from the  the media-col-database to the Chromium print backend.
TEST_F(PrintBackendCupsIppHelperTest, IncludePapersWithSizeRanges) {}

// Tests that when the media-col-database contains both bordered and borderless
// versions of a size, CapsAndDefaultsFromPrinter() takes the bordered version
// and marks it as having a borderless variant.
TEST_F(PrintBackendCupsIppHelperTest, HandleBorderlessVariants) {}

// At the time of this writing, there are no media-source or media-type
// attributes in the media-col-database that cupsd gives us. However, according
// to the IPP spec, each paper size *should* have a separate variant for each
// supported combination of size and type. So make sure behavior doesn't change
// and we don't create duplicate paper sizes when/if CUPS improves in the
// future.
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) {
  // Pin support missing, no setup.
  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  // BUILDFLAG(IS_CHROMEOS)

}  // namespace printing