chromium/chrome/browser/ash/printing/specifics_translation_unittest.cc

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

#include <string>
#include <utility>

#include "base/time/time.h"
#include "chrome/browser/ash/printing/specifics_translation.h"
#include "chromeos/printing/printer_configuration.h"
#include "components/sync/protocol/printer_specifics.pb.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

using ::chromeos::Printer;

constexpr char kId[] = "UNIQUE_ID";
constexpr char kDisplayName[] = "Best Printer Ever";
constexpr char kDescription[] = "The green one";
constexpr char kManufacturer[] = "Manufacturer";
constexpr char kModel[] = "MODEL";
constexpr char kMakeAndModel[] = "Manufacturer MODEL";
constexpr char kUri[] = "ipps://notaprinter.chromium.org:123/ipp/print";
constexpr char kUuid[] = "UUIDUUIDUUID";
const base::Time kUpdateTime = base::Time::FromInternalValue(22114455660000);

constexpr char kUserSuppliedPPD[] = "file://foo/bar/baz/eeaaaffccdd00";
constexpr char kEffectiveMakeAndModel[] = "Manufacturer Model T1000";

}  // namespace

namespace ash {

TEST(SpecificsTranslationTest, SpecificsToPrinter) {
  sync_pb::PrinterSpecifics specifics;
  specifics.set_id(kId);
  specifics.set_display_name(kDisplayName);
  specifics.set_description(kDescription);
  specifics.set_make_and_model(kMakeAndModel);
  specifics.set_uri(kUri);
  specifics.set_uuid(kUuid);
  specifics.set_updated_timestamp(kUpdateTime.InMillisecondsSinceUnixEpoch());

  sync_pb::PrinterPPDReference ppd;
  ppd.set_effective_make_and_model(kEffectiveMakeAndModel);
  *specifics.mutable_ppd_reference() = ppd;

  std::unique_ptr<Printer> result = SpecificsToPrinter(specifics);
  EXPECT_EQ(kId, result->id());
  EXPECT_EQ(kDisplayName, result->display_name());
  EXPECT_EQ(kDescription, result->description());
  EXPECT_EQ(kMakeAndModel, result->make_and_model());
  EXPECT_EQ(kUri, result->uri().GetNormalized(false));
  EXPECT_EQ(kUuid, result->uuid());

  EXPECT_EQ(kEffectiveMakeAndModel,
            result->ppd_reference().effective_make_and_model);
  EXPECT_FALSE(result->IsIppEverywhere());
}

TEST(SpecificsTranslationTest, SpecificsToPrinterSocketUriWithPath) {
  sync_pb::PrinterSpecifics specifics;
  specifics.set_id(kId);
  specifics.set_display_name(kDisplayName);
  specifics.set_description(kDescription);
  specifics.set_make_and_model(kMakeAndModel);
  specifics.set_uri("socket://abc.def:1234/path1/path2");
  specifics.set_uuid(kUuid);
  specifics.set_updated_timestamp(kUpdateTime.InMillisecondsSinceUnixEpoch());

  sync_pb::PrinterPPDReference ppd;
  ppd.set_effective_make_and_model(kEffectiveMakeAndModel);
  *specifics.mutable_ppd_reference() = ppd;

  std::unique_ptr<Printer> result = SpecificsToPrinter(specifics);
  EXPECT_EQ("socket://abc.def:1234", result->uri().GetNormalized());
}

TEST(SpecificsTranslationTest, PrinterToSpecifics) {
  Printer printer;
  printer.set_id(kId);
  printer.set_display_name(kDisplayName);
  printer.set_description(kDescription);
  printer.set_make_and_model(kMakeAndModel);
  printer.SetUri(kUri);
  printer.set_uuid(kUuid);

  Printer::PpdReference ppd;
  ppd.effective_make_and_model = kEffectiveMakeAndModel;
  *printer.mutable_ppd_reference() = ppd;

  std::unique_ptr<sync_pb::PrinterSpecifics> result =
      PrinterToSpecifics(printer);
  EXPECT_EQ(kId, result->id());
  EXPECT_EQ(kDisplayName, result->display_name());
  EXPECT_EQ(kDescription, result->description());
  EXPECT_EQ(kMakeAndModel, result->make_and_model());
  EXPECT_EQ(kUri, result->uri());
  EXPECT_EQ(kUuid, result->uuid());

  EXPECT_EQ(kEffectiveMakeAndModel,
            result->ppd_reference().effective_make_and_model());
}

TEST(SpecificsTranslationTest, SpecificsToPrinterRoundTrip) {
  Printer printer;
  printer.set_id(kId);
  printer.set_display_name(kDisplayName);
  printer.set_description(kDescription);
  printer.set_make_and_model(kMakeAndModel);
  printer.SetUri(kUri);
  printer.set_uuid(kUuid);

  Printer::PpdReference ppd;
  ppd.autoconf = true;
  *printer.mutable_ppd_reference() = ppd;

  std::unique_ptr<sync_pb::PrinterSpecifics> temp = PrinterToSpecifics(printer);
  std::unique_ptr<Printer> result = SpecificsToPrinter(*temp);

  EXPECT_EQ(kId, result->id());
  EXPECT_EQ(kDisplayName, result->display_name());
  EXPECT_EQ(kDescription, result->description());
  EXPECT_EQ(kMakeAndModel, result->make_and_model());
  EXPECT_EQ(kUri, result->uri().GetNormalized(false));
  EXPECT_EQ(kUuid, result->uuid());

  EXPECT_TRUE(result->ppd_reference().effective_make_and_model.empty());
  EXPECT_TRUE(result->ppd_reference().autoconf);
}

TEST(SpecificsTranslationTest, MergePrinterToSpecifics) {
  sync_pb::PrinterSpecifics original;
  original.set_id(kId);
  original.mutable_ppd_reference()->set_autoconf(true);
  original.set_manufacturer(kManufacturer);
  original.set_model(kModel);
  // make_and_model not set

  Printer printer(kId);
  printer.mutable_ppd_reference()->effective_make_and_model =
      kEffectiveMakeAndModel;
  printer.set_make_and_model(kMakeAndModel);
  // manufacturer not set
  // model not set

  MergePrinterToSpecifics(printer, &original);

  EXPECT_EQ(kId, original.id());
  EXPECT_EQ(kEffectiveMakeAndModel,
            original.ppd_reference().effective_make_and_model());

  // Verify that autoconf is cleared.
  EXPECT_FALSE(original.ppd_reference().autoconf());

  // Verify that both make_and_model and the old fields are retained.
  EXPECT_EQ(kMakeAndModel, original.make_and_model());
  EXPECT_EQ(kManufacturer, original.manufacturer());
  EXPECT_EQ(kModel, original.model());
}

// Tests that the autoconf value overrides other PpdReference fields.
TEST(SpecificsTranslationTest, AutoconfOverrides) {
  sync_pb::PrinterSpecifics original;
  original.set_id(kId);
  auto* ppd_reference = original.mutable_ppd_reference();
  ppd_reference->set_autoconf(true);
  ppd_reference->set_user_supplied_ppd_url(kUserSuppliedPPD);

  auto printer = SpecificsToPrinter(original);

  EXPECT_TRUE(printer->ppd_reference().autoconf);
  EXPECT_TRUE(printer->ppd_reference().user_supplied_ppd_url.empty());
  EXPECT_TRUE(printer->ppd_reference().effective_make_and_model.empty());
}

// Tests that user_supplied_ppd_url overwrites other PpdReference fields if
// autoconf is false.
TEST(SpecificsTranslationTest, UserSuppliedOverrides) {
  sync_pb::PrinterSpecifics original;
  original.set_id(kId);
  auto* ppd_reference = original.mutable_ppd_reference();
  ppd_reference->set_user_supplied_ppd_url(kUserSuppliedPPD);
  ppd_reference->set_effective_make_and_model(kEffectiveMakeAndModel);

  auto printer = SpecificsToPrinter(original);

  EXPECT_FALSE(printer->ppd_reference().autoconf);
  EXPECT_FALSE(printer->ppd_reference().user_supplied_ppd_url.empty());
  EXPECT_TRUE(printer->ppd_reference().effective_make_and_model.empty());
}

TEST(SpecificsTranslationTest, OldProtoExpectedValues) {
  sync_pb::PrinterSpecifics original;
  original.set_id(kId);
  original.set_manufacturer(kManufacturer);
  original.set_model(kModel);

  auto printer = SpecificsToPrinter(original);

  // make_and_model should be computed
  EXPECT_EQ(kMakeAndModel, printer->make_and_model());
}

TEST(SpecificsTranslationTest, OldProtoDuplicateManufacturer) {
  const std::string make = "IO";
  const std::string model = "IO Radar 2000";

  sync_pb::PrinterSpecifics original;
  original.set_id(kId);
  original.set_manufacturer(make);
  original.set_model(model);

  auto printer = SpecificsToPrinter(original);

  EXPECT_EQ("IO Radar 2000", printer->make_and_model());
}

TEST(SpecificsTranslationTest, MakeAndModelPreferred) {
  const std::string make = "UN";
  const std::string model = "EXPECTED";

  sync_pb::PrinterSpecifics original;
  original.set_id(kId);
  original.set_manufacturer(make);
  original.set_model(model);
  original.set_make_and_model(kMakeAndModel);

  auto printer = SpecificsToPrinter(original);

  EXPECT_EQ(kMakeAndModel, printer->make_and_model());
}

}  // namespace ash