OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "chrome/browser/chromeos/printing/combining_printer_detector.h" |
| 6 |
| 7 #include <algorithm> |
| 8 #include <memory> |
| 9 #include <set> |
| 10 #include <string> |
| 11 #include <utility> |
| 12 #include <vector> |
| 13 |
| 14 #include "base/memory/ptr_util.h" |
| 15 #include "base/observer_list.h" |
| 16 #include "base/strings/string_util.h" |
| 17 #include "chromeos/printing/printer_configuration.h" |
| 18 #include "testing/gtest/include/gtest/gtest.h" |
| 19 |
| 20 namespace chromeos { |
| 21 |
| 22 namespace { |
| 23 // Fake printer detectors used as the source of detections to be combined. |
| 24 class FakePrinterDetector : public PrinterDetector { |
| 25 public: |
| 26 explicit FakePrinterDetector( |
| 27 const std::vector<std::string>& starting_printers) |
| 28 : printer_ids_(starting_printers.begin(), starting_printers.end()) {} |
| 29 |
| 30 ~FakePrinterDetector() override = default; |
| 31 |
| 32 void Start() override {} |
| 33 |
| 34 // Add these printers to the list of detected printers, and notify |
| 35 // downstream observers. |
| 36 void AddPrinters(const std::vector<std::string>& ids) { |
| 37 for (const std::string& id : ids) { |
| 38 CHECK(printer_ids_.insert(id).second) |
| 39 << "Cowardly refusing to add printer with duplicate id " << id; |
| 40 } |
| 41 Notify(); |
| 42 } |
| 43 |
| 44 // Remove these printers from the list of detected printers, and notify |
| 45 // downstream observers. |
| 46 void RemovePrinters(const std::vector<std::string>& ids) { |
| 47 for (const std::string id : ids) { |
| 48 CHECK_EQ(printer_ids_.erase(id), static_cast<size_t>(1)) |
| 49 << "Can't remove printer with nonexistant id " << id; |
| 50 } |
| 51 Notify(); |
| 52 } |
| 53 |
| 54 // Tell downstream observers that we're done finding printers. |
| 55 void PrinterScanComplete() { |
| 56 for (PrinterDetector::Observer& observer : observer_list_) { |
| 57 observer.OnPrinterScanComplete(); |
| 58 } |
| 59 } |
| 60 |
| 61 // PrinterDetector implementations. |
| 62 void AddObserver(PrinterDetector::Observer* observer) override { |
| 63 observer_list_.AddObserver(observer); |
| 64 } |
| 65 |
| 66 void RemoveObserver(PrinterDetector::Observer* observer) override { |
| 67 observer_list_.RemoveObserver(observer); |
| 68 } |
| 69 |
| 70 std::vector<Printer> GetPrinters() override { |
| 71 std::vector<Printer> printers; |
| 72 for (const std::string& id : printer_ids_) { |
| 73 printers.push_back(Printer(id)); |
| 74 } |
| 75 return printers; |
| 76 } |
| 77 |
| 78 private: |
| 79 void Notify() { |
| 80 std::vector<Printer> printers = GetPrinters(); |
| 81 for (PrinterDetector::Observer& observer : observer_list_) { |
| 82 observer.OnPrintersFound(printers); |
| 83 } |
| 84 } |
| 85 |
| 86 base::ObserverList<PrinterDetector::Observer> observer_list_; |
| 87 |
| 88 // In the fake, we only use printer ids to figure out if the right printers |
| 89 // are being propagated. So internally we just track ids and construct |
| 90 // printers on the fly when asked for them. |
| 91 std::set<std::string> printer_ids_; |
| 92 }; |
| 93 |
| 94 class PrintingCombiningPrinterDetectorTest : public testing::Test, |
| 95 public PrinterDetector::Observer { |
| 96 public: |
| 97 void Init(const std::vector<std::vector<std::string>>& id_lists) { |
| 98 combining_detector_ = CombiningPrinterDetector::Create(); |
| 99 |
| 100 bool test_owned = false; |
| 101 for (const std::vector<std::string>& id_list : id_lists) { |
| 102 // Divide up fake detectors between owned and unowned to exercise both |
| 103 // paths. It shouldn't really matter in the test below where ownership of |
| 104 // a specific fake detector lies. |
| 105 auto fake_detector = base::MakeUnique<FakePrinterDetector>(id_list); |
| 106 fake_detectors_.push_back(fake_detector.get()); |
| 107 if (test_owned) { |
| 108 combining_detector_->AddDetector(fake_detector.get()); |
| 109 owned_fake_detectors_.emplace_back(std::move(fake_detector)); |
| 110 } else { |
| 111 combining_detector_->AddOwnedDetector(std::move(fake_detector)); |
| 112 } |
| 113 test_owned = !test_owned; |
| 114 } |
| 115 combining_detector_->AddObserver(this); |
| 116 combining_detector_->Start(); |
| 117 printers_ = combining_detector_->GetPrinters(); |
| 118 } |
| 119 |
| 120 void OnPrintersFound(const std::vector<Printer>& printers) override { |
| 121 printers_ = printers; |
| 122 } |
| 123 |
| 124 void OnPrinterScanComplete() override { scan_complete_ = true; } |
| 125 |
| 126 protected: |
| 127 // Testing utility function -- return true if the printers we got in the most |
| 128 // recent OnPrintersFound call are the same as printers (without considering |
| 129 // order). |
| 130 void ExpectFoundPrintersAre(const std::vector<std::string>& expected_ids) { |
| 131 std::vector<std::string> sorted_expected(expected_ids.begin(), |
| 132 expected_ids.end()); |
| 133 std::vector<std::string> sorted_actual; |
| 134 for (const Printer& printer : printers_) { |
| 135 sorted_actual.push_back(printer.id()); |
| 136 } |
| 137 std::sort(sorted_expected.begin(), sorted_expected.end()); |
| 138 std::sort(sorted_actual.begin(), sorted_actual.end()); |
| 139 if (sorted_expected != sorted_actual) { |
| 140 ADD_FAILURE() << "Printer ids mismatch. Expected: {" |
| 141 << base::JoinString(sorted_expected, ", ") << "}; Found: {" |
| 142 << base::JoinString(sorted_actual, ", ") << "}"; |
| 143 } |
| 144 } |
| 145 |
| 146 // Have we been notified that the scan is complete? |
| 147 bool scan_complete_ = false; |
| 148 |
| 149 // The printers in the most recent OnPrintersFound call. |
| 150 std::vector<Printer> printers_; |
| 151 |
| 152 // The fake detectors plugged into the combining detector. |
| 153 std::vector<FakePrinterDetector*> fake_detectors_; |
| 154 |
| 155 // Cleanup pointers for fake detectors owned by the test. (The |
| 156 // other fake detectors are owned by the combining_detector. |
| 157 std::vector<std::unique_ptr<FakePrinterDetector>> owned_fake_detectors_; |
| 158 |
| 159 std::unique_ptr<CombiningPrinterDetector> combining_detector_; |
| 160 }; |
| 161 |
| 162 TEST_F(PrintingCombiningPrinterDetectorTest, BasicUsage) { |
| 163 Init({{"1a"}, std::vector<std::string>(), {"3a"}}); |
| 164 ExpectFoundPrintersAre({"1a", "3a"}); |
| 165 EXPECT_FALSE(scan_complete_); |
| 166 |
| 167 // Find some printers in the second detector. |
| 168 fake_detectors_[1]->AddPrinters({"2a", "2b", "2c"}); |
| 169 ExpectFoundPrintersAre({"1a", "2a", "2b", "2c", "3a"}); |
| 170 EXPECT_FALSE(scan_complete_); |
| 171 |
| 172 // Find some printers on the first detector. |
| 173 fake_detectors_[0]->AddPrinters({"1b"}); |
| 174 ExpectFoundPrintersAre({"1a", "1b", "2a", "2b", "2c", "3a"}); |
| 175 EXPECT_FALSE(scan_complete_); |
| 176 |
| 177 // Have the first detector signal completion, the combined detector should |
| 178 // not be complete until all 3 fake detectors have completed. |
| 179 fake_detectors_[0]->PrinterScanComplete(); |
| 180 EXPECT_FALSE(scan_complete_); |
| 181 ExpectFoundPrintersAre({"1a", "1b", "2a", "2b", "2c", "3a"}); |
| 182 |
| 183 // Exercise removal of a printer. |
| 184 fake_detectors_[2]->RemovePrinters({"3a"}); |
| 185 EXPECT_FALSE(scan_complete_); |
| 186 ExpectFoundPrintersAre({"1a", "1b", "2a", "2b", "2c"}); |
| 187 |
| 188 // Mark the 3rd detector as complete. The 2nd detector has still not declared |
| 189 // itself complete. |
| 190 fake_detectors_[2]->PrinterScanComplete(); |
| 191 EXPECT_FALSE(scan_complete_); |
| 192 ExpectFoundPrintersAre({"1a", "1b", "2a", "2b", "2c"}); |
| 193 |
| 194 // Multiple scan complete calls from the same detector shouldn't happen, but |
| 195 // if they do happen, it should be a nop. |
| 196 fake_detectors_[2]->PrinterScanComplete(); |
| 197 EXPECT_FALSE(scan_complete_); |
| 198 ExpectFoundPrintersAre({"1a", "1b", "2a", "2b", "2c"}); |
| 199 |
| 200 // We can still add printers from a detector that has declared itself |
| 201 // complete. |
| 202 fake_detectors_[0]->AddPrinters({"1c"}); |
| 203 ExpectFoundPrintersAre({"1a", "1b", "1c", "2a", "2b", "2c"}); |
| 204 EXPECT_FALSE(scan_complete_); |
| 205 |
| 206 // Finally the 2nd detector declares itself complete, which should mean the |
| 207 // combined detector is now complete. |
| 208 fake_detectors_[1]->PrinterScanComplete(); |
| 209 EXPECT_TRUE(scan_complete_); |
| 210 ExpectFoundPrintersAre({"1a", "1b", "1c", "2a", "2b", "2c"}); |
| 211 |
| 212 // Should still be able to add printers even after completion. |
| 213 fake_detectors_[2]->AddPrinters({"3g", "3h", "3i"}); |
| 214 EXPECT_TRUE(scan_complete_); |
| 215 ExpectFoundPrintersAre( |
| 216 {"1a", "1b", "1c", "2a", "2b", "2c", "3g", "3h", "3i"}); |
| 217 } |
| 218 |
| 219 } // namespace |
| 220 } // namespace chromeos |
OLD | NEW |