Index: chrome/browser/chromeos/printing/combining_printer_detector_unittest.cc |
diff --git a/chrome/browser/chromeos/printing/combining_printer_detector_unittest.cc b/chrome/browser/chromeos/printing/combining_printer_detector_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..478b923e8a1d6f0adfee56a67926f97d8e1fb951 |
--- /dev/null |
+++ b/chrome/browser/chromeos/printing/combining_printer_detector_unittest.cc |
@@ -0,0 +1,220 @@ |
+// Copyright 2017 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 "chrome/browser/chromeos/printing/combining_printer_detector.h" |
+ |
+#include <algorithm> |
+#include <memory> |
+#include <set> |
+#include <string> |
+#include <utility> |
+#include <vector> |
+ |
+#include "base/memory/ptr_util.h" |
+#include "base/observer_list.h" |
+#include "base/strings/string_util.h" |
+#include "chromeos/printing/printer_configuration.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+namespace chromeos { |
+ |
+namespace { |
+// Fake printer detectors used as the source of detections to be combined. |
+class FakePrinterDetector : public PrinterDetector { |
+ public: |
+ explicit FakePrinterDetector( |
+ const std::vector<std::string>& starting_printers) |
+ : printer_ids_(starting_printers.begin(), starting_printers.end()) {} |
+ |
+ ~FakePrinterDetector() override = default; |
+ |
+ void Start() override {} |
+ |
+ // Add these printers to the list of detected printers, and notify |
+ // downstream observers. |
+ void AddPrinters(const std::vector<std::string>& ids) { |
+ for (const std::string& id : ids) { |
+ CHECK(printer_ids_.insert(id).second) |
+ << "Cowardly refusing to add printer with duplicate id " << id; |
+ } |
+ Notify(); |
+ } |
+ |
+ // Remove these printers from the list of detected printers, and notify |
+ // downstream observers. |
+ void RemovePrinters(const std::vector<std::string>& ids) { |
+ for (const std::string id : ids) { |
+ CHECK_EQ(printer_ids_.erase(id), static_cast<size_t>(1)) |
+ << "Can't remove printer with nonexistant id " << id; |
+ } |
+ Notify(); |
+ } |
+ |
+ // Tell downstream observers that we're done finding printers. |
+ void PrinterScanComplete() { |
+ for (PrinterDetector::Observer& observer : observer_list_) { |
+ observer.OnPrinterScanComplete(); |
+ } |
+ } |
+ |
+ // PrinterDetector implementations. |
+ void AddObserver(PrinterDetector::Observer* observer) override { |
+ observer_list_.AddObserver(observer); |
+ } |
+ |
+ void RemoveObserver(PrinterDetector::Observer* observer) override { |
+ observer_list_.RemoveObserver(observer); |
+ } |
+ |
+ std::vector<Printer> GetPrinters() override { |
+ std::vector<Printer> printers; |
+ for (const std::string& id : printer_ids_) { |
+ printers.push_back(Printer(id)); |
+ } |
+ return printers; |
+ } |
+ |
+ private: |
+ void Notify() { |
+ std::vector<Printer> printers = GetPrinters(); |
+ for (PrinterDetector::Observer& observer : observer_list_) { |
+ observer.OnPrintersFound(printers); |
+ } |
+ } |
+ |
+ base::ObserverList<PrinterDetector::Observer> observer_list_; |
+ |
+ // In the fake, we only use printer ids to figure out if the right printers |
+ // are being propagated. So internally we just track ids and construct |
+ // printers on the fly when asked for them. |
+ std::set<std::string> printer_ids_; |
+}; |
+ |
+class PrintingCombiningPrinterDetectorTest : public testing::Test, |
+ public PrinterDetector::Observer { |
+ public: |
+ void Init(const std::vector<std::vector<std::string>>& id_lists) { |
+ combining_detector_ = CombiningPrinterDetector::Create(); |
+ |
+ bool test_owned = false; |
+ for (const std::vector<std::string>& id_list : id_lists) { |
+ // Divide up fake detectors between owned and unowned to exercise both |
+ // paths. It shouldn't really matter in the test below where ownership of |
+ // a specific fake detector lies. |
+ auto fake_detector = base::MakeUnique<FakePrinterDetector>(id_list); |
+ fake_detectors_.push_back(fake_detector.get()); |
+ if (test_owned) { |
+ combining_detector_->AddDetector(fake_detector.get()); |
+ owned_fake_detectors_.emplace_back(std::move(fake_detector)); |
+ } else { |
+ combining_detector_->AddOwnedDetector(std::move(fake_detector)); |
+ } |
+ test_owned = !test_owned; |
+ } |
+ combining_detector_->AddObserver(this); |
+ combining_detector_->Start(); |
+ printers_ = combining_detector_->GetPrinters(); |
+ } |
+ |
+ void OnPrintersFound(const std::vector<Printer>& printers) override { |
+ printers_ = printers; |
+ } |
+ |
+ void OnPrinterScanComplete() override { scan_complete_ = true; } |
+ |
+ protected: |
+ // Testing utility function -- return true if the printers we got in the most |
+ // recent OnPrintersFound call are the same as printers (without considering |
+ // order). |
+ void ExpectFoundPrintersAre(const std::vector<std::string>& expected_ids) { |
+ std::vector<std::string> sorted_expected(expected_ids.begin(), |
+ expected_ids.end()); |
+ std::vector<std::string> sorted_actual; |
+ for (const Printer& printer : printers_) { |
+ sorted_actual.push_back(printer.id()); |
+ } |
+ std::sort(sorted_expected.begin(), sorted_expected.end()); |
+ std::sort(sorted_actual.begin(), sorted_actual.end()); |
+ if (sorted_expected != sorted_actual) { |
+ ADD_FAILURE() << "Printer ids mismatch. Expected: {" |
+ << base::JoinString(sorted_expected, ", ") << "}; Found: {" |
+ << base::JoinString(sorted_actual, ", ") << "}"; |
+ } |
+ } |
+ |
+ // Have we been notified that the scan is complete? |
+ bool scan_complete_ = false; |
+ |
+ // The printers in the most recent OnPrintersFound call. |
+ std::vector<Printer> printers_; |
+ |
+ // The fake detectors plugged into the combining detector. |
+ std::vector<FakePrinterDetector*> fake_detectors_; |
+ |
+ // Cleanup pointers for fake detectors owned by the test. (The |
+ // other fake detectors are owned by the combining_detector. |
+ std::vector<std::unique_ptr<FakePrinterDetector>> owned_fake_detectors_; |
+ |
+ std::unique_ptr<CombiningPrinterDetector> combining_detector_; |
+}; |
+ |
+TEST_F(PrintingCombiningPrinterDetectorTest, BasicUsage) { |
+ Init({{"1a"}, std::vector<std::string>(), {"3a"}}); |
+ ExpectFoundPrintersAre({"1a", "3a"}); |
+ EXPECT_FALSE(scan_complete_); |
+ |
+ // Find some printers in the second detector. |
+ fake_detectors_[1]->AddPrinters({"2a", "2b", "2c"}); |
+ ExpectFoundPrintersAre({"1a", "2a", "2b", "2c", "3a"}); |
+ EXPECT_FALSE(scan_complete_); |
+ |
+ // Find some printers on the first detector. |
+ fake_detectors_[0]->AddPrinters({"1b"}); |
+ ExpectFoundPrintersAre({"1a", "1b", "2a", "2b", "2c", "3a"}); |
+ EXPECT_FALSE(scan_complete_); |
+ |
+ // Have the first detector signal completion, the combined detector should |
+ // not be complete until all 3 fake detectors have completed. |
+ fake_detectors_[0]->PrinterScanComplete(); |
+ EXPECT_FALSE(scan_complete_); |
+ ExpectFoundPrintersAre({"1a", "1b", "2a", "2b", "2c", "3a"}); |
+ |
+ // Exercise removal of a printer. |
+ fake_detectors_[2]->RemovePrinters({"3a"}); |
+ EXPECT_FALSE(scan_complete_); |
+ ExpectFoundPrintersAre({"1a", "1b", "2a", "2b", "2c"}); |
+ |
+ // Mark the 3rd detector as complete. The 2nd detector has still not declared |
+ // itself complete. |
+ fake_detectors_[2]->PrinterScanComplete(); |
+ EXPECT_FALSE(scan_complete_); |
+ ExpectFoundPrintersAre({"1a", "1b", "2a", "2b", "2c"}); |
+ |
+ // Multiple scan complete calls from the same detector shouldn't happen, but |
+ // if they do happen, it should be a nop. |
+ fake_detectors_[2]->PrinterScanComplete(); |
+ EXPECT_FALSE(scan_complete_); |
+ ExpectFoundPrintersAre({"1a", "1b", "2a", "2b", "2c"}); |
+ |
+ // We can still add printers from a detector that has declared itself |
+ // complete. |
+ fake_detectors_[0]->AddPrinters({"1c"}); |
+ ExpectFoundPrintersAre({"1a", "1b", "1c", "2a", "2b", "2c"}); |
+ EXPECT_FALSE(scan_complete_); |
+ |
+ // Finally the 2nd detector declares itself complete, which should mean the |
+ // combined detector is now complete. |
+ fake_detectors_[1]->PrinterScanComplete(); |
+ EXPECT_TRUE(scan_complete_); |
+ ExpectFoundPrintersAre({"1a", "1b", "1c", "2a", "2b", "2c"}); |
+ |
+ // Should still be able to add printers even after completion. |
+ fake_detectors_[2]->AddPrinters({"3g", "3h", "3i"}); |
+ EXPECT_TRUE(scan_complete_); |
+ ExpectFoundPrintersAre( |
+ {"1a", "1b", "1c", "2a", "2b", "2c", "3g", "3h", "3i"}); |
+} |
+ |
+} // namespace |
+} // namespace chromeos |