blob: 05844977f75b93c9baf46bbe9aa2bfcff0ba65e8 [file] [log] [blame]
justincarlsonc7d4aa6c2016-10-25 15:12:101// Copyright 2016 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
Jimmy Gong533177732019-04-26 19:13:195#include "chromeos/printing/ppd_provider.h"
6
Justin Carlson781f77e212017-11-15 22:32:317#include <algorithm>
justincarlson2fc4d82b2017-02-03 22:49:478#include <map>
Ben Chane6cd0282017-10-18 18:38:419#include <memory>
justincarlson2fc4d82b2017-02-03 22:49:4710#include <utility>
11
justincarlsonc7d4aa6c2016-10-25 15:12:1012#include "base/bind.h"
justincarlson2fc4d82b2017-02-03 22:49:4713#include "base/bind_helpers.h"
justincarlsonc7d4aa6c2016-10-25 15:12:1014#include "base/files/file_util.h"
15#include "base/files/scoped_temp_dir.h"
16#include "base/logging.h"
justincarlsonc7d4aa6c2016-10-25 15:12:1017#include "base/run_loop.h"
18#include "base/single_thread_task_runner.h"
19#include "base/strings/stringprintf.h"
Gabriel Charetteb69fcd42019-08-23 02:13:2920#include "base/test/scoped_task_environment.h"
justincarlson2fc4d82b2017-02-03 22:49:4721#include "base/test/test_message_loop.h"
22#include "base/threading/sequenced_task_runner_handle.h"
justincarlsonc7d4aa6c2016-10-25 15:12:1023#include "base/threading/thread_task_runner_handle.h"
Luum Habtemariam67e8adb822018-01-04 16:04:4724#include "base/version.h"
Steven Bennetts38e9bde22019-01-03 17:31:1025#include "chromeos/constants/chromeos_paths.h"
justincarlsonc7d4aa6c2016-10-25 15:12:1026#include "chromeos/printing/ppd_cache.h"
Justin Carlson97bf1add2017-07-21 18:31:1427#include "chromeos/printing/printer_configuration.h"
Luum Habtemariamb30c8112018-06-25 21:51:2228#include "net/base/net_errors.h"
justincarlsonc7d4aa6c2016-10-25 15:12:1029#include "net/url_request/url_request_test_util.h"
Luum Habtemariamb30c8112018-06-25 21:51:2230#include "services/network/public/cpp/resource_request.h"
31#include "services/network/test/test_url_loader_factory.h"
justincarlsonc7d4aa6c2016-10-25 15:12:1032#include "testing/gtest/include/gtest/gtest.h"
33
justincarlsonc7d4aa6c2016-10-25 15:12:1034namespace chromeos {
justincarlson2fc4d82b2017-02-03 22:49:4735
justincarlsonc7d4aa6c2016-10-25 15:12:1036namespace {
37
Luum Habtemariam521c6872019-07-11 20:12:4638using PrinterDiscoveryType = PrinterSearchData::PrinterDiscoveryType;
39
justincarlson2fc4d82b2017-02-03 22:49:4740// Name of the fake server we're resolving ppds from.
41const char kPpdServer[] = "bogus.google.com";
justincarlson9c860c82016-11-01 17:46:3642
justincarlson96bf4bd82017-04-12 19:14:4643// A pseudo-ppd that should get cupsFilter lines extracted from it.
44const char kCupsFilterPpdContents[] = R"(
45Other random contents that we don't care about.
46*cupsFilter: "application/vnd.cups-raster 0 my_filter"
47More random contents that we don't care about
48*cupsFilter: "application/vnd.cups-awesome 0 a_different_filter"
49*cupsFilter: "application/vnd.cups-awesomesauce 0 filter3"
50Yet more randome contents that we don't care about.
51More random contents that we don't care about.
52)";
53
54// A pseudo-ppd that should get cupsFilter2 lines extracted from it.
55// We also have cupsFilter lines in here, but since cupsFilter2 lines
56// exist, the cupsFilter lines should be ignored.
57const char kCupsFilter2PpdContents[] = R"(
58Other random contents that we don't care about.
59*cupsFilter: "application/vnd.cups-raster 0 my_filter"
60More random contents that we don't care about
61*cupsFilter2: "foo bar 0 the_real_filter"
62*cupsFilter2: "bar baz 381 another_real_filter"
63Yet more randome contents that we don't care about.
64More random contents that we don't care about.
65)";
66
justincarlsonc7d4aa6c2016-10-25 15:12:1067class PpdProviderTest : public ::testing::Test {
68 public:
69 PpdProviderTest()
Gabriel Charette694c3c332019-08-19 14:53:0570 : task_environment_(base::test::TaskEnvironment::MainThreadType::IO) {
Luum Habtemariamb30c8112018-06-25 21:51:2271 TurnOffFakePpdServer();
72 }
justincarlsonc7d4aa6c2016-10-25 15:12:1073
74 void SetUp() override {
75 ASSERT_TRUE(ppd_cache_temp_dir_.CreateUniqueTempDir());
justincarlsonc7d4aa6c2016-10-25 15:12:1076 }
77
justincarlson2fc4d82b2017-02-03 22:49:4778 void TearDown() override { StopFakePpdServer(); }
79
Justin Carlsond9a046142018-01-24 17:56:0680 // Create and return a provider for a test that uses the given |locale|. If
81 // run_cache_on_test_thread is true, we'll run the cache using the
Gabriel Charette694c3c332019-08-19 14:53:0582 // task_environment_; otherwise we'll let it spawn it's own background
Justin Carlsond9a046142018-01-24 17:56:0683 // threads. You should only run the cache on the test thread if you need to
84 // explicity drain cache actions independently of draining ppd provider
85 // actions; otherwise letting the cache spawn its own thread should be safe,
86 // and better exercises the code paths under test.
87 scoped_refptr<PpdProvider> CreateProvider(const std::string& locale,
88 bool run_cache_on_test_thread) {
justincarlson2fc4d82b2017-02-03 22:49:4789 auto provider_options = PpdProvider::Options();
90 provider_options.ppd_server_root = std::string("https://") + kPpdServer;
91
Justin Carlsond9a046142018-01-24 17:56:0692 if (run_cache_on_test_thread) {
93 ppd_cache_ = PpdCache::CreateForTesting(
94 ppd_cache_temp_dir_.GetPath(),
Gabriel Charette694c3c332019-08-19 14:53:0595 task_environment_.GetMainThreadTaskRunner());
Justin Carlsond9a046142018-01-24 17:56:0696 } else {
97 ppd_cache_ = PpdCache::Create(ppd_cache_temp_dir_.GetPath());
98 }
Luum Habtemariamb30c8112018-06-25 21:51:2299 return PpdProvider::Create(locale, &loader_factory_, ppd_cache_,
100 base::Version("40.8.6753.09"), provider_options);
justincarlson2fc4d82b2017-02-03 22:49:47101 }
102
Luum Habtemariamb30c8112018-06-25 21:51:22103 // Fill loader_factory_ with preset contents for test URLs
justincarlson2fc4d82b2017-02-03 22:49:47104 void StartFakePpdServer() {
Luum Habtemariamb30c8112018-06-25 21:51:22105 loader_factory_.ClearResponses();
106 for (const auto& entry : server_contents()) {
107 network::URLLoaderCompletionStatus status;
108 if (!entry.second.empty()) {
109 status.decoded_body_length = entry.second.size();
110 } else {
111 status.error_code = net::ERR_ADDRESS_UNREACHABLE;
112 }
113
114 loader_factory_.AddResponse(FileToURL(entry.first),
115 network::ResourceResponseHead(), entry.second,
116 status);
justincarlson2fc4d82b2017-02-03 22:49:47117 }
118 }
119
120 // Interceptor posts a *task* during destruction that actually unregisters
121 // things. So we have to run the message loop post-interceptor-destruction to
122 // actually unregister the URLs, otherwise they won't *actually* be
123 // unregistered until the next time we invoke the message loop. Which may be
124 // in the middle of the next test.
125 //
126 // Note this is harmless to call if we haven't started a fake ppd server.
127 void StopFakePpdServer() {
Luum Habtemariamb30c8112018-06-25 21:51:22128 TurnOffFakePpdServer();
Gabriel Charette694c3c332019-08-19 14:53:05129 task_environment_.RunUntilIdle();
justincarlson2fc4d82b2017-02-03 22:49:47130 }
131
132 // Capture the result of a ResolveManufacturers() call.
133 void CaptureResolveManufacturers(PpdProvider::CallbackResultCode code,
134 const std::vector<std::string>& data) {
135 captured_resolve_manufacturers_.push_back({code, data});
136 }
137
138 // Capture the result of a ResolvePrinters() call.
139 void CaptureResolvePrinters(PpdProvider::CallbackResultCode code,
Justin Carlson97bf1add2017-07-21 18:31:14140 const PpdProvider::ResolvedPrintersList& data) {
justincarlson2fc4d82b2017-02-03 22:49:47141 captured_resolve_printers_.push_back({code, data});
142 }
143
144 // Capture the result of a ResolvePpd() call.
145 void CaptureResolvePpd(PpdProvider::CallbackResultCode code,
justincarlson96bf4bd82017-04-12 19:14:46146 const std::string& ppd_contents,
147 const std::vector<std::string>& ppd_filters) {
148 CapturedResolvePpdResults results;
149 results.code = code;
150 results.ppd_contents = ppd_contents;
151 results.ppd_filters = ppd_filters;
152 captured_resolve_ppd_.push_back(results);
justincarlson2fc4d82b2017-02-03 22:49:47153 }
154
justincarlson9d5b7af2017-02-14 23:04:49155 // Capture the result of a ResolveUsbIds() call.
Justin Carlson97bf1add2017-07-21 18:31:14156 void CaptureResolvePpdReference(PpdProvider::CallbackResultCode code,
Jimmy Gong533177732019-04-26 19:13:19157 const Printer::PpdReference& ref,
158 const std::string& usb_manufacturer) {
159 captured_resolve_ppd_references_.push_back({code, ref, usb_manufacturer});
justincarlson9d5b7af2017-02-14 23:04:49160 }
161
Sean Kau7f57a922017-08-01 19:00:26162 void CaptureReverseLookup(PpdProvider::CallbackResultCode code,
163 const std::string& manufacturer,
164 const std::string& model) {
165 captured_reverse_lookup_.push_back({code, manufacturer, model});
166 }
167
justincarlson2fc4d82b2017-02-03 22:49:47168 // Discard the result of a ResolvePpd() call.
169 void DiscardResolvePpd(PpdProvider::CallbackResultCode code,
170 const std::string& contents) {}
171
justincarlsonc7d4aa6c2016-10-25 15:12:10172 protected:
justincarlson2fc4d82b2017-02-03 22:49:47173 // Run a ResolveManufacturers run from the given locale, expect to get
174 // results in expected_used_locale.
175 void RunLocalizationTest(const std::string& browser_locale,
176 const std::string& expected_used_locale) {
177 captured_resolve_manufacturers_.clear();
Justin Carlsond9a046142018-01-24 17:56:06178 auto provider = CreateProvider(browser_locale, false);
Luum Habtemariam0517d812018-01-26 17:56:05179 provider->ResolveManufacturers(base::BindOnce(
justincarlson2fc4d82b2017-02-03 22:49:47180 &PpdProviderTest::CaptureResolveManufacturers, base::Unretained(this)));
Gabriel Charette694c3c332019-08-19 14:53:05181 task_environment_.RunUntilIdle();
justincarlson2fc4d82b2017-02-03 22:49:47182 provider = nullptr;
183 ASSERT_EQ(captured_resolve_manufacturers_.size(), 1UL);
184 EXPECT_EQ(captured_resolve_manufacturers_[0].first, PpdProvider::SUCCESS);
185
186 const auto& result_vec = captured_resolve_manufacturers_[0].second;
187
188 // It's sufficient to check for one of the expected locale keys to make sure
189 // we got the right map.
Jan Wilken Dörriedb2c3ef2019-06-08 08:45:32190 EXPECT_TRUE(
191 base::Contains(result_vec, "manufacturer_a_" + expected_used_locale));
justincarlson2fc4d82b2017-02-03 22:49:47192 }
193
Luum Habtemariamb30c8112018-06-25 21:51:22194 // Fake server being down, return ERR_ADDRESS_UNREACHABLE for all endpoints
195 void TurnOffFakePpdServer() {
196 loader_factory_.ClearResponses();
197 network::URLLoaderCompletionStatus status(net::ERR_ADDRESS_UNREACHABLE);
198 for (const auto& entry : server_contents()) {
199 loader_factory_.AddResponse(FileToURL(entry.first),
200 network::ResourceResponseHead(), "", status);
201 }
202 }
203
204 GURL FileToURL(std::string filename) {
205 return GURL(
206 base::StringPrintf("https://%s/%s", kPpdServer, filename.c_str()));
207 }
208
209 // List of relevant endpoint for this FakeServer
210 std::vector<std::pair<std::string, std::string>> server_contents() const {
211 // Use brace initialization to express the desired server contents as "url",
212 // "contents" pairs.
213 return {{"metadata_v2/locales.json",
214 R"(["en",
215 "es-mx",
216 "en-gb"])"},
217 {"metadata_v2/index-01.json",
218 R"([
219 ["printer_a_ref", "printer_a.ppd"]
220 ])"},
221 {"metadata_v2/index-02.json",
222 R"([
223 ["printer_b_ref", "printer_b.ppd"]
224 ])"},
225 {"metadata_v2/index-03.json",
226 R"([
227 ["printer_c_ref", "printer_c.ppd"]
228 ])"},
229 {"metadata_v2/index-04.json",
230 R"([
231 ["printer_d_ref", "printer_d.ppd"]
232 ])"},
233 {"metadata_v2/index-05.json",
234 R"([
235 ["printer_e_ref", "printer_e.ppd"]
236 ])"},
237 {"metadata_v2/index-13.json",
238 R"([
239 ])"},
240 {"metadata_v2/usb-031f.json",
241 R"([
242 [1592, "Some canonical reference"],
243 [6535, "Some other canonical reference"]
244 ])"},
Jimmy Gong533177732019-04-26 19:13:19245 {"metadata_v2/usb-03f0.json", ""},
Luum Habtemariamb30c8112018-06-25 21:51:22246 {"metadata_v2/usb-1234.json", ""},
247 {"metadata_v2/manufacturers-en.json",
248 R"([
249 ["manufacturer_a_en", "manufacturer_a.json"],
250 ["manufacturer_b_en", "manufacturer_b.json"]
251 ])"},
252 {"metadata_v2/manufacturers-en-gb.json",
253 R"([
254 ["manufacturer_a_en-gb", "manufacturer_a.json"],
255 ["manufacturer_b_en-gb", "manufacturer_b.json"]
256 ])"},
257 {"metadata_v2/manufacturers-es-mx.json",
258 R"([
259 ["manufacturer_a_es-mx", "manufacturer_a.json"],
260 ["manufacturer_b_es-mx", "manufacturer_b.json"]
261 ])"},
262 {"metadata_v2/manufacturer_a.json",
263 R"([
264 ["printer_a", "printer_a_ref"],
265 ["printer_b", "printer_b_ref"],
266 ["printer_d", "printer_d_ref"]
267 ])"},
268 {"metadata_v2/manufacturer_a.json",
269 R"([
270 ["printer_a", "printer_a_ref",
271 {"min_milestone":25.0000}],
272 ["printer_b", "printer_b_ref",
273 {"min_milestone":30.0000, "max_milestone":45.0000}],
274 ["printer_d", "printer_d_ref",
275 {"min_milestone":60.0000, "max_milestone":75.0000}]
276 ])"},
277 {"metadata_v2/manufacturer_b.json",
278 R"([
279 ["printer_c", "printer_c_ref"],
280 ["printer_e", "printer_e_ref"]
281 ])"},
282 {"metadata_v2/reverse_index-en-01.json",
283 R"([
284 ["printer_a_ref", "manufacturer_a_en", "printer_a"]
285 ])"},
286 {"metadata_v2/reverse_index-en-19.json",
287 R"([
288 ])"},
289 {"metadata_v2/manufacturer_b.json",
290 R"([
291 ["printer_c", "printer_c_ref",
292 {"max_milestone":55.0000}],
293 ["printer_e", "printer_e_ref",
294 {"min_milestone":17.0000, "max_milestone":33.0000}]
295 ])"},
296 {"ppds/printer_a.ppd", kCupsFilterPpdContents},
297 {"ppds/printer_b.ppd", kCupsFilter2PpdContents},
298 {"ppds/printer_c.ppd", "c"},
299 {"ppds/printer_d.ppd", "d"},
300 {"ppds/printer_e.ppd", "e"},
301 {"user_supplied_ppd_directory/user_supplied.ppd", "u"}};
302 }
303
skau4fb6e692017-06-20 21:27:52304 // Environment for task schedulers.
Gabriel Charette694c3c332019-08-19 14:53:05305 base::test::TaskEnvironment task_environment_;
justincarlson2fc4d82b2017-02-03 22:49:47306
307 std::vector<
308 std::pair<PpdProvider::CallbackResultCode, std::vector<std::string>>>
309 captured_resolve_manufacturers_;
310
Justin Carlson97bf1add2017-07-21 18:31:14311 std::vector<std::pair<PpdProvider::CallbackResultCode,
312 PpdProvider::ResolvedPrintersList>>
justincarlson2fc4d82b2017-02-03 22:49:47313 captured_resolve_printers_;
314
justincarlson96bf4bd82017-04-12 19:14:46315 struct CapturedResolvePpdResults {
316 PpdProvider::CallbackResultCode code;
317 std::string ppd_contents;
318 std::vector<std::string> ppd_filters;
319 };
320 std::vector<CapturedResolvePpdResults> captured_resolve_ppd_;
justincarlson2fc4d82b2017-02-03 22:49:47321
Jimmy Gong533177732019-04-26 19:13:19322 struct CapturedResolvePpdReferenceResults {
323 PpdProvider::CallbackResultCode code;
324 Printer::PpdReference ref;
325 std::string usb_manufacturer;
326 };
327
328 std::vector<CapturedResolvePpdReferenceResults>
Justin Carlson97bf1add2017-07-21 18:31:14329 captured_resolve_ppd_references_;
justincarlson9d5b7af2017-02-14 23:04:49330
Sean Kau7f57a922017-08-01 19:00:26331 struct CapturedReverseLookup {
332 PpdProvider::CallbackResultCode code;
333 std::string manufacturer;
334 std::string model;
335 };
336 std::vector<CapturedReverseLookup> captured_reverse_lookup_;
337
justincarlsonc7d4aa6c2016-10-25 15:12:10338 base::ScopedTempDir ppd_cache_temp_dir_;
justincarlson2fc4d82b2017-02-03 22:49:47339 base::ScopedTempDir interceptor_temp_dir_;
justincarlsonc7d4aa6c2016-10-25 15:12:10340
Justin Carlsond9a046142018-01-24 17:56:06341 // Reference to the underlying ppd_cache_ so we can muck with it to test
342 // cache-dependent behavior of ppd_provider_.
343 scoped_refptr<PpdCache> ppd_cache_;
justincarlsonc7d4aa6c2016-10-25 15:12:10344
345 // Misc extra stuff needed for the test environment to function.
justincarlson2fc4d82b2017-02-03 22:49:47346 // base::TestMessageLoop loop_;
Luum Habtemariamb30c8112018-06-25 21:51:22347 network::TestURLLoaderFactory loader_factory_;
justincarlsonc7d4aa6c2016-10-25 15:12:10348};
349
justincarlson2fc4d82b2017-02-03 22:49:47350// Test that we get back manufacturer maps as expected.
351TEST_F(PpdProviderTest, ManufacturersFetch) {
352 StartFakePpdServer();
Justin Carlsond9a046142018-01-24 17:56:06353 auto provider = CreateProvider("en", false);
justincarlson2fc4d82b2017-02-03 22:49:47354 // Issue two requests at the same time, both should be resolved properly.
Luum Habtemariam0517d812018-01-26 17:56:05355 provider->ResolveManufacturers(base::BindOnce(
justincarlson2fc4d82b2017-02-03 22:49:47356 &PpdProviderTest::CaptureResolveManufacturers, base::Unretained(this)));
Luum Habtemariam0517d812018-01-26 17:56:05357 provider->ResolveManufacturers(base::BindOnce(
justincarlson2fc4d82b2017-02-03 22:49:47358 &PpdProviderTest::CaptureResolveManufacturers, base::Unretained(this)));
Gabriel Charette694c3c332019-08-19 14:53:05359 task_environment_.RunUntilIdle();
justincarlson2fc4d82b2017-02-03 22:49:47360 ASSERT_EQ(2UL, captured_resolve_manufacturers_.size());
361 std::vector<std::string> expected_result(
362 {"manufacturer_a_en", "manufacturer_b_en"});
363 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_manufacturers_[0].first);
364 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_manufacturers_[1].first);
365 EXPECT_TRUE(captured_resolve_manufacturers_[0].second == expected_result);
366 EXPECT_TRUE(captured_resolve_manufacturers_[1].second == expected_result);
justincarlsonc7d4aa6c2016-10-25 15:12:10367}
368
justincarlson2fc4d82b2017-02-03 22:49:47369// Test that we get a reasonable error when we have no server to contact. Tis
370// is almost exactly the same as the above test, we just don't bring up the fake
371// server first.
372TEST_F(PpdProviderTest, ManufacturersFetchNoServer) {
Justin Carlsond9a046142018-01-24 17:56:06373 auto provider = CreateProvider("en", false);
justincarlson2fc4d82b2017-02-03 22:49:47374 // Issue two requests at the same time, both should be resolved properly.
Luum Habtemariam0517d812018-01-26 17:56:05375 provider->ResolveManufacturers(base::BindOnce(
justincarlson2fc4d82b2017-02-03 22:49:47376 &PpdProviderTest::CaptureResolveManufacturers, base::Unretained(this)));
Luum Habtemariam0517d812018-01-26 17:56:05377 provider->ResolveManufacturers(base::BindOnce(
justincarlson2fc4d82b2017-02-03 22:49:47378 &PpdProviderTest::CaptureResolveManufacturers, base::Unretained(this)));
Gabriel Charette694c3c332019-08-19 14:53:05379 task_environment_.RunUntilIdle();
justincarlson2fc4d82b2017-02-03 22:49:47380 ASSERT_EQ(2UL, captured_resolve_manufacturers_.size());
381 EXPECT_EQ(PpdProvider::SERVER_ERROR,
382 captured_resolve_manufacturers_[0].first);
383 EXPECT_EQ(PpdProvider::SERVER_ERROR,
384 captured_resolve_manufacturers_[1].first);
385 EXPECT_TRUE(captured_resolve_manufacturers_[0].second.empty());
386 EXPECT_TRUE(captured_resolve_manufacturers_[1].second.empty());
justincarlsonc7d4aa6c2016-10-25 15:12:10387}
388
justincarlson2fc4d82b2017-02-03 22:49:47389// Test that we get things in the requested locale, and that fallbacks are sane.
390TEST_F(PpdProviderTest, LocalizationAndFallbacks) {
391 StartFakePpdServer();
392 RunLocalizationTest("en-gb", "en-gb");
393 RunLocalizationTest("en-blah", "en");
394 RunLocalizationTest("en-gb-foo", "en-gb");
395 RunLocalizationTest("es", "es-mx");
396 RunLocalizationTest("bogus", "en");
397}
398
Sean Kau698756b2017-08-24 20:01:18399// Tests that mutiples requests for make-and-model resolution can be fulfilled
400// simultaneously.
401TEST_F(PpdProviderTest, RepeatedMakeModel) {
402 StartFakePpdServer();
Justin Carlsond9a046142018-01-24 17:56:06403 auto provider = CreateProvider("en", false);
Sean Kau698756b2017-08-24 20:01:18404
Luum Habtemariam2cbe8352019-01-25 20:57:52405 PrinterSearchData unrecognized_printer;
Luum Habtemariam521c6872019-07-11 20:12:46406 unrecognized_printer.discovery_type = PrinterDiscoveryType::kManual;
Sean Kau698756b2017-08-24 20:01:18407 unrecognized_printer.make_and_model = {"Printer Printer"};
408
Luum Habtemariam2cbe8352019-01-25 20:57:52409 PrinterSearchData recognized_printer;
Luum Habtemariam521c6872019-07-11 20:12:46410 recognized_printer.discovery_type = PrinterDiscoveryType::kManual;
Sean Kau698756b2017-08-24 20:01:18411 recognized_printer.make_and_model = {"printer_a_ref"};
412
Luum Habtemariam2cbe8352019-01-25 20:57:52413 PrinterSearchData mixed;
Luum Habtemariam521c6872019-07-11 20:12:46414 mixed.discovery_type = PrinterDiscoveryType::kManual;
Sean Kau698756b2017-08-24 20:01:18415 mixed.make_and_model = {"printer_a_ref", "Printer Printer"};
416
417 // Resolve the same thing repeatedly.
418 provider->ResolvePpdReference(
419 unrecognized_printer,
Luum Habtemariam0517d812018-01-26 17:56:05420 base::BindOnce(&PpdProviderTest::CaptureResolvePpdReference,
421 base::Unretained(this)));
Sean Kau698756b2017-08-24 20:01:18422 provider->ResolvePpdReference(
Luum Habtemariam0517d812018-01-26 17:56:05423 mixed, base::BindOnce(&PpdProviderTest::CaptureResolvePpdReference,
424 base::Unretained(this)));
Sean Kau698756b2017-08-24 20:01:18425 provider->ResolvePpdReference(
426 recognized_printer,
Luum Habtemariam0517d812018-01-26 17:56:05427 base::BindOnce(&PpdProviderTest::CaptureResolvePpdReference,
428 base::Unretained(this)));
Gabriel Charette694c3c332019-08-19 14:53:05429 task_environment_.RunUntilIdle();
Sean Kau698756b2017-08-24 20:01:18430
431 ASSERT_EQ(static_cast<size_t>(3), captured_resolve_ppd_references_.size());
Jimmy Gong533177732019-04-26 19:13:19432 EXPECT_EQ(PpdProvider::NOT_FOUND, captured_resolve_ppd_references_[0].code);
433 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_references_[1].code);
434 EXPECT_EQ("printer_a_ref",
435 captured_resolve_ppd_references_[1].ref.effective_make_and_model);
436 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_references_[2].code);
437 EXPECT_EQ("printer_a_ref",
438 captured_resolve_ppd_references_[2].ref.effective_make_and_model);
Sean Kau698756b2017-08-24 20:01:18439}
440
justincarlson9d5b7af2017-02-14 23:04:49441// Test successful and unsuccessful usb resolutions.
442TEST_F(PpdProviderTest, UsbResolution) {
443 StartFakePpdServer();
Justin Carlsond9a046142018-01-24 17:56:06444 auto provider = CreateProvider("en", false);
justincarlson9d5b7af2017-02-14 23:04:49445
Luum Habtemariam2cbe8352019-01-25 20:57:52446 PrinterSearchData search_data;
Luum Habtemariam521c6872019-07-11 20:12:46447 search_data.discovery_type = PrinterDiscoveryType::kUsb;
Justin Carlson97bf1add2017-07-21 18:31:14448
justincarlson9d5b7af2017-02-14 23:04:49449 // Should get back "Some canonical reference"
Justin Carlson97bf1add2017-07-21 18:31:14450 search_data.usb_vendor_id = 0x031f;
451 search_data.usb_product_id = 1592;
452 provider->ResolvePpdReference(
Luum Habtemariam0517d812018-01-26 17:56:05453 search_data, base::BindOnce(&PpdProviderTest::CaptureResolvePpdReference,
454 base::Unretained(this)));
justincarlson9d5b7af2017-02-14 23:04:49455 // Should get back "Some other canonical reference"
Justin Carlson97bf1add2017-07-21 18:31:14456 search_data.usb_vendor_id = 0x031f;
457 search_data.usb_product_id = 6535;
458 provider->ResolvePpdReference(
Luum Habtemariam0517d812018-01-26 17:56:05459 search_data, base::BindOnce(&PpdProviderTest::CaptureResolvePpdReference,
460 base::Unretained(this)));
justincarlson9d5b7af2017-02-14 23:04:49461
Jimmy Gong533177732019-04-26 19:13:19462 // Vendor id that exists, nonexistent device id, should get a NOT_FOUND.
Justin Carlson97bf1add2017-07-21 18:31:14463 search_data.usb_vendor_id = 0x031f;
464 search_data.usb_product_id = 8162;
465 provider->ResolvePpdReference(
Luum Habtemariam0517d812018-01-26 17:56:05466 search_data, base::BindOnce(&PpdProviderTest::CaptureResolvePpdReference,
467 base::Unretained(this)));
justincarlson9d5b7af2017-02-14 23:04:49468
Jimmy Gong533177732019-04-26 19:13:19469 // Nonexistent vendor id, should get a NOT_FOUND in the real world, but
470 // the URL interceptor we're using considers all nonexistent files to
justincarlson9d5b7af2017-02-14 23:04:49471 // be effectively CONNECTION REFUSED, so we just check for non-success
472 // on this one.
Luum Habtemariamb30c8112018-06-25 21:51:22473 search_data.usb_vendor_id = 0x1234;
Justin Carlson97bf1add2017-07-21 18:31:14474 search_data.usb_product_id = 1782;
475 provider->ResolvePpdReference(
Luum Habtemariam0517d812018-01-26 17:56:05476 search_data, base::BindOnce(&PpdProviderTest::CaptureResolvePpdReference,
477 base::Unretained(this)));
Gabriel Charette694c3c332019-08-19 14:53:05478 task_environment_.RunUntilIdle();
justincarlson9d5b7af2017-02-14 23:04:49479
Justin Carlson97bf1add2017-07-21 18:31:14480 ASSERT_EQ(captured_resolve_ppd_references_.size(), static_cast<size_t>(4));
Jimmy Gong533177732019-04-26 19:13:19481 EXPECT_EQ(captured_resolve_ppd_references_[0].code, PpdProvider::SUCCESS);
482 EXPECT_EQ(captured_resolve_ppd_references_[0].ref.effective_make_and_model,
Justin Carlson97bf1add2017-07-21 18:31:14483 "Some canonical reference");
Jimmy Gong533177732019-04-26 19:13:19484 EXPECT_EQ(captured_resolve_ppd_references_[1].code, PpdProvider::SUCCESS);
485 EXPECT_EQ(captured_resolve_ppd_references_[1].ref.effective_make_and_model,
justincarlson9d5b7af2017-02-14 23:04:49486 "Some other canonical reference");
Jimmy Gong533177732019-04-26 19:13:19487 EXPECT_EQ(captured_resolve_ppd_references_[2].code, PpdProvider::NOT_FOUND);
488 EXPECT_FALSE(captured_resolve_ppd_references_[3].code ==
Justin Carlson97bf1add2017-07-21 18:31:14489 PpdProvider::SUCCESS);
justincarlson9d5b7af2017-02-14 23:04:49490}
491
justincarlson2fc4d82b2017-02-03 22:49:47492// For convenience a null ResolveManufacturers callback target.
493void ResolveManufacturersNop(PpdProvider::CallbackResultCode code,
494 const std::vector<std::string>& v) {}
495
496// Test basic ResolvePrinters() functionality. At the same time, make
497// sure we can get the PpdReference for each of the resolved printers.
498TEST_F(PpdProviderTest, ResolvePrinters) {
499 StartFakePpdServer();
Justin Carlsond9a046142018-01-24 17:56:06500 auto provider = CreateProvider("en", false);
justincarlson2fc4d82b2017-02-03 22:49:47501
502 // Grab the manufacturer list, but don't bother to save it, we know what
503 // should be in it and we check that elsewhere. We just need to run the
504 // resolve to populate the internal PpdProvider structures.
Luum Habtemariam0517d812018-01-26 17:56:05505 provider->ResolveManufacturers(base::BindOnce(&ResolveManufacturersNop));
Gabriel Charette694c3c332019-08-19 14:53:05506 task_environment_.RunUntilIdle();
justincarlson2fc4d82b2017-02-03 22:49:47507
Luum Habtemariam0517d812018-01-26 17:56:05508 provider->ResolvePrinters(
509 "manufacturer_a_en",
510 base::BindOnce(&PpdProviderTest::CaptureResolvePrinters,
511 base::Unretained(this)));
512 provider->ResolvePrinters(
513 "manufacturer_b_en",
514 base::BindOnce(&PpdProviderTest::CaptureResolvePrinters,
515 base::Unretained(this)));
Luum Habtemariam67e8adb822018-01-04 16:04:47516
Gabriel Charette694c3c332019-08-19 14:53:05517 task_environment_.RunUntilIdle();
justincarlson2fc4d82b2017-02-03 22:49:47518 ASSERT_EQ(2UL, captured_resolve_printers_.size());
519 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_printers_[0].first);
520 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_printers_[1].first);
521 EXPECT_EQ(2UL, captured_resolve_printers_[0].second.size());
justincarlson2fc4d82b2017-02-03 22:49:47522
Justin Carlson97bf1add2017-07-21 18:31:14523 // First capture should get back printer_a, and printer_b, with ppd
524 // reference effective make and models of printer_a_ref and printer_b_ref.
525 const auto& capture0 = captured_resolve_printers_[0].second;
526 ASSERT_EQ(2UL, capture0.size());
Luum Habtemariam67e8adb822018-01-04 16:04:47527 EXPECT_EQ("printer_a", capture0[0].name);
528 EXPECT_EQ("printer_a_ref", capture0[0].ppd_ref.effective_make_and_model);
Justin Carlson97bf1add2017-07-21 18:31:14529
Luum Habtemariam67e8adb822018-01-04 16:04:47530 EXPECT_EQ("printer_b", capture0[1].name);
531 EXPECT_EQ("printer_b_ref", capture0[1].ppd_ref.effective_make_and_model);
Justin Carlson97bf1add2017-07-21 18:31:14532
533 // Second capture should get back printer_c with effective make and model of
534 // printer_c_ref
535 const auto& capture1 = captured_resolve_printers_[1].second;
536 ASSERT_EQ(1UL, capture1.size());
Luum Habtemariam67e8adb822018-01-04 16:04:47537 EXPECT_EQ("printer_c", capture1[0].name);
538 EXPECT_EQ("printer_c_ref", capture1[0].ppd_ref.effective_make_and_model);
539 // EXPECT_EQ(base::Version("55"), capture1[0].restrictions.max_milestone);
justincarlson2fc4d82b2017-02-03 22:49:47540}
541
542// Test that if we give a bad reference to ResolvePrinters(), we get an
543// INTERNAL_ERROR.
544TEST_F(PpdProviderTest, ResolvePrintersBadReference) {
545 StartFakePpdServer();
Justin Carlsond9a046142018-01-24 17:56:06546 auto provider = CreateProvider("en", false);
Luum Habtemariam0517d812018-01-26 17:56:05547 provider->ResolveManufacturers(base::BindOnce(&ResolveManufacturersNop));
Gabriel Charette694c3c332019-08-19 14:53:05548 task_environment_.RunUntilIdle();
justincarlson2fc4d82b2017-02-03 22:49:47549
Luum Habtemariam0517d812018-01-26 17:56:05550 provider->ResolvePrinters(
551 "bogus_doesnt_exist",
552 base::BindOnce(&PpdProviderTest::CaptureResolvePrinters,
553 base::Unretained(this)));
Gabriel Charette694c3c332019-08-19 14:53:05554 task_environment_.RunUntilIdle();
justincarlson2fc4d82b2017-02-03 22:49:47555 ASSERT_EQ(1UL, captured_resolve_printers_.size());
556 EXPECT_EQ(PpdProvider::INTERNAL_ERROR, captured_resolve_printers_[0].first);
557}
558
559// Test that if the server is unavailable, we get SERVER_ERRORs back out.
560TEST_F(PpdProviderTest, ResolvePrintersNoServer) {
561 StartFakePpdServer();
Justin Carlsond9a046142018-01-24 17:56:06562 auto provider = CreateProvider("en", false);
Luum Habtemariam0517d812018-01-26 17:56:05563 provider->ResolveManufacturers(base::BindOnce(&ResolveManufacturersNop));
Gabriel Charette694c3c332019-08-19 14:53:05564 task_environment_.RunUntilIdle();
justincarlson2fc4d82b2017-02-03 22:49:47565
566 StopFakePpdServer();
567
Luum Habtemariam0517d812018-01-26 17:56:05568 provider->ResolvePrinters(
569 "manufacturer_a_en",
570 base::BindOnce(&PpdProviderTest::CaptureResolvePrinters,
571 base::Unretained(this)));
572 provider->ResolvePrinters(
573 "manufacturer_b_en",
574 base::BindOnce(&PpdProviderTest::CaptureResolvePrinters,
575 base::Unretained(this)));
Gabriel Charette694c3c332019-08-19 14:53:05576 task_environment_.RunUntilIdle();
justincarlson2fc4d82b2017-02-03 22:49:47577 ASSERT_EQ(2UL, captured_resolve_printers_.size());
578 EXPECT_EQ(PpdProvider::SERVER_ERROR, captured_resolve_printers_[0].first);
579 EXPECT_EQ(PpdProvider::SERVER_ERROR, captured_resolve_printers_[1].first);
580}
581
582// Test a successful ppd resolution from an effective_make_and_model reference.
583TEST_F(PpdProviderTest, ResolveServerKeyPpd) {
584 StartFakePpdServer();
Justin Carlsond9a046142018-01-24 17:56:06585 auto provider = CreateProvider("en", false);
justincarlson2fc4d82b2017-02-03 22:49:47586 Printer::PpdReference ref;
587 ref.effective_make_and_model = "printer_b_ref";
Luum Habtemariam0517d812018-01-26 17:56:05588 provider->ResolvePpd(ref, base::BindOnce(&PpdProviderTest::CaptureResolvePpd,
589 base::Unretained(this)));
justincarlson2fc4d82b2017-02-03 22:49:47590 ref.effective_make_and_model = "printer_c_ref";
Luum Habtemariam0517d812018-01-26 17:56:05591 provider->ResolvePpd(ref, base::BindOnce(&PpdProviderTest::CaptureResolvePpd,
592 base::Unretained(this)));
Gabriel Charette694c3c332019-08-19 14:53:05593 task_environment_.RunUntilIdle();
justincarlson2fc4d82b2017-02-03 22:49:47594
595 ASSERT_EQ(2UL, captured_resolve_ppd_.size());
justincarlson96bf4bd82017-04-12 19:14:46596 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_[0].code);
597 EXPECT_EQ(kCupsFilter2PpdContents, captured_resolve_ppd_[0].ppd_contents);
598 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_[1].code);
599 EXPECT_EQ("c", captured_resolve_ppd_[1].ppd_contents);
justincarlson2fc4d82b2017-02-03 22:49:47600}
601
602// Test that we *don't* resolve a ppd URL over non-file schemes. It's not clear
603// whether we'll want to do this in the long term, but for now this is
604// disallowed because we're not sure we completely understand the security
605// implications.
606TEST_F(PpdProviderTest, ResolveUserSuppliedUrlPpdFromNetworkFails) {
607 StartFakePpdServer();
Justin Carlsond9a046142018-01-24 17:56:06608 auto provider = CreateProvider("en", false);
justincarlson2fc4d82b2017-02-03 22:49:47609
610 Printer::PpdReference ref;
611 ref.user_supplied_ppd_url = base::StringPrintf(
612 "https://%s/user_supplied_ppd_directory/user_supplied.ppd", kPpdServer);
Luum Habtemariam0517d812018-01-26 17:56:05613 provider->ResolvePpd(ref, base::BindOnce(&PpdProviderTest::CaptureResolvePpd,
614 base::Unretained(this)));
Gabriel Charette694c3c332019-08-19 14:53:05615 task_environment_.RunUntilIdle();
justincarlson2fc4d82b2017-02-03 22:49:47616
617 ASSERT_EQ(1UL, captured_resolve_ppd_.size());
justincarlson96bf4bd82017-04-12 19:14:46618 EXPECT_EQ(PpdProvider::INTERNAL_ERROR, captured_resolve_ppd_[0].code);
619 EXPECT_TRUE(captured_resolve_ppd_[0].ppd_contents.empty());
justincarlson2fc4d82b2017-02-03 22:49:47620}
621
622// Test a successful ppd resolution from a user_supplied_url field when
623// reading from a file. Note we shouldn't need the server to be up
624// to do this successfully, as we should be able to do this offline.
625TEST_F(PpdProviderTest, ResolveUserSuppliedUrlPpdFromFile) {
Justin Carlsond9a046142018-01-24 17:56:06626 auto provider = CreateProvider("en", false);
justincarlsonc7d4aa6c2016-10-25 15:12:10627 base::ScopedTempDir temp_dir;
justincarlson9c860c82016-11-01 17:46:36628 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
justincarlson2fc4d82b2017-02-03 22:49:47629 base::FilePath filename = temp_dir.GetPath().Append("my_spiffy.ppd");
justincarlsonc7d4aa6c2016-10-25 15:12:10630
justincarlson2fc4d82b2017-02-03 22:49:47631 std::string user_ppd_contents = "Woohoo";
justincarlsonc7d4aa6c2016-10-25 15:12:10632
justincarlson2fc4d82b2017-02-03 22:49:47633 ASSERT_EQ(base::WriteFile(filename, user_ppd_contents.data(),
634 user_ppd_contents.size()),
635 static_cast<int>(user_ppd_contents.size()));
justincarlsonc7d4aa6c2016-10-25 15:12:10636
justincarlson2fc4d82b2017-02-03 22:49:47637 Printer::PpdReference ref;
638 ref.user_supplied_ppd_url =
639 base::StringPrintf("file://%s", filename.MaybeAsASCII().c_str());
Luum Habtemariam0517d812018-01-26 17:56:05640 provider->ResolvePpd(ref, base::BindOnce(&PpdProviderTest::CaptureResolvePpd,
641 base::Unretained(this)));
Gabriel Charette694c3c332019-08-19 14:53:05642 task_environment_.RunUntilIdle();
justincarlsonc7d4aa6c2016-10-25 15:12:10643
justincarlson2fc4d82b2017-02-03 22:49:47644 ASSERT_EQ(1UL, captured_resolve_ppd_.size());
justincarlson96bf4bd82017-04-12 19:14:46645 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_[0].code);
646 EXPECT_EQ(user_ppd_contents, captured_resolve_ppd_[0].ppd_contents);
justincarlsonc7d4aa6c2016-10-25 15:12:10647}
648
justincarlson2fc4d82b2017-02-03 22:49:47649// Test that we cache ppd resolutions when we fetch them and that we can resolve
650// from the cache without the server available.
651TEST_F(PpdProviderTest, ResolvedPpdsGetCached) {
Justin Carlsond9a046142018-01-24 17:56:06652 auto provider = CreateProvider("en", false);
justincarlson2fc4d82b2017-02-03 22:49:47653 std::string user_ppd_contents = "Woohoo";
654 Printer::PpdReference ref;
justincarlsonc7d4aa6c2016-10-25 15:12:10655 {
656 base::ScopedTempDir temp_dir;
justincarlson9c860c82016-11-01 17:46:36657 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
justincarlson2fc4d82b2017-02-03 22:49:47658 base::FilePath filename = temp_dir.GetPath().Append("my_spiffy.ppd");
justincarlsonc7d4aa6c2016-10-25 15:12:10659
justincarlson2fc4d82b2017-02-03 22:49:47660 ASSERT_EQ(base::WriteFile(filename, user_ppd_contents.data(),
661 user_ppd_contents.size()),
662 static_cast<int>(user_ppd_contents.size()));
663
664 ref.user_supplied_ppd_url =
665 base::StringPrintf("file://%s", filename.MaybeAsASCII().c_str());
Luum Habtemariam0517d812018-01-26 17:56:05666 provider->ResolvePpd(ref,
667 base::BindOnce(&PpdProviderTest::CaptureResolvePpd,
668 base::Unretained(this)));
Gabriel Charette694c3c332019-08-19 14:53:05669 task_environment_.RunUntilIdle();
justincarlson2fc4d82b2017-02-03 22:49:47670
671 ASSERT_EQ(1UL, captured_resolve_ppd_.size());
justincarlson96bf4bd82017-04-12 19:14:46672 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_[0].code);
673 EXPECT_EQ(user_ppd_contents, captured_resolve_ppd_[0].ppd_contents);
justincarlsonc7d4aa6c2016-10-25 15:12:10674 }
justincarlson2fc4d82b2017-02-03 22:49:47675 // ScopedTempDir goes out of scope, so the source file should now be
676 // deleted. But if we resolve again, we should hit the cache and
677 // still be successful.
justincarlsonc7d4aa6c2016-10-25 15:12:10678
justincarlson2fc4d82b2017-02-03 22:49:47679 captured_resolve_ppd_.clear();
justincarlsonc7d4aa6c2016-10-25 15:12:10680
justincarlson2fc4d82b2017-02-03 22:49:47681 // Recreate the provider to make sure we don't have any memory caches which
682 // would mask problems with disk persistence.
Justin Carlsond9a046142018-01-24 17:56:06683 provider = CreateProvider("en", false);
justincarlsonc7d4aa6c2016-10-25 15:12:10684
justincarlson2fc4d82b2017-02-03 22:49:47685 // Re-resolve.
Luum Habtemariam0517d812018-01-26 17:56:05686 provider->ResolvePpd(ref, base::BindOnce(&PpdProviderTest::CaptureResolvePpd,
687 base::Unretained(this)));
Gabriel Charette694c3c332019-08-19 14:53:05688 task_environment_.RunUntilIdle();
justincarlson9c860c82016-11-01 17:46:36689
justincarlson2fc4d82b2017-02-03 22:49:47690 ASSERT_EQ(1UL, captured_resolve_ppd_.size());
justincarlson96bf4bd82017-04-12 19:14:46691 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_[0].code);
692 EXPECT_EQ(user_ppd_contents, captured_resolve_ppd_[0].ppd_contents);
693}
694
695// Test that the filter extraction code successfully pulls the filters
696// from the ppds resolved.
697TEST_F(PpdProviderTest, ExtractPpdFilters) {
698 StartFakePpdServer();
Justin Carlsond9a046142018-01-24 17:56:06699 auto provider = CreateProvider("en", false);
justincarlson96bf4bd82017-04-12 19:14:46700 Printer::PpdReference ref;
701 ref.effective_make_and_model = "printer_a_ref";
Luum Habtemariam0517d812018-01-26 17:56:05702 provider->ResolvePpd(ref, base::BindOnce(&PpdProviderTest::CaptureResolvePpd,
703 base::Unretained(this)));
justincarlson96bf4bd82017-04-12 19:14:46704 ref.effective_make_and_model = "printer_b_ref";
Luum Habtemariam0517d812018-01-26 17:56:05705 provider->ResolvePpd(ref, base::BindOnce(&PpdProviderTest::CaptureResolvePpd,
706 base::Unretained(this)));
justincarlson96bf4bd82017-04-12 19:14:46707
Gabriel Charette694c3c332019-08-19 14:53:05708 task_environment_.RunUntilIdle();
Justin Carlson781f77e212017-11-15 22:32:31709
710 std::sort(captured_resolve_ppd_[0].ppd_filters.begin(),
711 captured_resolve_ppd_[0].ppd_filters.end());
Luum Habtemariam8f4a22c2018-04-14 10:09:41712 ASSERT_EQ(2UL, captured_resolve_ppd_.size());
713 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_[0].code);
714 EXPECT_EQ(kCupsFilterPpdContents, captured_resolve_ppd_[0].ppd_contents);
justincarlson96bf4bd82017-04-12 19:14:46715 EXPECT_EQ(
716 std::vector<std::string>({"a_different_filter", "filter3", "my_filter"}),
717 captured_resolve_ppd_[0].ppd_filters);
718
Justin Carlson781f77e212017-11-15 22:32:31719 std::sort(captured_resolve_ppd_[1].ppd_filters.begin(),
720 captured_resolve_ppd_[1].ppd_filters.end());
justincarlson96bf4bd82017-04-12 19:14:46721 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_[1].code);
722 EXPECT_EQ(kCupsFilter2PpdContents, captured_resolve_ppd_[1].ppd_contents);
723 EXPECT_EQ(
724 std::vector<std::string>({"another_real_filter", "the_real_filter"}),
725 captured_resolve_ppd_[1].ppd_filters);
justincarlson9c860c82016-11-01 17:46:36726}
727
Luum Habtemariam8f4a22c2018-04-14 10:09:41728// Test that all entrypoints will correctly work with case-insensitve
729// effective-make-and-model strings.
730TEST_F(PpdProviderTest, CaseInsensitiveMakeAndModel) {
731 StartFakePpdServer();
732 auto provider = CreateProvider("en", false);
733 std::string ref = "pRiNteR_A_reF";
734
735 Printer::PpdReference ppd_ref;
736 ppd_ref.effective_make_and_model = ref;
737 provider->ResolvePpd(ppd_ref,
738 base::BindOnce(&PpdProviderTest::CaptureResolvePpd,
739 base::Unretained(this)));
740 provider->ReverseLookup(ref,
741 base::BindOnce(&PpdProviderTest::CaptureReverseLookup,
742 base::Unretained(this)));
Luum Habtemariam2cbe8352019-01-25 20:57:52743 PrinterSearchData printer_info;
Luum Habtemariam8f4a22c2018-04-14 10:09:41744 printer_info.make_and_model = {ref};
745 provider->ResolvePpdReference(
746 printer_info, base::BindOnce(&PpdProviderTest::CaptureResolvePpdReference,
747 base::Unretained(this)));
Gabriel Charette694c3c332019-08-19 14:53:05748 task_environment_.RunUntilIdle();
Luum Habtemariam8f4a22c2018-04-14 10:09:41749
750 std::sort(captured_resolve_ppd_[0].ppd_filters.begin(),
751 captured_resolve_ppd_[0].ppd_filters.end());
752
753 // Check PpdProvider::ResolvePpd
754 ASSERT_EQ(1UL, captured_resolve_ppd_.size());
755 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_[0].code);
756 EXPECT_EQ(kCupsFilterPpdContents, captured_resolve_ppd_[0].ppd_contents);
757
758 // Check PpdProvider::ReverseLookup
759 ASSERT_EQ(1UL, captured_reverse_lookup_.size());
760 EXPECT_EQ(PpdProvider::SUCCESS, captured_reverse_lookup_[0].code);
761 EXPECT_EQ("manufacturer_a_en", captured_reverse_lookup_[0].manufacturer);
762 EXPECT_EQ("printer_a", captured_reverse_lookup_[0].model);
763
764 // Check PpdProvider::ResolvePpdReference
765 ASSERT_EQ(1UL, captured_resolve_ppd_references_.size());
Jimmy Gong533177732019-04-26 19:13:19766 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_references_[0].code);
767 EXPECT_EQ("printer_a_ref",
768 captured_resolve_ppd_references_[0].ref.effective_make_and_model);
Luum Habtemariam8f4a22c2018-04-14 10:09:41769}
770
Sean Kau7f57a922017-08-01 19:00:26771// Verifies that we can extract the Manufacturer and Model selectison for a
772// given effective make and model.
773TEST_F(PpdProviderTest, ReverseLookup) {
774 StartFakePpdServer();
Justin Carlsond9a046142018-01-24 17:56:06775 auto provider = CreateProvider("en", false);
Sean Kau7f57a922017-08-01 19:00:26776 std::string ref = "printer_a_ref";
777 provider->ReverseLookup(ref,
Luum Habtemariam0517d812018-01-26 17:56:05778 base::BindOnce(&PpdProviderTest::CaptureReverseLookup,
779 base::Unretained(this)));
Sean Kau7f57a922017-08-01 19:00:26780 // TODO(skau): PpdProvider has a race condition that prevents running these
781 // requests in parallel.
Gabriel Charette694c3c332019-08-19 14:53:05782 task_environment_.RunUntilIdle();
Sean Kau7f57a922017-08-01 19:00:26783
784 std::string ref_fail = "printer_does_not_exist";
785 provider->ReverseLookup(ref_fail,
Luum Habtemariam0517d812018-01-26 17:56:05786 base::BindOnce(&PpdProviderTest::CaptureReverseLookup,
787 base::Unretained(this)));
Gabriel Charette694c3c332019-08-19 14:53:05788 task_environment_.RunUntilIdle();
Sean Kau7f57a922017-08-01 19:00:26789
790 ASSERT_EQ(2U, captured_reverse_lookup_.size());
791 CapturedReverseLookup success_capture = captured_reverse_lookup_[0];
792 EXPECT_EQ(PpdProvider::SUCCESS, success_capture.code);
793 EXPECT_EQ("manufacturer_a_en", success_capture.manufacturer);
794 EXPECT_EQ("printer_a", success_capture.model);
795
796 CapturedReverseLookup failed_capture = captured_reverse_lookup_[1];
797 EXPECT_EQ(PpdProvider::NOT_FOUND, failed_capture.code);
798}
799
Justin Carlsond9a046142018-01-24 17:56:06800// If we have a fresh entry in the cache, we shouldn't need to go out to the
801// network at all to successfully resolve a ppd.
802TEST_F(PpdProviderTest, FreshCacheHitNoNetworkTraffic) {
803 // Explicitly *not* starting a fake server.
804 std::string cached_ppd_contents =
805 "These cached contents are different from what's being served";
806 auto provider = CreateProvider("en", true);
807 Printer::PpdReference ref;
808 ref.effective_make_and_model = "printer_a_ref";
809 std::string cache_key = PpdProvider::PpdReferenceToCacheKey(ref);
810 // Cache exists, and is just created, so should be fresh.
811 ppd_cache_->StoreForTesting(PpdProvider::PpdReferenceToCacheKey(ref),
812 cached_ppd_contents, base::TimeDelta());
Gabriel Charette694c3c332019-08-19 14:53:05813 task_environment_.RunUntilIdle();
tzikc8fdd6c32018-04-11 04:02:40814 provider->ResolvePpd(ref, base::BindOnce(&PpdProviderTest::CaptureResolvePpd,
815 base::Unretained(this)));
Gabriel Charette694c3c332019-08-19 14:53:05816 task_environment_.RunUntilIdle();
Justin Carlsond9a046142018-01-24 17:56:06817 ASSERT_EQ(1UL, captured_resolve_ppd_.size());
818
819 // Should get the cached (not served) results back, and not have hit the
820 // network.
821 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_[0].code);
822 EXPECT_EQ(cached_ppd_contents, captured_resolve_ppd_[0].ppd_contents);
823}
824
825// If we have a stale cache entry and a good network connection, does the cache
826// get refreshed during a resolution?
827TEST_F(PpdProviderTest, StaleCacheGetsRefreshed) {
828 StartFakePpdServer();
829 std::string cached_ppd_contents =
830 "These cached contents are different from what's being served";
831 auto provider = CreateProvider("en", true);
832 // printer_ref_a resolves to kCupsFilterPpdContents on the server.
833 std::string expected_ppd = kCupsFilterPpdContents;
834 Printer::PpdReference ref;
835 ref.effective_make_and_model = "printer_a_ref";
836 std::string cache_key = PpdProvider::PpdReferenceToCacheKey(ref);
837 // Cache exists, and is 6 months old, so really stale.
838 ppd_cache_->StoreForTesting(PpdProvider::PpdReferenceToCacheKey(ref),
839 cached_ppd_contents,
840 base::TimeDelta::FromDays(180));
Gabriel Charette694c3c332019-08-19 14:53:05841 task_environment_.RunUntilIdle();
tzikc8fdd6c32018-04-11 04:02:40842 provider->ResolvePpd(ref, base::BindOnce(&PpdProviderTest::CaptureResolvePpd,
843 base::Unretained(this)));
Gabriel Charette694c3c332019-08-19 14:53:05844 task_environment_.RunUntilIdle();
Justin Carlsond9a046142018-01-24 17:56:06845 ASSERT_EQ(1UL, captured_resolve_ppd_.size());
846
847 // Should get the served results back, not the stale cached ones.
848 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_[0].code);
849 EXPECT_EQ(captured_resolve_ppd_[0].ppd_contents, expected_ppd);
Justin Carlsond9a046142018-01-24 17:56:06850
851 // Check that the cache was also updated.
852 PpdCache::FindResult captured_find_result;
853 // This is just a complicated syntax around the idea "use the Find callback to
854 // save the result in captured_find_result.
855 ppd_cache_->Find(PpdProvider::PpdReferenceToCacheKey(ref),
856 base::BindOnce(
857 [](PpdCache::FindResult* captured_find_result,
858 const PpdCache::FindResult& find_result) {
859 *captured_find_result = find_result;
860 },
861 &captured_find_result));
Gabriel Charette694c3c332019-08-19 14:53:05862 task_environment_.RunUntilIdle();
Justin Carlsond9a046142018-01-24 17:56:06863 EXPECT_EQ(captured_find_result.success, true);
864 EXPECT_EQ(captured_find_result.contents, expected_ppd);
865 EXPECT_LT(captured_find_result.age, base::TimeDelta::FromDays(1));
866}
867
868// Test that, if we have an old entry in the cache that needs to be refreshed,
869// and we fail to contact the server, we still use the cached version.
870TEST_F(PpdProviderTest, StaleCacheGetsUsedIfNetworkFails) {
871 // Note that we're explicitly *not* starting the Fake ppd server in this test.
872 std::string cached_ppd_contents =
873 "These cached contents are different from what's being served";
874 auto provider = CreateProvider("en", true);
875 Printer::PpdReference ref;
876 ref.effective_make_and_model = "printer_a_ref";
877 std::string cache_key = PpdProvider::PpdReferenceToCacheKey(ref);
878 // Cache exists, and is 6 months old, so really stale.
879 ppd_cache_->StoreForTesting(PpdProvider::PpdReferenceToCacheKey(ref),
880 cached_ppd_contents,
881 base::TimeDelta::FromDays(180));
Gabriel Charette694c3c332019-08-19 14:53:05882 task_environment_.RunUntilIdle();
tzikc8fdd6c32018-04-11 04:02:40883 provider->ResolvePpd(ref, base::BindOnce(&PpdProviderTest::CaptureResolvePpd,
884 base::Unretained(this)));
Gabriel Charette694c3c332019-08-19 14:53:05885 task_environment_.RunUntilIdle();
Justin Carlsond9a046142018-01-24 17:56:06886 ASSERT_EQ(1UL, captured_resolve_ppd_.size());
887
888 // Should successfully resolve from the cache, even though it's stale.
889 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_[0].code);
890 EXPECT_EQ(cached_ppd_contents, captured_resolve_ppd_[0].ppd_contents);
891
892 // Check that the cache is *not* updated; it should remain stale.
893 PpdCache::FindResult captured_find_result;
894 // This is just a complicated syntax around the idea "use the Find callback to
895 // save the result in captured_find_result.
896 ppd_cache_->Find(PpdProvider::PpdReferenceToCacheKey(ref),
897 base::BindOnce(
898 [](PpdCache::FindResult* captured_find_result,
899 const PpdCache::FindResult& find_result) {
900 *captured_find_result = find_result;
901 },
902 &captured_find_result));
Gabriel Charette694c3c332019-08-19 14:53:05903 task_environment_.RunUntilIdle();
Justin Carlsond9a046142018-01-24 17:56:06904 EXPECT_EQ(captured_find_result.success, true);
905 EXPECT_EQ(captured_find_result.contents, cached_ppd_contents);
906 EXPECT_GT(captured_find_result.age, base::TimeDelta::FromDays(179));
907}
908
909// For user-provided ppds, we should always use the latest version on
910// disk if it still exists there.
911TEST_F(PpdProviderTest, UserPpdAlwaysRefreshedIfAvailable) {
912 base::ScopedTempDir temp_dir;
913 StartFakePpdServer();
914 std::string cached_ppd_contents = "Cached Ppd Contents";
915 std::string disk_ppd_contents = "Updated Ppd Contents";
916 auto provider = CreateProvider("en", true);
917 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
918 base::FilePath filename = temp_dir.GetPath().Append("my_spiffy.ppd");
919
920 Printer::PpdReference ref;
921 ref.user_supplied_ppd_url =
922 base::StringPrintf("file://%s", filename.MaybeAsASCII().c_str());
923
924 // Put cached_ppd_contents into the cache.
925 ppd_cache_->StoreForTesting(PpdProvider::PpdReferenceToCacheKey(ref),
926 cached_ppd_contents, base::TimeDelta());
Gabriel Charette694c3c332019-08-19 14:53:05927 task_environment_.RunUntilIdle();
Justin Carlsond9a046142018-01-24 17:56:06928
929 // Write different contents to disk, so that the cached contents are
930 // now stale.
931 ASSERT_EQ(base::WriteFile(filename, disk_ppd_contents.data(),
932 disk_ppd_contents.size()),
933 static_cast<int>(disk_ppd_contents.size()));
934
tzikc8fdd6c32018-04-11 04:02:40935 provider->ResolvePpd(ref, base::BindOnce(&PpdProviderTest::CaptureResolvePpd,
936 base::Unretained(this)));
Gabriel Charette694c3c332019-08-19 14:53:05937 task_environment_.RunUntilIdle();
Justin Carlsond9a046142018-01-24 17:56:06938 ASSERT_EQ(1UL, captured_resolve_ppd_.size());
939 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_[0].code);
940 EXPECT_EQ(disk_ppd_contents, captured_resolve_ppd_[0].ppd_contents);
941
942 // Check that the cache was also updated with the new contents.
943 PpdCache::FindResult captured_find_result;
944 ppd_cache_->Find(PpdProvider::PpdReferenceToCacheKey(ref),
945 base::BindOnce(
946 [](PpdCache::FindResult* captured_find_result,
947 const PpdCache::FindResult& find_result) {
948 *captured_find_result = find_result;
949 },
950 &captured_find_result));
Gabriel Charette694c3c332019-08-19 14:53:05951 task_environment_.RunUntilIdle();
Justin Carlsond9a046142018-01-24 17:56:06952 EXPECT_EQ(captured_find_result.success, true);
953 EXPECT_EQ(captured_find_result.contents, disk_ppd_contents);
954}
955
Jimmy Gong533177732019-04-26 19:13:19956// Test resolving usb manufacturer when failed to resolve PpdReference.
957TEST_F(PpdProviderTest, ResolveUsbManufacturer) {
958 StartFakePpdServer();
959 auto provider = CreateProvider("en", false);
960
961 PrinterSearchData search_data;
Luum Habtemariam521c6872019-07-11 20:12:46962 search_data.discovery_type = PrinterDiscoveryType::kUsb;
Jimmy Gong533177732019-04-26 19:13:19963
964 // Vendor id that exists, nonexistent device id, should get a NOT_FOUND.
965 // Although this is an unsupported printer model, we can still expect to get
966 // the manufacturer name.
967 search_data.usb_vendor_id = 0x03f0;
968 search_data.usb_product_id = 9999;
969 provider->ResolvePpdReference(
970 search_data, base::BindOnce(&PpdProviderTest::CaptureResolvePpdReference,
971 base::Unretained(this)));
972
973 // Nonexistent vendor id, should get a NOT_FOUND in the real world, but
974 // the URL interceptor we're using considers all nonexistent files to
975 // be effectively CONNECTION REFUSED, so we just check for non-success
976 // on this one. We should also not be able to get a manufacturer name from a
977 // nonexistent vendor id.
978 search_data.usb_vendor_id = 0x1234;
979 search_data.usb_product_id = 1782;
980 provider->ResolvePpdReference(
981 search_data, base::BindOnce(&PpdProviderTest::CaptureResolvePpdReference,
982 base::Unretained(this)));
Gabriel Charette694c3c332019-08-19 14:53:05983 task_environment_.RunUntilIdle();
Jimmy Gong533177732019-04-26 19:13:19984
985 ASSERT_EQ(static_cast<size_t>(2), captured_resolve_ppd_references_.size());
986 // Was able to find the printer manufactuer but unable to find the printer
987 // model should result in a NOT_FOUND.
988 EXPECT_EQ(PpdProvider::NOT_FOUND, captured_resolve_ppd_references_[0].code);
989 // Failed to grab the PPD for a USB printer, but should still be able to grab
990 // its manufacturer name.
991 EXPECT_EQ("HP", captured_resolve_ppd_references_[0].usb_manufacturer);
992
993 // Unable to find the PPD file should result in a failure.
994 EXPECT_FALSE(captured_resolve_ppd_references_[1].code ==
995 PpdProvider::SUCCESS);
996 // Unknown vendor id should result in an empty manufacturer string.
997 EXPECT_TRUE(captured_resolve_ppd_references_[1].usb_manufacturer.empty());
998}
999
justincarlsonc7d4aa6c2016-10-25 15:12:101000} // namespace
justincarlsonc7d4aa6c2016-10-25 15:12:101001} // namespace chromeos