chromium/chrome/browser/ash/printing/printer_event_tracker_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 "chrome/browser/ash/printing/printer_event_tracker.h"

#include "base/time/time.h"
#include "chromeos/printing/printer_configuration.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/metrics_proto/printer_event.pb.h"

namespace ash {
namespace {

using ::chromeos::Printer;

constexpr int kVendorId = 0x3241;
constexpr int kProductId = 0x1337;
constexpr char kUsbManufacturer[] = "Usb MakesPrinters";
constexpr char kUsbModel[] = "Printer ModelName";

constexpr char kMakeAndModel[] = "Chromium RazLazer X4321er";
constexpr char kEffectiveMakeAndModel[] = "Generic PostScript";

class PrinterEventTrackerTest : public testing::Test {
 public:
  PrinterEventTrackerTest() = default;

  PrinterEventTrackerTest(const PrinterEventTrackerTest&) = delete;
  PrinterEventTrackerTest& operator=(const PrinterEventTrackerTest&) = delete;

  ~PrinterEventTrackerTest() override = default;

 protected:
  PrinterEventTracker tracker_;

  // Returns a copy of the first element recorded by the tracker.  Calls Flush
  // on the |tracker_|.
  std::vector<metrics::PrinterEventProto> GetEvents() {
    std::vector<metrics::PrinterEventProto> events;
    tracker_.FlushPrinterEvents(&events);
    return events;
  }
};

TEST_F(PrinterEventTrackerTest, RecordsWhenEnabled) {
  tracker_.set_logging(true);

  Printer test_printer;
  test_printer.set_make_and_model(kMakeAndModel);
  test_printer.mutable_ppd_reference()->effective_make_and_model =
      kEffectiveMakeAndModel;

  tracker_.RecordIppPrinterInstalled(test_printer, PrinterEventTracker::kUser);

  auto events = GetEvents();
  EXPECT_EQ(1U, events.size());
}

TEST_F(PrinterEventTrackerTest, DefaultLoggingOff) {
  Printer test_printer;
  test_printer.set_make_and_model(kMakeAndModel);
  test_printer.mutable_ppd_reference()->effective_make_and_model =
      kEffectiveMakeAndModel;

  tracker_.RecordIppPrinterInstalled(test_printer,
                                     PrinterEventTracker::kAutomatic);

  auto events = GetEvents();
  EXPECT_TRUE(events.empty());
}

TEST_F(PrinterEventTrackerTest, DoesNotRecordWhileDisabled) {
  tracker_.set_logging(false);

  Printer test_printer;
  test_printer.set_make_and_model(kMakeAndModel);
  test_printer.mutable_ppd_reference()->effective_make_and_model =
      kEffectiveMakeAndModel;

  tracker_.RecordIppPrinterInstalled(test_printer,
                                     PrinterEventTracker::kAutomatic);

  auto events = GetEvents();
  EXPECT_TRUE(events.empty());
}

TEST_F(PrinterEventTrackerTest, InstalledIppPrinter) {
  tracker_.set_logging(true);

  Printer test_printer;
  test_printer.set_make_and_model(kMakeAndModel);
  test_printer.mutable_ppd_reference()->effective_make_and_model =
      kEffectiveMakeAndModel;

  tracker_.RecordIppPrinterInstalled(test_printer, PrinterEventTracker::kUser);

  auto events = GetEvents();
  ASSERT_FALSE(events.empty());
  metrics::PrinterEventProto recorded_event = events.front();
  EXPECT_EQ(metrics::PrinterEventProto::SETUP_MANUAL,
            recorded_event.event_type());
  EXPECT_EQ(kMakeAndModel, recorded_event.ipp_make_and_model());
  EXPECT_EQ(kEffectiveMakeAndModel, recorded_event.ppd_identifier());

  EXPECT_FALSE(recorded_event.has_usb_printer_manufacturer());
  EXPECT_FALSE(recorded_event.has_usb_printer_model());
  EXPECT_FALSE(recorded_event.has_usb_vendor_id());
  EXPECT_FALSE(recorded_event.has_usb_model_id());
  EXPECT_FALSE(recorded_event.user_ppd());
}

TEST_F(PrinterEventTrackerTest, InstalledPrinterAuto) {
  tracker_.set_logging(true);

  Printer test_printer;
  test_printer.set_make_and_model(kMakeAndModel);
  test_printer.mutable_ppd_reference()->autoconf = true;

  tracker_.RecordIppPrinterInstalled(
      test_printer, PrinterEventTracker::SetupMode::kAutomatic);

  auto events = GetEvents();
  ASSERT_FALSE(events.empty());

  metrics::PrinterEventProto recorded_event = events.front();
  EXPECT_EQ(metrics::PrinterEventProto::SETUP_AUTOMATIC,
            recorded_event.event_type());
  EXPECT_EQ(kMakeAndModel, recorded_event.ipp_make_and_model());
  // For autoconf printers, ppd identifier is blank but a successful setup is
  // recorded.
  EXPECT_FALSE(recorded_event.has_ppd_identifier());

  EXPECT_FALSE(recorded_event.has_usb_printer_manufacturer());
  EXPECT_FALSE(recorded_event.has_usb_printer_model());
  EXPECT_FALSE(recorded_event.has_usb_vendor_id());
  EXPECT_FALSE(recorded_event.has_usb_model_id());
  EXPECT_FALSE(recorded_event.user_ppd());
}

TEST_F(PrinterEventTrackerTest, InstalledPrinterUserPpd) {
  tracker_.set_logging(true);

  Printer test_printer;
  test_printer.mutable_ppd_reference()->user_supplied_ppd_url =
      "file:///i_dont_record_this_field/blah/blah/blah/some_ppd.ppd";

  tracker_.RecordIppPrinterInstalled(test_printer,
                                     PrinterEventTracker::SetupMode::kUser);

  auto events = GetEvents();
  ASSERT_FALSE(events.empty());

  metrics::PrinterEventProto recorded_event = events.front();
  EXPECT_EQ(metrics::PrinterEventProto::SETUP_MANUAL,
            recorded_event.event_type());

  // For user PPDs we just record that it was a user PPD, the value is not
  // recorded.
  EXPECT_TRUE(recorded_event.user_ppd());
  EXPECT_FALSE(recorded_event.has_ppd_identifier());

  // This is empty if it was not detected.
  EXPECT_FALSE(recorded_event.has_ipp_make_and_model());

  // Network printers do not have usb information.
  EXPECT_FALSE(recorded_event.has_usb_printer_manufacturer());
  EXPECT_FALSE(recorded_event.has_usb_printer_model());
  EXPECT_FALSE(recorded_event.has_usb_vendor_id());
  EXPECT_FALSE(recorded_event.has_usb_model_id());
}

TEST_F(PrinterEventTrackerTest, InstalledUsbPrinter) {
  tracker_.set_logging(true);
  PrinterDetector::DetectedPrinter usb_printer;
  usb_printer.ppd_search_data.usb_vendor_id = kVendorId;
  usb_printer.ppd_search_data.usb_product_id = kProductId;
  usb_printer.ppd_search_data.usb_manufacturer = kUsbManufacturer;
  usb_printer.ppd_search_data.usb_model = kUsbModel;
  usb_printer.printer.mutable_ppd_reference()->effective_make_and_model =
      kEffectiveMakeAndModel;

  tracker_.RecordUsbPrinterInstalled(usb_printer,
                                     PrinterEventTracker::SetupMode::kUser);

  auto events = GetEvents();
  ASSERT_FALSE(events.empty());

  metrics::PrinterEventProto record = events.front();
  EXPECT_EQ(metrics::PrinterEventProto::SETUP_MANUAL, record.event_type());
  EXPECT_EQ(kVendorId, record.usb_vendor_id());
  EXPECT_EQ(kProductId, record.usb_model_id());
  EXPECT_EQ(kUsbManufacturer, record.usb_printer_manufacturer());
  EXPECT_EQ(kUsbModel, record.usb_printer_model());

  EXPECT_EQ(kEffectiveMakeAndModel, record.ppd_identifier());
  EXPECT_FALSE(record.user_ppd());

  // USB doesn't detect this field.
  EXPECT_FALSE(record.has_ipp_make_and_model());
}

TEST_F(PrinterEventTrackerTest, AbandonedNetworkPrinter) {
  tracker_.set_logging(true);

  Printer test_printer;
  test_printer.set_make_and_model(kMakeAndModel);

  tracker_.RecordSetupAbandoned(test_printer);

  auto events = GetEvents();
  ASSERT_FALSE(events.empty());

  metrics::PrinterEventProto recorded_event = events.front();
  EXPECT_EQ(metrics::PrinterEventProto::SETUP_ABANDONED,
            recorded_event.event_type());
  EXPECT_EQ(kMakeAndModel, recorded_event.ipp_make_and_model());

  // Abandoned setups should not record a chosen PPD or user PPD.
  EXPECT_FALSE(recorded_event.has_user_ppd());
  EXPECT_FALSE(recorded_event.has_ppd_identifier());

  EXPECT_FALSE(recorded_event.has_usb_printer_manufacturer());
  EXPECT_FALSE(recorded_event.has_usb_printer_model());
  EXPECT_FALSE(recorded_event.has_usb_vendor_id());
  EXPECT_FALSE(recorded_event.has_usb_model_id());
}

TEST_F(PrinterEventTrackerTest, AbandonedUsbPrinter) {
  tracker_.set_logging(true);

  PrinterDetector::DetectedPrinter usb_printer;
  usb_printer.ppd_search_data.usb_vendor_id = kVendorId;
  usb_printer.ppd_search_data.usb_product_id = kProductId;
  usb_printer.ppd_search_data.usb_manufacturer = kUsbManufacturer;
  usb_printer.ppd_search_data.usb_model = kUsbModel;

  tracker_.RecordUsbSetupAbandoned(usb_printer);

  auto events = GetEvents();
  ASSERT_FALSE(events.empty());

  metrics::PrinterEventProto record = events.front();
  EXPECT_EQ(metrics::PrinterEventProto::SETUP_ABANDONED, record.event_type());
  EXPECT_EQ(kVendorId, record.usb_vendor_id());
  EXPECT_EQ(kProductId, record.usb_model_id());
  EXPECT_EQ(kUsbManufacturer, record.usb_printer_manufacturer());
  EXPECT_EQ(kUsbModel, record.usb_printer_model());

  EXPECT_FALSE(record.has_user_ppd());
  EXPECT_FALSE(record.has_ppd_identifier());
}

TEST_F(PrinterEventTrackerTest, RemovedPrinter) {
  tracker_.set_logging(true);

  Printer test_printer;
  test_printer.set_make_and_model(kMakeAndModel);
  test_printer.mutable_ppd_reference()->effective_make_and_model =
      kEffectiveMakeAndModel;

  tracker_.RecordPrinterRemoved(test_printer);

  auto events = GetEvents();
  ASSERT_FALSE(events.empty());

  metrics::PrinterEventProto recorded_event = events.front();
  EXPECT_EQ(metrics::PrinterEventProto::PRINTER_DELETED,
            recorded_event.event_type());
  // All printers record make and model information here.
  EXPECT_EQ(kMakeAndModel, recorded_event.ipp_make_and_model());

  // PPD info.
  EXPECT_EQ(kEffectiveMakeAndModel, recorded_event.ppd_identifier());
  EXPECT_FALSE(recorded_event.user_ppd());

  // USB Info is not retained for removed printers.
  EXPECT_FALSE(recorded_event.has_usb_printer_manufacturer());
  EXPECT_FALSE(recorded_event.has_usb_printer_model());
  EXPECT_FALSE(recorded_event.has_usb_vendor_id());
  EXPECT_FALSE(recorded_event.has_usb_model_id());
}

}  // namespace
}  // namespace ash