ppd_provider_unittest.cc 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144
  1. // 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. #include "chromeos/printing/ppd_provider.h"
  5. #include <algorithm>
  6. #include <map>
  7. #include <memory>
  8. #include <string>
  9. #include <utility>
  10. #include <vector>
  11. #include "base/bind.h"
  12. #include "base/callback_helpers.h"
  13. #include "base/files/file_util.h"
  14. #include "base/files/scoped_temp_dir.h"
  15. #include "base/run_loop.h"
  16. #include "base/strings/strcat.h"
  17. #include "base/strings/stringprintf.h"
  18. #include "base/task/single_thread_task_runner.h"
  19. #include "base/test/bind.h"
  20. #include "base/test/simple_test_clock.h"
  21. #include "base/test/task_environment.h"
  22. #include "base/test/test_message_loop.h"
  23. #include "base/threading/sequenced_task_runner_handle.h"
  24. #include "base/threading/thread_task_runner_handle.h"
  25. #include "base/version.h"
  26. #include "chromeos/printing/fake_printer_config_cache.h"
  27. #include "chromeos/printing/ppd_cache.h"
  28. #include "chromeos/printing/ppd_metadata_manager.h"
  29. #include "chromeos/printing/printer_config_cache.h"
  30. #include "chromeos/printing/printer_configuration.h"
  31. #include "testing/gmock/include/gmock/gmock-matchers.h"
  32. #include "testing/gtest/include/gtest/gtest.h"
  33. namespace chromeos {
  34. namespace {
  35. using PrinterDiscoveryType = PrinterSearchData::PrinterDiscoveryType;
  36. using ::testing::AllOf;
  37. using ::testing::Eq;
  38. using ::testing::Field;
  39. using ::testing::StrEq;
  40. using ::testing::UnorderedElementsAre;
  41. // A pseudo-ppd that should get cupsFilter lines extracted from it.
  42. const char kCupsFilterPpdContents[] = R"(
  43. Other random contents that we don't care about.
  44. *cupsFilter: "application/vnd.cups-raster 0 my_filter"
  45. More random contents that we don't care about
  46. *cupsFilter: "application/vnd.cups-awesome 0 a_different_filter"
  47. *cupsFilter: "application/vnd.cups-awesomesauce 0 filter3"
  48. Yet more randome contents that we don't care about.
  49. More random contents that we don't care about.
  50. )";
  51. // A pseudo-ppd that should get cupsFilter2 lines extracted from it.
  52. // We also have cupsFilter lines in here, but since cupsFilter2 lines
  53. // exist, the cupsFilter lines should be ignored.
  54. const char kCupsFilter2PpdContents[] = R"(
  55. Other random contents that we don't care about.
  56. *cupsFilter: "application/vnd.cups-raster 0 my_filter"
  57. More random contents that we don't care about
  58. *cupsFilter2: "foo bar 0 the_real_filter"
  59. *cupsFilter2: "bar baz 381 another_real_filter"
  60. Yet more randome contents that we don't care about.
  61. More random contents that we don't care about.
  62. )";
  63. // Known number of public method calls that the PpdProvider will defer
  64. // before posting failures directly.
  65. // * This value is left unspecified in the header.
  66. // * This value must be kept in sync with the exact value in the
  67. // implementation of PpdProvider.
  68. constexpr int kMethodDeferralLimitForTesting = 20;
  69. // Default manufacturers metadata used for these tests.
  70. const char kDefaultManufacturersJson[] = R"({
  71. "filesMap": {
  72. "Manufacturer A": "manufacturer_a-en.json",
  73. "Manufacturer B": "manufacturer_b-en.json"
  74. }
  75. })";
  76. // Unowned raw pointers to helper classes composed into the
  77. // PpdProvider at construct time. Used throughout to activate testing
  78. // codepaths.
  79. struct PpdProviderComposedMembers {
  80. FakePrinterConfigCache* config_cache = nullptr;
  81. FakePrinterConfigCache* manager_config_cache = nullptr;
  82. PpdMetadataManager* metadata_manager = nullptr;
  83. };
  84. class PpdProviderTest : public ::testing::Test {
  85. public:
  86. // * Determines where the PpdCache class runs.
  87. // * If set to kOnTestThread, the PpdCache class will use the
  88. // task environment of the test fixture.
  89. // * If set to kInBackgroundThreads, the PpdCache class will
  90. // spawn its own background threads.
  91. // * Prefer only to run cache on the test thread if you need to
  92. // manipulate its sequencing independently of PpdProvider;
  93. // otherwise, allowing it spawn its own background threads
  94. // should be safe and good for exercising its codepaths.
  95. enum class PpdCacheRunLocation {
  96. kOnTestThread,
  97. kInBackgroundThreads,
  98. };
  99. // * Determines whether the browser locale given to PpdProvider
  100. // should be propagated to the composed PpdMetadataManager as its
  101. // metadata locale as well.
  102. // * Useful to the caller depending on whether or not one is
  103. // interested in the codepaths that fetch and parse the locales
  104. // metadata.
  105. enum class PropagateLocaleToMetadataManager {
  106. kDoNotPropagate,
  107. kDoPropagate,
  108. };
  109. // Options passed to CreateProvider().
  110. struct CreateProviderOptions {
  111. std::string browser_locale;
  112. PpdCacheRunLocation where_ppd_cache_runs;
  113. PropagateLocaleToMetadataManager propagate_locale;
  114. };
  115. PpdProviderTest()
  116. : task_environment_(base::test::TaskEnvironment::MainThreadType::IO,
  117. base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
  118. void SetUp() override {
  119. ASSERT_TRUE(ppd_cache_temp_dir_.CreateUniqueTempDir());
  120. }
  121. // Creates and return a provider for a test that uses the given |options|.
  122. scoped_refptr<PpdProvider> CreateProvider(
  123. const CreateProviderOptions& options) {
  124. switch (options.where_ppd_cache_runs) {
  125. case PpdCacheRunLocation::kOnTestThread:
  126. ppd_cache_ = PpdCache::CreateForTesting(
  127. ppd_cache_temp_dir_.GetPath(),
  128. task_environment_.GetMainThreadTaskRunner());
  129. break;
  130. case PpdCacheRunLocation::kInBackgroundThreads:
  131. default:
  132. ppd_cache_ = PpdCache::Create(ppd_cache_temp_dir_.GetPath());
  133. break;
  134. }
  135. auto manager_config_cache = std::make_unique<FakePrinterConfigCache>();
  136. provider_backdoor_.manager_config_cache = manager_config_cache.get();
  137. auto manager = PpdMetadataManager::Create(options.browser_locale, &clock_,
  138. std::move(manager_config_cache));
  139. provider_backdoor_.metadata_manager = manager.get();
  140. switch (options.propagate_locale) {
  141. case PropagateLocaleToMetadataManager::kDoNotPropagate:
  142. // Nothing to do; the no-propagate case allows the
  143. // PpdMetadataManager to acquire the metadata locale (or fail to
  144. // do so) by natural means.
  145. break;
  146. case PropagateLocaleToMetadataManager::kDoPropagate:
  147. default:
  148. provider_backdoor_.metadata_manager->SetLocaleForTesting(
  149. options.browser_locale);
  150. break;
  151. }
  152. auto config_cache = std::make_unique<FakePrinterConfigCache>();
  153. provider_backdoor_.config_cache = config_cache.get();
  154. return PpdProvider::Create(base::Version("40.8.6753.09"), ppd_cache_,
  155. std::move(manager), std::move(config_cache));
  156. }
  157. // Fills the fake Chrome OS Printing serving root with content.
  158. // Must be called after CreateProvider().
  159. void StartFakePpdServer() {
  160. for (const auto& entry : server_contents()) {
  161. provider_backdoor_.config_cache->SetFetchResponseForTesting(entry.first,
  162. entry.second);
  163. provider_backdoor_.manager_config_cache->SetFetchResponseForTesting(
  164. entry.first, entry.second);
  165. }
  166. }
  167. // Interceptor posts a *task* during destruction that actually unregisters
  168. // things. So we have to run the message loop post-interceptor-destruction to
  169. // actually unregister the URLs, otherwise they won't *actually* be
  170. // unregistered until the next time we invoke the message loop. Which may be
  171. // in the middle of the next test.
  172. //
  173. // Note this is harmless to call if we haven't started a fake ppd server.
  174. void StopFakePpdServer() {
  175. for (const auto& entry : server_contents()) {
  176. provider_backdoor_.config_cache->Drop(entry.first);
  177. provider_backdoor_.manager_config_cache->Drop(entry.first);
  178. }
  179. task_environment_.RunUntilIdle();
  180. }
  181. // Capture the result of a ResolveManufacturers() call.
  182. void CaptureResolveManufacturers(PpdProvider::CallbackResultCode code,
  183. const std::vector<std::string>& data) {
  184. captured_resolve_manufacturers_.push_back({code, data});
  185. }
  186. // Capture the result of a ResolvePrinters() call.
  187. void CaptureResolvePrinters(PpdProvider::CallbackResultCode code,
  188. const PpdProvider::ResolvedPrintersList& data) {
  189. captured_resolve_printers_.push_back({code, data});
  190. }
  191. // Capture the result of a ResolvePpd() call.
  192. void CaptureResolvePpd(PpdProvider::CallbackResultCode code,
  193. const std::string& ppd_contents) {
  194. CapturedResolvePpdResults results;
  195. results.code = code;
  196. results.ppd_contents = ppd_contents;
  197. captured_resolve_ppd_.push_back(results);
  198. }
  199. // Capture the result of a ResolveUsbIds() call.
  200. void CaptureResolvePpdReference(PpdProvider::CallbackResultCode code,
  201. const Printer::PpdReference& ref,
  202. const std::string& usb_manufacturer) {
  203. captured_resolve_ppd_references_.push_back({code, ref, usb_manufacturer});
  204. }
  205. // Capture the result of a ResolvePpdLicense() call.
  206. void CaptureResolvePpdLicense(PpdProvider::CallbackResultCode code,
  207. const std::string& license) {
  208. captured_resolve_ppd_license_.push_back({code, license});
  209. }
  210. void CaptureReverseLookup(PpdProvider::CallbackResultCode code,
  211. const std::string& manufacturer,
  212. const std::string& model) {
  213. captured_reverse_lookup_.push_back({code, manufacturer, model});
  214. }
  215. // Discard the result of a ResolvePpd() call.
  216. void DiscardResolvePpd(PpdProvider::CallbackResultCode code,
  217. const std::string& contents) {}
  218. // Calls the ResolveManufacturer() method of the |provider| and
  219. // waits for its completion. Ignores the returned string values and
  220. // returns whether the result code was
  221. // PpdProvider::CallbackResultCode::SUCCESS.
  222. bool SuccessfullyResolveManufacturers(PpdProvider* provider) {
  223. base::RunLoop run_loop;
  224. PpdProvider::CallbackResultCode code;
  225. provider->ResolveManufacturers(base::BindLambdaForTesting(
  226. [&run_loop, &code](
  227. PpdProvider::CallbackResultCode result_code,
  228. const std::vector<std::string>& unused_manufacturers) {
  229. code = result_code;
  230. run_loop.QuitClosure().Run();
  231. }));
  232. run_loop.Run();
  233. return code == PpdProvider::CallbackResultCode::SUCCESS;
  234. }
  235. protected:
  236. // List of relevant endpoint for this FakeServer
  237. std::vector<std::pair<std::string, std::string>> server_contents() const {
  238. // Use brace initialization to express the desired server contents as "url",
  239. // "contents" pairs.
  240. return {{"metadata_v3/locales.json",
  241. R"({
  242. "locales": [ "de", "en", "es" ]
  243. })"},
  244. {"metadata_v3/manufacturers-en.json", kDefaultManufacturersJson},
  245. {"metadata_v3/manufacturer_a-en.json",
  246. R"({
  247. "printers": [ {
  248. "name": "printer_a",
  249. "emm": "printer_a_ref"
  250. }, {
  251. "name": "printer_b",
  252. "emm": "printer_b_ref"
  253. } ]
  254. })"},
  255. {"metadata_v3/manufacturer_b-en.json",
  256. R"({
  257. "printers": [ {
  258. "name": "printer_c",
  259. "emm": "printer_c_ref"
  260. } ]
  261. })"},
  262. {"metadata_v3/index-01.json",
  263. R"({
  264. "ppdIndex": {
  265. "printer_a_ref": {
  266. "ppdMetadata": [ {
  267. "name": "printer_a.ppd",
  268. "license": "fake_license"
  269. } ]
  270. }
  271. }
  272. })"},
  273. {"metadata_v3/index-02.json",
  274. R"({
  275. "ppdIndex": {
  276. "printer_b_ref": {
  277. "ppdMetadata": [ {
  278. "name": "printer_b.ppd"
  279. } ]
  280. }
  281. }
  282. })"},
  283. {"metadata_v3/index-03.json",
  284. R"({
  285. "ppdIndex": {
  286. "printer_c_ref": {
  287. "ppdMetadata": [ {
  288. "name": "printer_c.ppd"
  289. } ]
  290. }
  291. }
  292. })"},
  293. {"metadata_v3/index-04.json",
  294. R"({
  295. "ppdIndex": {
  296. "printer_d_ref": {
  297. "ppdMetadata": [ {
  298. "name": "printer_d.ppd"
  299. } ]
  300. }
  301. }
  302. })"},
  303. {"metadata_v3/index-05.json",
  304. R"({
  305. "ppdIndex": {
  306. "printer_e_ref": {
  307. "ppdMetadata": [ {
  308. "name": "printer_e.ppd"
  309. } ]
  310. }
  311. }
  312. })"},
  313. {"metadata_v3/index-08.json",
  314. R"({
  315. "ppdIndex": {
  316. "Some canonical reference": {
  317. "ppdMetadata": [ {
  318. "name": "unused.ppd"
  319. } ]
  320. }
  321. }
  322. })"},
  323. {"metadata_v3/index-10.json",
  324. R"({
  325. "ppdIndex": {
  326. "Some other canonical reference": {
  327. "ppdMetadata": [ {
  328. "name": "unused.ppd"
  329. } ]
  330. }
  331. }
  332. })"},
  333. {"metadata_v3/usb-031f.json",
  334. R"({
  335. "usbIndex": {
  336. "1592": {
  337. "effectiveMakeAndModel": "Some canonical reference"
  338. },
  339. "6535": {
  340. "effectiveMakeAndModel": "Some other canonical reference"
  341. }
  342. }
  343. })"},
  344. {"metadata_v3/usb-03f0.json", ""},
  345. {"metadata_v3/usb-1234.json", ""},
  346. {"metadata_v3/usb_vendor_ids.json", R"({
  347. "entries": [ {
  348. "vendorId": 799,
  349. "vendorName": "Seven Ninety Nine LLC"
  350. }, {
  351. "vendorId": 1008,
  352. "vendorName": "HP"
  353. } ]
  354. })"},
  355. {"metadata_v3/reverse_index-en-01.json",
  356. R"({
  357. "reverseIndex": {
  358. "printer_a_ref": {
  359. "manufacturer": "manufacturer_a_en",
  360. "model": "printer_a"
  361. }
  362. }
  363. })"},
  364. {"metadata_v3/reverse_index-en-19.json",
  365. R"({
  366. "reverseIndex": {
  367. "unused effective make and model": {
  368. "manufacturer": "unused manufacturer",
  369. "model": "unused model"
  370. }
  371. }
  372. })"},
  373. {"ppds_for_metadata_v3/printer_a.ppd", kCupsFilterPpdContents},
  374. {"ppds_for_metadata_v3/printer_b.ppd", kCupsFilter2PpdContents},
  375. {"ppds_for_metadata_v3/printer_c.ppd", "c"},
  376. {"ppds_for_metadata_v3/printer_d.ppd", "d"},
  377. {"ppds_for_metadata_v3/printer_e.ppd", "e"},
  378. {"user_supplied_ppd_directory/user_supplied.ppd", "u"}};
  379. }
  380. // Environment for task schedulers.
  381. base::test::TaskEnvironment task_environment_;
  382. std::vector<
  383. std::pair<PpdProvider::CallbackResultCode, std::vector<std::string>>>
  384. captured_resolve_manufacturers_;
  385. std::vector<std::pair<PpdProvider::CallbackResultCode,
  386. PpdProvider::ResolvedPrintersList>>
  387. captured_resolve_printers_;
  388. struct CapturedResolvePpdResults {
  389. PpdProvider::CallbackResultCode code;
  390. std::string ppd_contents;
  391. };
  392. std::vector<CapturedResolvePpdResults> captured_resolve_ppd_;
  393. struct CapturedResolvePpdReferenceResults {
  394. PpdProvider::CallbackResultCode code;
  395. Printer::PpdReference ref;
  396. std::string usb_manufacturer;
  397. };
  398. std::vector<CapturedResolvePpdReferenceResults>
  399. captured_resolve_ppd_references_;
  400. struct CapturedReverseLookup {
  401. PpdProvider::CallbackResultCode code;
  402. std::string manufacturer;
  403. std::string model;
  404. };
  405. std::vector<CapturedReverseLookup> captured_reverse_lookup_;
  406. struct CapturedResolvePpdLicense {
  407. PpdProvider::CallbackResultCode code;
  408. std::string license;
  409. };
  410. std::vector<CapturedResolvePpdLicense> captured_resolve_ppd_license_;
  411. base::ScopedTempDir ppd_cache_temp_dir_;
  412. base::ScopedTempDir interceptor_temp_dir_;
  413. // Reference to the underlying ppd_cache_ so we can muck with it to test
  414. // cache-dependent behavior of ppd_provider_.
  415. scoped_refptr<PpdCache> ppd_cache_;
  416. PpdProviderComposedMembers provider_backdoor_;
  417. // Misc extra stuff needed for the test environment to function.
  418. base::SimpleTestClock clock_;
  419. };
  420. // Tests that PpdProvider enqueues a bounded number of calls to
  421. // ResolveManufacturers() and fails the oldest call when the queue is
  422. // deemed full (implementation-specified detail).
  423. TEST_F(PpdProviderTest, FailsOldestQueuedResolveManufacturers) {
  424. auto provider =
  425. CreateProvider({"en", PpdCacheRunLocation::kInBackgroundThreads,
  426. PropagateLocaleToMetadataManager::kDoNotPropagate});
  427. // Prevents the provider from ever getting a metadata locale.
  428. // We want it to stall out, forcing it to perpetually defer method
  429. // calls to ResolveManufacturers().
  430. provider_backdoor_.manager_config_cache->DiscardFetchRequestFor(
  431. "metadata_v3/locales.json");
  432. for (int i = kMethodDeferralLimitForTesting; i >= 0; i--) {
  433. provider->ResolveManufacturers(base::BindOnce(
  434. &PpdProviderTest::CaptureResolveManufacturers, base::Unretained(this)));
  435. }
  436. // The for loop above should have overflowed the deferral queue by
  437. // a factor of one: the oldest call to ResolveManufacturers() should
  438. // have been forced out and asked to fail, and we expect it to be
  439. // sitting on the sequence right now.
  440. ASSERT_EQ(1UL, task_environment_.GetPendingMainThreadTaskCount());
  441. task_environment_.FastForwardUntilNoTasksRemain();
  442. ASSERT_EQ(1UL, captured_resolve_manufacturers_.size());
  443. EXPECT_EQ(PpdProvider::CallbackResultCode::SERVER_ERROR,
  444. captured_resolve_manufacturers_[0].first);
  445. }
  446. // Tests that PpdProvider enqueues a bounded number of calls to
  447. // ReverseLookup() and fails the oldest call when the queue is deemed
  448. // full (implementation-specified detail).
  449. TEST_F(PpdProviderTest, FailsOldestQueuedReverseLookup) {
  450. auto provider =
  451. CreateProvider({"en", PpdCacheRunLocation::kInBackgroundThreads,
  452. PropagateLocaleToMetadataManager::kDoNotPropagate});
  453. // Prevents the provider from ever getting a metadata locale.
  454. // We want it to stall out, forcing it to perpetually defer method
  455. // calls to ReverseLookup().
  456. provider_backdoor_.manager_config_cache->DiscardFetchRequestFor(
  457. "metadata_v3/locales.json");
  458. for (int i = kMethodDeferralLimitForTesting; i >= 0; i--) {
  459. provider->ReverseLookup(
  460. "some effective-make-and-model string",
  461. base::BindOnce(&PpdProviderTest::CaptureReverseLookup,
  462. base::Unretained(this)));
  463. }
  464. // The for loop above should have overflowed the deferral queue by
  465. // a factor of one: the oldest call to ReverseLookup() should have
  466. // been forced out and asked to fail, and we expect it to be sitting
  467. // on the sequence right now.
  468. ASSERT_EQ(1UL, task_environment_.GetPendingMainThreadTaskCount());
  469. task_environment_.FastForwardUntilNoTasksRemain();
  470. ASSERT_EQ(1UL, captured_reverse_lookup_.size());
  471. EXPECT_EQ(PpdProvider::CallbackResultCode::SERVER_ERROR,
  472. captured_reverse_lookup_[0].code);
  473. }
  474. // Test that we get back manufacturer maps as expected.
  475. TEST_F(PpdProviderTest, ManufacturersFetch) {
  476. auto provider =
  477. CreateProvider({"en", PpdCacheRunLocation::kInBackgroundThreads,
  478. PropagateLocaleToMetadataManager::kDoNotPropagate});
  479. StartFakePpdServer();
  480. // Issue two requests at the same time, both should be resolved properly.
  481. provider->ResolveManufacturers(base::BindOnce(
  482. &PpdProviderTest::CaptureResolveManufacturers, base::Unretained(this)));
  483. provider->ResolveManufacturers(base::BindOnce(
  484. &PpdProviderTest::CaptureResolveManufacturers, base::Unretained(this)));
  485. task_environment_.FastForwardUntilNoTasksRemain();
  486. ASSERT_EQ(2UL, captured_resolve_manufacturers_.size());
  487. std::vector<std::string> expected_result(
  488. {"Manufacturer A", "Manufacturer B"});
  489. EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_manufacturers_[0].first);
  490. EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_manufacturers_[1].first);
  491. EXPECT_TRUE(captured_resolve_manufacturers_[0].second == expected_result);
  492. EXPECT_TRUE(captured_resolve_manufacturers_[1].second == expected_result);
  493. }
  494. // Test that we get a reasonable error when we have no server to contact. Tis
  495. // is almost exactly the same as the above test, we just don't bring up the fake
  496. // server first.
  497. TEST_F(PpdProviderTest, ManufacturersFetchNoServer) {
  498. auto provider =
  499. CreateProvider({"en", PpdCacheRunLocation::kInBackgroundThreads,
  500. PropagateLocaleToMetadataManager::kDoNotPropagate});
  501. // Issue two requests at the same time, both should resolve properly
  502. // (though they will fail).
  503. provider->ResolveManufacturers(base::BindOnce(
  504. &PpdProviderTest::CaptureResolveManufacturers, base::Unretained(this)));
  505. provider->ResolveManufacturers(base::BindOnce(
  506. &PpdProviderTest::CaptureResolveManufacturers, base::Unretained(this)));
  507. task_environment_.FastForwardUntilNoTasksRemain();
  508. ASSERT_EQ(2UL, captured_resolve_manufacturers_.size());
  509. EXPECT_EQ(PpdProvider::SERVER_ERROR,
  510. captured_resolve_manufacturers_[0].first);
  511. EXPECT_EQ(PpdProvider::SERVER_ERROR,
  512. captured_resolve_manufacturers_[1].first);
  513. EXPECT_TRUE(captured_resolve_manufacturers_[0].second.empty());
  514. EXPECT_TRUE(captured_resolve_manufacturers_[1].second.empty());
  515. }
  516. // Tests that mutiples requests for make-and-model resolution can be fulfilled
  517. // simultaneously.
  518. TEST_F(PpdProviderTest, RepeatedMakeModel) {
  519. auto provider =
  520. CreateProvider({"en", PpdCacheRunLocation::kInBackgroundThreads,
  521. PropagateLocaleToMetadataManager::kDoPropagate});
  522. StartFakePpdServer();
  523. PrinterSearchData unrecognized_printer;
  524. unrecognized_printer.discovery_type = PrinterDiscoveryType::kManual;
  525. unrecognized_printer.make_and_model = {"Printer Printer"};
  526. PrinterSearchData recognized_printer;
  527. recognized_printer.discovery_type = PrinterDiscoveryType::kManual;
  528. recognized_printer.make_and_model = {"printer_a_ref"};
  529. PrinterSearchData mixed;
  530. mixed.discovery_type = PrinterDiscoveryType::kManual;
  531. mixed.make_and_model = {"printer_a_ref", "Printer Printer"};
  532. // Resolve the same thing repeatedly.
  533. provider->ResolvePpdReference(
  534. unrecognized_printer,
  535. base::BindOnce(&PpdProviderTest::CaptureResolvePpdReference,
  536. base::Unretained(this)));
  537. provider->ResolvePpdReference(
  538. mixed, base::BindOnce(&PpdProviderTest::CaptureResolvePpdReference,
  539. base::Unretained(this)));
  540. provider->ResolvePpdReference(
  541. recognized_printer,
  542. base::BindOnce(&PpdProviderTest::CaptureResolvePpdReference,
  543. base::Unretained(this)));
  544. task_environment_.RunUntilIdle();
  545. ASSERT_EQ(static_cast<size_t>(3), captured_resolve_ppd_references_.size());
  546. EXPECT_EQ(PpdProvider::NOT_FOUND, captured_resolve_ppd_references_[0].code);
  547. EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_references_[1].code);
  548. EXPECT_EQ("printer_a_ref",
  549. captured_resolve_ppd_references_[1].ref.effective_make_and_model);
  550. EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_references_[2].code);
  551. EXPECT_EQ("printer_a_ref",
  552. captured_resolve_ppd_references_[2].ref.effective_make_and_model);
  553. }
  554. // Test successful and unsuccessful usb resolutions.
  555. TEST_F(PpdProviderTest, UsbResolution) {
  556. auto provider =
  557. CreateProvider({"en", PpdCacheRunLocation::kInBackgroundThreads,
  558. PropagateLocaleToMetadataManager::kDoPropagate});
  559. StartFakePpdServer();
  560. PrinterSearchData search_data;
  561. search_data.discovery_type = PrinterDiscoveryType::kUsb;
  562. // Should get back "Some canonical reference"
  563. search_data.usb_vendor_id = 0x031f;
  564. search_data.usb_product_id = 1592;
  565. provider->ResolvePpdReference(
  566. search_data, base::BindOnce(&PpdProviderTest::CaptureResolvePpdReference,
  567. base::Unretained(this)));
  568. // Should get back "Some other canonical reference"
  569. search_data.usb_vendor_id = 0x031f;
  570. search_data.usb_product_id = 6535;
  571. provider->ResolvePpdReference(
  572. search_data, base::BindOnce(&PpdProviderTest::CaptureResolvePpdReference,
  573. base::Unretained(this)));
  574. // Vendor id that exists, nonexistent device id, should get a NOT_FOUND.
  575. // In our fake serving root, the manufacturer with vendor ID 0x031f
  576. // (== 799) is named "Seven Ninety Nine LLC."
  577. search_data.usb_vendor_id = 0x031f;
  578. search_data.usb_product_id = 8162;
  579. provider->ResolvePpdReference(
  580. search_data, base::BindOnce(&PpdProviderTest::CaptureResolvePpdReference,
  581. base::Unretained(this)));
  582. // Nonexistent vendor id, should get a NOT_FOUND in the real world, but
  583. // the URL interceptor we're using considers all nonexistent files to
  584. // be effectively CONNECTION REFUSED, so we just check for non-success
  585. // on this one.
  586. search_data.usb_vendor_id = 0x1234;
  587. search_data.usb_product_id = 1782;
  588. provider->ResolvePpdReference(
  589. search_data, base::BindOnce(&PpdProviderTest::CaptureResolvePpdReference,
  590. base::Unretained(this)));
  591. task_environment_.RunUntilIdle();
  592. ASSERT_EQ(captured_resolve_ppd_references_.size(), static_cast<size_t>(4));
  593. // ResolvePpdReference() takes place in several asynchronous steps, so
  594. // order is not guaranteed.
  595. EXPECT_THAT(
  596. captured_resolve_ppd_references_,
  597. UnorderedElementsAre(
  598. AllOf(Field(&CapturedResolvePpdReferenceResults::code,
  599. Eq(PpdProvider::SUCCESS)),
  600. Field(&CapturedResolvePpdReferenceResults::ref,
  601. Field(&Printer::PpdReference::effective_make_and_model,
  602. StrEq("Some canonical reference")))),
  603. AllOf(Field(&CapturedResolvePpdReferenceResults::code,
  604. Eq(PpdProvider::SUCCESS)),
  605. Field(&CapturedResolvePpdReferenceResults::ref,
  606. Field(&Printer::PpdReference::effective_make_and_model,
  607. StrEq("Some other canonical reference")))),
  608. AllOf(Field(&CapturedResolvePpdReferenceResults::code,
  609. Eq(PpdProvider::NOT_FOUND)),
  610. Field(&CapturedResolvePpdReferenceResults::usb_manufacturer,
  611. StrEq("Seven Ninety Nine LLC"))),
  612. Field(&CapturedResolvePpdReferenceResults::code,
  613. Eq(PpdProvider::NOT_FOUND))));
  614. }
  615. // Test basic ResolvePrinters() functionality. At the same time, make
  616. // sure we can get the PpdReference for each of the resolved printers.
  617. TEST_F(PpdProviderTest, ResolvePrinters) {
  618. auto provider =
  619. CreateProvider({"en", PpdCacheRunLocation::kInBackgroundThreads,
  620. PropagateLocaleToMetadataManager::kDoPropagate});
  621. StartFakePpdServer();
  622. // Required setup calls to advance past PpdProvider's method deferral.
  623. ASSERT_TRUE(provider_backdoor_.metadata_manager->SetManufacturersForTesting(
  624. kDefaultManufacturersJson));
  625. ASSERT_TRUE(SuccessfullyResolveManufacturers(provider.get()));
  626. provider->ResolvePrinters(
  627. "Manufacturer A", base::BindOnce(&PpdProviderTest::CaptureResolvePrinters,
  628. base::Unretained(this)));
  629. provider->ResolvePrinters(
  630. "Manufacturer B", base::BindOnce(&PpdProviderTest::CaptureResolvePrinters,
  631. base::Unretained(this)));
  632. task_environment_.RunUntilIdle();
  633. ASSERT_EQ(2UL, captured_resolve_printers_.size());
  634. EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_printers_[0].first);
  635. EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_printers_[1].first);
  636. EXPECT_EQ(2UL, captured_resolve_printers_[0].second.size());
  637. // First capture should get back printer_a, and printer_b, with ppd
  638. // reference effective make and models of printer_a_ref and printer_b_ref.
  639. const auto& capture0 = captured_resolve_printers_[0].second;
  640. ASSERT_EQ(2UL, capture0.size());
  641. EXPECT_EQ("printer_a", capture0[0].name);
  642. EXPECT_EQ("printer_a_ref", capture0[0].ppd_ref.effective_make_and_model);
  643. EXPECT_EQ("printer_b", capture0[1].name);
  644. EXPECT_EQ("printer_b_ref", capture0[1].ppd_ref.effective_make_and_model);
  645. // Second capture should get back printer_c with effective make and model of
  646. // printer_c_ref
  647. const auto& capture1 = captured_resolve_printers_[1].second;
  648. ASSERT_EQ(1UL, capture1.size());
  649. EXPECT_EQ("printer_c", capture1[0].name);
  650. EXPECT_EQ("printer_c_ref", capture1[0].ppd_ref.effective_make_and_model);
  651. }
  652. // Test that if we give a bad reference to ResolvePrinters(), we get a
  653. // SERVER_ERROR. There's currently no feedback that indicates
  654. // specifically to the caller that they asked for the printers of
  655. // a manufacturer we didn't previously advertise.
  656. TEST_F(PpdProviderTest, ResolvePrintersBadReference) {
  657. auto provider =
  658. CreateProvider({"en", PpdCacheRunLocation::kInBackgroundThreads,
  659. PropagateLocaleToMetadataManager::kDoPropagate});
  660. StartFakePpdServer();
  661. // Required setup calls to advance past PpdProvider's method deferral.
  662. ASSERT_TRUE(provider_backdoor_.metadata_manager->SetManufacturersForTesting(
  663. kDefaultManufacturersJson));
  664. ASSERT_TRUE(SuccessfullyResolveManufacturers(provider.get()));
  665. provider->ResolvePrinters(
  666. "bogus_doesnt_exist",
  667. base::BindOnce(&PpdProviderTest::CaptureResolvePrinters,
  668. base::Unretained(this)));
  669. task_environment_.RunUntilIdle();
  670. ASSERT_EQ(1UL, captured_resolve_printers_.size());
  671. EXPECT_EQ(PpdProvider::SERVER_ERROR, captured_resolve_printers_[0].first);
  672. }
  673. // Test that if the server is unavailable, we get SERVER_ERRORs back out.
  674. TEST_F(PpdProviderTest, ResolvePrintersNoServer) {
  675. auto provider =
  676. CreateProvider({"en", PpdCacheRunLocation::kInBackgroundThreads,
  677. PropagateLocaleToMetadataManager::kDoPropagate});
  678. // Required setup calls to advance past PpdProvider's method deferral.
  679. ASSERT_TRUE(provider_backdoor_.metadata_manager->SetManufacturersForTesting(
  680. kDefaultManufacturersJson));
  681. ASSERT_TRUE(SuccessfullyResolveManufacturers(provider.get()));
  682. provider->ResolvePrinters(
  683. "Manufacturer A", base::BindOnce(&PpdProviderTest::CaptureResolvePrinters,
  684. base::Unretained(this)));
  685. provider->ResolvePrinters(
  686. "Manufacturer B", base::BindOnce(&PpdProviderTest::CaptureResolvePrinters,
  687. base::Unretained(this)));
  688. task_environment_.RunUntilIdle();
  689. ASSERT_EQ(2UL, captured_resolve_printers_.size());
  690. EXPECT_EQ(PpdProvider::SERVER_ERROR, captured_resolve_printers_[0].first);
  691. EXPECT_EQ(PpdProvider::SERVER_ERROR, captured_resolve_printers_[1].first);
  692. }
  693. // Test a successful ppd resolution from an effective_make_and_model reference.
  694. TEST_F(PpdProviderTest, ResolveServerKeyPpd) {
  695. auto provider =
  696. CreateProvider({"en", PpdCacheRunLocation::kInBackgroundThreads,
  697. PropagateLocaleToMetadataManager::kDoPropagate});
  698. StartFakePpdServer();
  699. Printer::PpdReference ref;
  700. ref.effective_make_and_model = "printer_b_ref";
  701. provider->ResolvePpd(ref, base::BindOnce(&PpdProviderTest::CaptureResolvePpd,
  702. base::Unretained(this)));
  703. ref.effective_make_and_model = "printer_c_ref";
  704. provider->ResolvePpd(ref, base::BindOnce(&PpdProviderTest::CaptureResolvePpd,
  705. base::Unretained(this)));
  706. task_environment_.RunUntilIdle();
  707. ASSERT_EQ(2UL, captured_resolve_ppd_.size());
  708. // ResolvePpd() works in several asynchronous steps, so order of
  709. // return is not guaranteed.
  710. EXPECT_THAT(
  711. captured_resolve_ppd_,
  712. UnorderedElementsAre(
  713. AllOf(Field(&CapturedResolvePpdResults::code,
  714. PpdProvider::CallbackResultCode::SUCCESS),
  715. Field(&CapturedResolvePpdResults::ppd_contents,
  716. StrEq(kCupsFilter2PpdContents))),
  717. AllOf(Field(&CapturedResolvePpdResults::code,
  718. PpdProvider::CallbackResultCode::SUCCESS),
  719. Field(&CapturedResolvePpdResults::ppd_contents, StrEq("c")))));
  720. }
  721. // Test that we *don't* resolve a ppd URL over non-file schemes. It's not clear
  722. // whether we'll want to do this in the long term, but for now this is
  723. // disallowed because we're not sure we completely understand the security
  724. // implications.
  725. TEST_F(PpdProviderTest, ResolveUserSuppliedUrlPpdFromNetworkFails) {
  726. auto provider =
  727. CreateProvider({"en", PpdCacheRunLocation::kInBackgroundThreads,
  728. PropagateLocaleToMetadataManager::kDoPropagate});
  729. StartFakePpdServer();
  730. Printer::PpdReference ref;
  731. // PpdProvider::ResolvePpd() shall fail if a user-supplied PPD URL
  732. // does not begin with the "file://" scheme.
  733. ref.user_supplied_ppd_url = "nonfilescheme://unused";
  734. provider->ResolvePpd(ref, base::BindOnce(&PpdProviderTest::CaptureResolvePpd,
  735. base::Unretained(this)));
  736. task_environment_.RunUntilIdle();
  737. ASSERT_EQ(1UL, captured_resolve_ppd_.size());
  738. EXPECT_EQ(PpdProvider::INTERNAL_ERROR, captured_resolve_ppd_[0].code);
  739. EXPECT_TRUE(captured_resolve_ppd_[0].ppd_contents.empty());
  740. }
  741. // Test a successful ppd resolution from a user_supplied_url field when
  742. // reading from a file. Note we shouldn't need the server to be up
  743. // to do this successfully, as we should be able to do this offline.
  744. TEST_F(PpdProviderTest, ResolveUserSuppliedUrlPpdFromFile) {
  745. auto provider =
  746. CreateProvider({"en", PpdCacheRunLocation::kInBackgroundThreads,
  747. PropagateLocaleToMetadataManager::kDoPropagate});
  748. base::ScopedTempDir temp_dir;
  749. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  750. base::FilePath filename = temp_dir.GetPath().Append("my_spiffy.ppd");
  751. std::string user_ppd_contents = "Woohoo";
  752. ASSERT_TRUE(base::WriteFile(filename, user_ppd_contents));
  753. Printer::PpdReference ref;
  754. ref.user_supplied_ppd_url =
  755. base::StringPrintf("file://%s", filename.MaybeAsASCII().c_str());
  756. provider->ResolvePpd(ref, base::BindOnce(&PpdProviderTest::CaptureResolvePpd,
  757. base::Unretained(this)));
  758. task_environment_.RunUntilIdle();
  759. ASSERT_EQ(1UL, captured_resolve_ppd_.size());
  760. EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_[0].code);
  761. EXPECT_EQ(user_ppd_contents, captured_resolve_ppd_[0].ppd_contents);
  762. }
  763. // Test that we cache ppd resolutions when we fetch them and that we can resolve
  764. // from the cache without the server available.
  765. TEST_F(PpdProviderTest, ResolvedPpdsGetCached) {
  766. auto provider =
  767. CreateProvider({"en", PpdCacheRunLocation::kInBackgroundThreads,
  768. PropagateLocaleToMetadataManager::kDoPropagate});
  769. std::string user_ppd_contents = "Woohoo";
  770. Printer::PpdReference ref;
  771. {
  772. base::ScopedTempDir temp_dir;
  773. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  774. base::FilePath filename = temp_dir.GetPath().Append("my_spiffy.ppd");
  775. ASSERT_TRUE(base::WriteFile(filename, user_ppd_contents));
  776. ref.user_supplied_ppd_url =
  777. base::StringPrintf("file://%s", filename.MaybeAsASCII().c_str());
  778. provider->ResolvePpd(ref,
  779. base::BindOnce(&PpdProviderTest::CaptureResolvePpd,
  780. base::Unretained(this)));
  781. task_environment_.RunUntilIdle();
  782. ASSERT_EQ(1UL, captured_resolve_ppd_.size());
  783. EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_[0].code);
  784. EXPECT_EQ(user_ppd_contents, captured_resolve_ppd_[0].ppd_contents);
  785. }
  786. // ScopedTempDir goes out of scope, so the source file should now be
  787. // deleted. But if we resolve again, we should hit the cache and
  788. // still be successful.
  789. captured_resolve_ppd_.clear();
  790. // Recreate the provider to make sure we don't have any memory caches which
  791. // would mask problems with disk persistence.
  792. provider = CreateProvider({"en", PpdCacheRunLocation::kInBackgroundThreads,
  793. PropagateLocaleToMetadataManager::kDoPropagate});
  794. // Re-resolve.
  795. provider->ResolvePpd(ref, base::BindOnce(&PpdProviderTest::CaptureResolvePpd,
  796. base::Unretained(this)));
  797. task_environment_.RunUntilIdle();
  798. ASSERT_EQ(1UL, captured_resolve_ppd_.size());
  799. EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_[0].code);
  800. EXPECT_EQ(user_ppd_contents, captured_resolve_ppd_[0].ppd_contents);
  801. }
  802. // Test that all entrypoints will correctly work with case-insensitve
  803. // effective-make-and-model strings.
  804. TEST_F(PpdProviderTest, CaseInsensitiveMakeAndModel) {
  805. auto provider =
  806. CreateProvider({"en", PpdCacheRunLocation::kInBackgroundThreads,
  807. PropagateLocaleToMetadataManager::kDoPropagate});
  808. StartFakePpdServer();
  809. std::string ref = "pRiNteR_A_reF";
  810. Printer::PpdReference ppd_ref;
  811. ppd_ref.effective_make_and_model = ref;
  812. provider->ResolvePpd(ppd_ref,
  813. base::BindOnce(&PpdProviderTest::CaptureResolvePpd,
  814. base::Unretained(this)));
  815. provider->ReverseLookup(ref,
  816. base::BindOnce(&PpdProviderTest::CaptureReverseLookup,
  817. base::Unretained(this)));
  818. PrinterSearchData printer_info;
  819. printer_info.make_and_model = {ref};
  820. provider->ResolvePpdReference(
  821. printer_info, base::BindOnce(&PpdProviderTest::CaptureResolvePpdReference,
  822. base::Unretained(this)));
  823. task_environment_.RunUntilIdle();
  824. // Check PpdProvider::ResolvePpd
  825. ASSERT_EQ(1UL, captured_resolve_ppd_.size());
  826. EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_[0].code);
  827. EXPECT_EQ(kCupsFilterPpdContents, captured_resolve_ppd_[0].ppd_contents);
  828. // Check PpdProvider::ReverseLookup
  829. ASSERT_EQ(1UL, captured_reverse_lookup_.size());
  830. EXPECT_EQ(PpdProvider::SUCCESS, captured_reverse_lookup_[0].code);
  831. EXPECT_EQ("manufacturer_a_en", captured_reverse_lookup_[0].manufacturer);
  832. EXPECT_EQ("printer_a", captured_reverse_lookup_[0].model);
  833. // Check PpdProvider::ResolvePpdReference
  834. ASSERT_EQ(1UL, captured_resolve_ppd_references_.size());
  835. EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_references_[0].code);
  836. EXPECT_EQ("printer_a_ref",
  837. captured_resolve_ppd_references_[0].ref.effective_make_and_model);
  838. }
  839. // Tests that ResolvePpdLicense is able to correctly source the index and
  840. // determine the name of the PPD license associated with the given effecive make
  841. // and model (if any).
  842. TEST_F(PpdProviderTest, ResolvePpdLicense) {
  843. auto provider =
  844. CreateProvider({"en", PpdCacheRunLocation::kInBackgroundThreads,
  845. PropagateLocaleToMetadataManager::kDoNotPropagate});
  846. StartFakePpdServer();
  847. // For this effective_make_and_model, we expect that there is associated
  848. // license.
  849. const char kEmm1[] = "printer_a_ref";
  850. provider->ResolvePpdLicense(
  851. kEmm1, base::BindOnce(&PpdProviderTest::CaptureResolvePpdLicense,
  852. base::Unretained(this)));
  853. // We do not expect there to be any license associated with this
  854. // effective_make_and_model, so the response should be empty.
  855. const char kEmm2[] = "printer_b_ref";
  856. provider->ResolvePpdLicense(
  857. kEmm2, base::BindOnce(&PpdProviderTest::CaptureResolvePpdLicense,
  858. base::Unretained(this)));
  859. task_environment_.RunUntilIdle();
  860. ASSERT_EQ(2UL, captured_resolve_ppd_license_.size());
  861. EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_license_[0].code);
  862. EXPECT_EQ("fake_license", captured_resolve_ppd_license_[0].license);
  863. EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_license_[1].code);
  864. EXPECT_EQ("", captured_resolve_ppd_license_[1].license);
  865. }
  866. // Verifies that we can extract the Manufacturer and Model selection for a
  867. // given effective make and model.
  868. TEST_F(PpdProviderTest, ReverseLookup) {
  869. auto provider =
  870. CreateProvider({"en", PpdCacheRunLocation::kInBackgroundThreads,
  871. PropagateLocaleToMetadataManager::kDoPropagate});
  872. StartFakePpdServer();
  873. std::string ref = "printer_a_ref";
  874. provider->ReverseLookup(ref,
  875. base::BindOnce(&PpdProviderTest::CaptureReverseLookup,
  876. base::Unretained(this)));
  877. // TODO(skau): PpdProvider has a race condition that prevents running these
  878. // requests in parallel.
  879. task_environment_.RunUntilIdle();
  880. std::string ref_fail = "printer_does_not_exist";
  881. provider->ReverseLookup(ref_fail,
  882. base::BindOnce(&PpdProviderTest::CaptureReverseLookup,
  883. base::Unretained(this)));
  884. task_environment_.RunUntilIdle();
  885. ASSERT_EQ(2U, captured_reverse_lookup_.size());
  886. CapturedReverseLookup success_capture = captured_reverse_lookup_[0];
  887. EXPECT_EQ(PpdProvider::SUCCESS, success_capture.code);
  888. EXPECT_EQ("manufacturer_a_en", success_capture.manufacturer);
  889. EXPECT_EQ("printer_a", success_capture.model);
  890. CapturedReverseLookup failed_capture = captured_reverse_lookup_[1];
  891. EXPECT_EQ(PpdProvider::NOT_FOUND, failed_capture.code);
  892. }
  893. // Verifies that we never attempt to re-download a PPD that we
  894. // previously retrieved from the serving root. The Chrome OS Printing
  895. // Team plans to keep PPDs immutable inside the serving root, so
  896. // PpdProvider should always prefer to retrieve a PPD from the PpdCache
  897. // when it's possible to do so.
  898. TEST_F(PpdProviderTest, PreferToResolvePpdFromPpdCacheOverServingRoot) {
  899. // Explicitly *not* starting a fake server.
  900. std::string cached_ppd_contents =
  901. "These cached contents are different from what's being served";
  902. auto provider =
  903. CreateProvider({"en", PpdCacheRunLocation::kOnTestThread,
  904. PropagateLocaleToMetadataManager::kDoPropagate});
  905. Printer::PpdReference ref;
  906. ref.effective_make_and_model = "printer_a_ref";
  907. std::string cache_key = PpdProvider::PpdReferenceToCacheKey(ref);
  908. // Cache exists, and is just created, so should be fresh.
  909. //
  910. // PPD basename is taken from value specified in forward index shard
  911. // defined in server_contents().
  912. const std::string ppd_basename = "printer_a.ppd";
  913. ppd_cache_->StoreForTesting(PpdProvider::PpdBasenameToCacheKey(ppd_basename),
  914. cached_ppd_contents, base::TimeDelta());
  915. ppd_cache_->StoreForTesting(PpdProvider::PpdReferenceToCacheKey(ref),
  916. ppd_basename, base::TimeDelta());
  917. task_environment_.RunUntilIdle();
  918. provider->ResolvePpd(ref, base::BindOnce(&PpdProviderTest::CaptureResolvePpd,
  919. base::Unretained(this)));
  920. task_environment_.RunUntilIdle();
  921. ASSERT_EQ(1UL, captured_resolve_ppd_.size());
  922. // Should get the cached (not served) results back, and not have hit the
  923. // network.
  924. EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_[0].code);
  925. EXPECT_EQ(cached_ppd_contents, captured_resolve_ppd_[0].ppd_contents);
  926. }
  927. // For user-provided ppds, we should always use the latest version on
  928. // disk if it still exists there.
  929. TEST_F(PpdProviderTest, UserPpdAlwaysRefreshedIfAvailable) {
  930. base::ScopedTempDir temp_dir;
  931. std::string cached_ppd_contents = "Cached Ppd Contents";
  932. std::string disk_ppd_contents = "Updated Ppd Contents";
  933. auto provider =
  934. CreateProvider({"en", PpdCacheRunLocation::kOnTestThread,
  935. PropagateLocaleToMetadataManager::kDoPropagate});
  936. StartFakePpdServer();
  937. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  938. base::FilePath filename = temp_dir.GetPath().Append("my_spiffy.ppd");
  939. Printer::PpdReference ref;
  940. ref.user_supplied_ppd_url =
  941. base::StringPrintf("file://%s", filename.MaybeAsASCII().c_str());
  942. // Put cached_ppd_contents into the cache.
  943. ppd_cache_->StoreForTesting(PpdProvider::PpdReferenceToCacheKey(ref),
  944. cached_ppd_contents, base::TimeDelta());
  945. task_environment_.RunUntilIdle();
  946. // Write different contents to disk, so that the cached contents are
  947. // now stale.
  948. ASSERT_TRUE(base::WriteFile(filename, disk_ppd_contents));
  949. provider->ResolvePpd(ref, base::BindOnce(&PpdProviderTest::CaptureResolvePpd,
  950. base::Unretained(this)));
  951. task_environment_.RunUntilIdle();
  952. ASSERT_EQ(1UL, captured_resolve_ppd_.size());
  953. EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_[0].code);
  954. EXPECT_EQ(disk_ppd_contents, captured_resolve_ppd_[0].ppd_contents);
  955. // Check that the cache was also updated with the new contents.
  956. PpdCache::FindResult captured_find_result;
  957. ppd_cache_->Find(PpdProvider::PpdReferenceToCacheKey(ref),
  958. base::BindOnce(
  959. [](PpdCache::FindResult* captured_find_result,
  960. const PpdCache::FindResult& find_result) {
  961. *captured_find_result = find_result;
  962. },
  963. &captured_find_result));
  964. task_environment_.RunUntilIdle();
  965. EXPECT_EQ(captured_find_result.success, true);
  966. EXPECT_EQ(captured_find_result.contents, disk_ppd_contents);
  967. }
  968. // Test resolving usb manufacturer when failed to resolve PpdReference.
  969. TEST_F(PpdProviderTest, ResolveUsbManufacturer) {
  970. auto provider =
  971. CreateProvider({"en", PpdCacheRunLocation::kInBackgroundThreads,
  972. PropagateLocaleToMetadataManager::kDoPropagate});
  973. StartFakePpdServer();
  974. PrinterSearchData search_data;
  975. search_data.discovery_type = PrinterDiscoveryType::kUsb;
  976. // Vendor id that exists, nonexistent device id, should get a NOT_FOUND.
  977. // Although this is an unsupported printer model, we can still expect to get
  978. // the manufacturer name.
  979. search_data.usb_vendor_id = 0x03f0;
  980. search_data.usb_product_id = 9999;
  981. provider->ResolvePpdReference(
  982. search_data, base::BindOnce(&PpdProviderTest::CaptureResolvePpdReference,
  983. base::Unretained(this)));
  984. // Nonexistent vendor id, should get a NOT_FOUND in the real world, but
  985. // the URL interceptor we're using considers all nonexistent files to
  986. // be effectively CONNECTION REFUSED, so we just check for non-success
  987. // on this one. We should also not be able to get a manufacturer name from a
  988. // nonexistent vendor id.
  989. search_data.usb_vendor_id = 0x1234;
  990. search_data.usb_product_id = 1782;
  991. provider->ResolvePpdReference(
  992. search_data, base::BindOnce(&PpdProviderTest::CaptureResolvePpdReference,
  993. base::Unretained(this)));
  994. task_environment_.RunUntilIdle();
  995. ASSERT_EQ(static_cast<size_t>(2), captured_resolve_ppd_references_.size());
  996. // Was able to find the printer manufactuer but unable to find the printer
  997. // model should result in a NOT_FOUND.
  998. EXPECT_EQ(PpdProvider::NOT_FOUND, captured_resolve_ppd_references_[0].code);
  999. // Failed to grab the PPD for a USB printer, but should still be able to grab
  1000. // its manufacturer name.
  1001. EXPECT_EQ("HP", captured_resolve_ppd_references_[0].usb_manufacturer);
  1002. // Unable to find the PPD file should result in a failure.
  1003. EXPECT_FALSE(captured_resolve_ppd_references_[1].code ==
  1004. PpdProvider::SUCCESS);
  1005. // Unknown vendor id should result in an empty manufacturer string.
  1006. EXPECT_TRUE(captured_resolve_ppd_references_[1].usb_manufacturer.empty());
  1007. }
  1008. } // namespace
  1009. } // namespace chromeos