ppd_metadata_parser_unittest.cc 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835
  1. // Copyright 2020 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_metadata_parser.h"
  5. #include "base/json/json_reader.h"
  6. #include "base/strings/string_piece.h"
  7. #include "chromeos/printing/ppd_metadata_matchers.h"
  8. #include "testing/gmock/include/gmock/gmock-matchers.h"
  9. #include "testing/gmock/include/gmock/gmock.h"
  10. #include "testing/gtest/include/gtest/gtest.h"
  11. namespace chromeos {
  12. namespace {
  13. using ::testing::AllOf;
  14. using ::testing::ElementsAre;
  15. using ::testing::Eq;
  16. using ::testing::ExplainMatchResult;
  17. using ::testing::Field;
  18. using ::testing::Ne;
  19. using ::testing::Optional;
  20. using ::testing::Pair;
  21. using ::testing::StrEq;
  22. using ::testing::UnorderedElementsAre;
  23. constexpr base::StringPiece kInvalidJson = "blah blah invalid JSON";
  24. // Verifies that ParseLocales() can parse locales metadata.
  25. TEST(PpdMetadataParserTest, CanParseLocales) {
  26. constexpr base::StringPiece kLocalesJson = R"(
  27. {
  28. "locales": [ "de", "en", "es", "jp" ]
  29. }
  30. )";
  31. const auto parsed = ParseLocales(kLocalesJson);
  32. ASSERT_TRUE(parsed.has_value());
  33. EXPECT_THAT(*parsed,
  34. ElementsAre(StrEq("de"), StrEq("en"), StrEq("es"), StrEq("jp")));
  35. }
  36. // Verifies that ParseLocales() can parse locales and return a partial
  37. // list even when it encounters unexpected values.
  38. TEST(PpdMetadataParserTest, CanPartiallyParseLocales) {
  39. // The values "0.0" and "78" are gibberish that ParseLocales() shall
  40. // ignore; however, these don't structurally foul the JSON, so it can
  41. // still return the other locales.
  42. constexpr base::StringPiece kLocalesJson = R"(
  43. {
  44. "locales": [ 0.0, "de", 78, "en", "es", "jp" ]
  45. }
  46. )";
  47. const auto parsed = ParseLocales(kLocalesJson);
  48. ASSERT_TRUE(parsed.has_value());
  49. EXPECT_THAT(*parsed,
  50. ElementsAre(StrEq("de"), StrEq("en"), StrEq("es"), StrEq("jp")));
  51. }
  52. // Verifies that ParseLocales() returns absl::nullopt rather than an
  53. // empty container.
  54. TEST(PpdMetadataParserTest, ParseLocalesDoesNotReturnEmptyContainer) {
  55. // The values "0.0" and "78" are gibberish that ParseLocales() shall
  56. // ignore; while the JSON is still well-formed, the parsed list of
  57. // locales contains no values.
  58. constexpr base::StringPiece kLocalesJson = R"(
  59. {
  60. "locales": [ 0.0, 78 ]
  61. }
  62. )";
  63. EXPECT_FALSE(ParseLocales(kLocalesJson).has_value());
  64. }
  65. // Verifies that ParseLocales() returns absl::nullopt on irrecoverable
  66. // parse error.
  67. TEST(PpdMetadataParserTest, ParseLocalesFailsGracefully) {
  68. EXPECT_FALSE(ParseLocales(kInvalidJson).has_value());
  69. }
  70. // Verifies that ParseManufacturers() can parse manufacturers metadata.
  71. TEST(PpdMetadataParserTest, CanParseManufacturers) {
  72. constexpr base::StringPiece kManufacturersJson = R"(
  73. {
  74. "filesMap": {
  75. "Andante": "andante-en.json",
  76. "Sostenuto": "sostenuto-en.json"
  77. }
  78. }
  79. )";
  80. const auto parsed = ParseManufacturers(kManufacturersJson);
  81. ASSERT_TRUE(parsed.has_value());
  82. EXPECT_THAT(*parsed,
  83. UnorderedElementsAre(
  84. Pair(StrEq("Andante"), StrEq("andante-en.json")),
  85. Pair(StrEq("Sostenuto"), StrEq("sostenuto-en.json"))));
  86. }
  87. // Verifies that ParseManufacturers() can parse manufacturers and return
  88. // a partial list even when it encounters unexpected values.
  89. TEST(PpdMetadataParserTest, CanPartiallyParseManufacturers) {
  90. // Contains an embedded dictionary keyed on "Dearie me."
  91. // ParseManufacturers() shall ignore this.
  92. constexpr base::StringPiece kManufacturersJson = R"(
  93. {
  94. "filesMap": {
  95. "Dearie me": {
  96. "I didn't": "expect",
  97. "to go": "deeper"
  98. },
  99. "Andante": "andante-en.json",
  100. "Sostenuto": "sostenuto-en.json"
  101. }
  102. }
  103. )";
  104. const auto parsed = ParseManufacturers(kManufacturersJson);
  105. ASSERT_TRUE(parsed.has_value());
  106. EXPECT_THAT(*parsed,
  107. UnorderedElementsAre(
  108. Pair(StrEq("Andante"), StrEq("andante-en.json")),
  109. Pair(StrEq("Sostenuto"), StrEq("sostenuto-en.json"))));
  110. }
  111. // Verifies that ParseManufacturers() returns absl::nullopt rather than
  112. // an empty container.
  113. TEST(PpdMetadataParserTest, ParseManufacturersDoesNotReturnEmptyContainer) {
  114. // Contains an embedded dictionary keyed on "Dearie me."
  115. // ParseManufacturers() shall ignore this, but in doing so shall leave
  116. // its ParsedManufacturers return value empty.
  117. constexpr base::StringPiece kManufacturersJson = R"(
  118. {
  119. "filesMap": {
  120. "Dearie me": {
  121. "I didn't": "expect",
  122. "to go": "deeper"
  123. }
  124. }
  125. }
  126. )";
  127. EXPECT_FALSE(ParseManufacturers(kManufacturersJson).has_value());
  128. }
  129. // Verifies that ParseManufacturers() returns absl::nullopt on
  130. // irrecoverable parse error.
  131. TEST(PpdMetadataParserTest, ParseManufacturersFailsGracefully) {
  132. EXPECT_FALSE(ParseManufacturers(kInvalidJson).has_value());
  133. }
  134. // Verifies that ParsePrinters() can parse printers metadata.
  135. TEST(PpdMetadataParserTest, CanParsePrinters) {
  136. constexpr base::StringPiece kPrintersJson = R"(
  137. {
  138. "printers": [ {
  139. "emm": "d 547b",
  140. "name": "An die Musik"
  141. }, {
  142. "emm": "d 553",
  143. "name": "Auf der Donau"
  144. } ]
  145. }
  146. )";
  147. const auto parsed = ParsePrinters(kPrintersJson);
  148. ASSERT_TRUE(parsed.has_value());
  149. EXPECT_THAT(*parsed, UnorderedElementsAre(
  150. ParsedPrinterLike("An die Musik", "d 547b"),
  151. ParsedPrinterLike("Auf der Donau", "d 553")));
  152. }
  153. // Verifies that ParsePrinters() can parse printers and return a partial
  154. // list even when it encounters unexpected values.
  155. TEST(PpdMetadataParserTest, CanPartiallyParsePrinters) {
  156. // Contains an extra value keyed on "hello" in an otherwise valid leaf
  157. // value in Printers metadata. ParsePrinters() shall ignore this.
  158. constexpr base::StringPiece kPrintersJson = R"(
  159. {
  160. "printers": [ {
  161. "emm": "d 552",
  162. "name": "Hänflings Liebeswerbung",
  163. "hello": "there!"
  164. }, {
  165. "emm": "d 553",
  166. "name": "Auf der Donau"
  167. } ]
  168. }
  169. )";
  170. const auto parsed = ParsePrinters(kPrintersJson);
  171. ASSERT_TRUE(parsed.has_value());
  172. EXPECT_THAT(*parsed,
  173. UnorderedElementsAre(
  174. ParsedPrinterLike("Hänflings Liebeswerbung", "d 552"),
  175. ParsedPrinterLike("Auf der Donau", "d 553")));
  176. }
  177. // Verifies that ParsePrinters() can parse printers and their
  178. // well-formed restrictions (if any are specified).
  179. TEST(PpdMetadataParserTest, CanParsePrintersWithRestrictions) {
  180. // Specifies
  181. // * a printer with a minimum milestone,
  182. // * a printer with a maximum milestone, and
  183. // * a printer with both minimum and maximum milestones.
  184. constexpr base::StringPiece kPrintersJson = R"(
  185. {
  186. "printers": [ {
  187. "emm": "d 121",
  188. "name": "Schäfers Klagelied",
  189. "restriction": {
  190. "minMilestone": 121
  191. }
  192. }, {
  193. "emm": "d 216",
  194. "name": "Meeres Stille",
  195. "restriction": {
  196. "maxMilestone": 216
  197. }
  198. }, {
  199. "emm": "d 257",
  200. "name": "Heidenröslein",
  201. "restriction": {
  202. "minMilestone": 216,
  203. "maxMilestone": 257
  204. }
  205. } ]
  206. }
  207. )";
  208. const auto parsed = ParsePrinters(kPrintersJson);
  209. ASSERT_TRUE(parsed.has_value());
  210. EXPECT_THAT(*parsed,
  211. UnorderedElementsAre(
  212. AllOf(ParsedPrinterLike("Schäfers Klagelied", "d 121"),
  213. Field(&ParsedPrinter::restrictions,
  214. RestrictionsWithMinMilestone(121))),
  215. AllOf(ParsedPrinterLike("Meeres Stille", "d 216"),
  216. Field(&ParsedPrinter::restrictions,
  217. RestrictionsWithMaxMilestone(216))),
  218. AllOf(ParsedPrinterLike("Heidenröslein", "d 257"),
  219. Field(&ParsedPrinter::restrictions,
  220. RestrictionsWithMinAndMaxMilestones(216, 257)))));
  221. }
  222. // Verifies that ParsePrinters() can parse printers and ignore
  223. // malformed restrictions.
  224. TEST(PpdMetadataParserTest, CanParsePrintersWithMalformedRestrictions) {
  225. // Specifies a printer with invalid restrictions.
  226. constexpr base::StringPiece kPrintersJson = R"(
  227. {
  228. "printers": [ {
  229. "emm": "d 368",
  230. "name": "Jägers Abendlied",
  231. "restriction": {
  232. "hello": "there!"
  233. }
  234. } ]
  235. }
  236. )";
  237. const auto parsed = ParsePrinters(kPrintersJson);
  238. ASSERT_TRUE(parsed.has_value());
  239. EXPECT_THAT(
  240. *parsed,
  241. UnorderedElementsAre(
  242. AllOf(ParsedPrinterLike("Jägers Abendlied", "d 368"),
  243. Field(&ParsedPrinter::restrictions, UnboundedRestrictions()))));
  244. }
  245. // Verifies that ParsePrinters() returns absl::nullopt rather than an
  246. // empty container.
  247. TEST(PpdMetadataParserTest, ParsePrintersDoesNotReturnEmptyContainer) {
  248. // No printers are specified in this otherwise valid JSON dictionary.
  249. EXPECT_FALSE(ParsePrinters("{}").has_value());
  250. }
  251. // Verifies that ParsePrinters() returns absl::nullopt on irrecoverable
  252. // parse error.
  253. TEST(PpdMetadataParserTest, ParsePrintersFailsGracefully) {
  254. EXPECT_FALSE(ParsePrinters(kInvalidJson).has_value());
  255. }
  256. // Verifies that ParseForwardIndex() can parse forward index metadata.
  257. TEST(PpdMetadataParserTest, CanParseForwardIndex) {
  258. constexpr base::StringPiece kJsonForwardIndex = R"({
  259. "ppdIndex": {
  260. "der wanderer": {
  261. "ppdMetadata": [ {
  262. "name": "d-489.ppd.gz"
  263. } ]
  264. },
  265. "morgenlied": {
  266. "ppdMetadata": [ {
  267. "name": "d-685.ppd.gz"
  268. } ]
  269. },
  270. "wandrers nachtlied": {
  271. "ppdMetadata": [ {
  272. "name": "d-224.ppd.gz"
  273. } ]
  274. }
  275. }
  276. })";
  277. const auto parsed = ParseForwardIndex(kJsonForwardIndex);
  278. ASSERT_TRUE(parsed.has_value());
  279. EXPECT_THAT(
  280. parsed.value(),
  281. UnorderedElementsAre(
  282. ParsedIndexEntryLike(
  283. "der wanderer",
  284. UnorderedElementsAre(
  285. ParsedIndexLeafWithPpdBasename("d-489.ppd.gz"))),
  286. ParsedIndexEntryLike(
  287. "morgenlied", UnorderedElementsAre(ParsedIndexLeafWithPpdBasename(
  288. "d-685.ppd.gz"))),
  289. ParsedIndexEntryLike(
  290. "wandrers nachtlied",
  291. UnorderedElementsAre(
  292. ParsedIndexLeafWithPpdBasename("d-224.ppd.gz")))));
  293. }
  294. // Verifies that ParseForwardIndex() can parse forward index metadata
  295. // and return a partial list even when it encounters unexpected values.
  296. TEST(PpdMetadataParserTest, CanPartiallyParseForwardIndex) {
  297. // Uses the same value as the CanParseForwardIndex test, but
  298. // with garbage values mixed in.
  299. constexpr base::StringPiece kJsonForwardIndex = R"({
  300. "ppdIndex": {
  301. "garbage": "unused value",
  302. "more garbage": [ "more", "unused", "values" ],
  303. "der wanderer": {
  304. "ppdMetadata": [ {
  305. "name": "d-489.ppd.gz",
  306. "more garbage still": "unused value"
  307. }, {
  308. "also garbage": "unused value"
  309. } ],
  310. "unending garbage": "unused value"
  311. },
  312. "morgenlied": {
  313. "ppdMetadata": [ {
  314. "name": "d-685.ppd.gz"
  315. } ]
  316. },
  317. "wandrers nachtlied": {
  318. "ppdMetadata": [ {
  319. "name": "d-224.ppd.gz"
  320. } ]
  321. }
  322. }
  323. })";
  324. const auto parsed = ParseForwardIndex(kJsonForwardIndex);
  325. ASSERT_TRUE(parsed.has_value());
  326. EXPECT_THAT(
  327. parsed.value(),
  328. UnorderedElementsAre(
  329. ParsedIndexEntryLike(
  330. "der wanderer",
  331. UnorderedElementsAre(
  332. ParsedIndexLeafWithPpdBasename("d-489.ppd.gz"))),
  333. ParsedIndexEntryLike(
  334. "morgenlied", UnorderedElementsAre(ParsedIndexLeafWithPpdBasename(
  335. "d-685.ppd.gz"))),
  336. ParsedIndexEntryLike(
  337. "wandrers nachtlied",
  338. UnorderedElementsAre(
  339. ParsedIndexLeafWithPpdBasename("d-224.ppd.gz")))));
  340. }
  341. // Verifies that ParseForwardIndex() can parse forward index metadata
  342. // in which leaf values have multiple ppdMetadata key-value pairs.
  343. TEST(PpdMetadataParserTest, CanParseForwardIndexWithMultiplePpdMetadataLeafs) {
  344. constexpr base::StringPiece kJsonForwardIndex = R"({
  345. "ppdIndex": {
  346. "rastlose liebe": {
  347. "ppdMetadata": [ {
  348. "name": "d-138.ppd.gz"
  349. }, {
  350. "name": "1815.ppd.gz"
  351. } ]
  352. }
  353. }
  354. })";
  355. const auto parsed = ParseForwardIndex(kJsonForwardIndex);
  356. ASSERT_TRUE(parsed.has_value());
  357. EXPECT_THAT(parsed.value(),
  358. UnorderedElementsAre(ParsedIndexEntryLike(
  359. "rastlose liebe",
  360. UnorderedElementsAre(
  361. ParsedIndexLeafWithPpdBasename("d-138.ppd.gz"),
  362. ParsedIndexLeafWithPpdBasename("1815.ppd.gz")))));
  363. }
  364. // Verifies that ParseForwardIndex() can parse forward index metadata
  365. // and its well-formed restrictions (if any are specified).
  366. TEST(PpdMetadataParserTest, CanParseForwardIndexWithRestrictions) {
  367. // Specifies
  368. // * a PPD metadata leaf with a minimum milestone,
  369. // * a PPD metadata leaf with a maximum milestone, and
  370. // * a PPD metadata leaf with both minimum and maximum milestones.
  371. constexpr base::StringPiece kJsonForwardIndex = R"({
  372. "ppdIndex": {
  373. "nähe des geliebten": {
  374. "ppdMetadata": [ {
  375. "name": "d-162.ppd.gz",
  376. "restriction": {
  377. "minMilestone": 25
  378. }
  379. } ]
  380. },
  381. "der fischer": {
  382. "ppdMetadata": [ {
  383. "name": "d-225.ppd.gz",
  384. "restriction": {
  385. "maxMilestone": 35
  386. }
  387. } ]
  388. },
  389. "erster verlust": {
  390. "ppdMetadata": [ {
  391. "name": "d-226.ppd.gz",
  392. "restriction": {
  393. "minMilestone": 45,
  394. "maxMilestone": 46
  395. }
  396. } ]
  397. }
  398. }
  399. })";
  400. const auto parsed = ParseForwardIndex(kJsonForwardIndex);
  401. ASSERT_TRUE(parsed.has_value());
  402. EXPECT_THAT(
  403. parsed.value(),
  404. UnorderedElementsAre(
  405. ParsedIndexEntryLike(
  406. "nähe des geliebten",
  407. UnorderedElementsAre(
  408. AllOf(ParsedIndexLeafWithPpdBasename("d-162.ppd.gz"),
  409. Field(&ParsedIndexLeaf::restrictions,
  410. RestrictionsWithMinMilestone(25))))),
  411. ParsedIndexEntryLike(
  412. "der fischer", UnorderedElementsAre(AllOf(
  413. ParsedIndexLeafWithPpdBasename("d-225.ppd.gz"),
  414. Field(&ParsedIndexLeaf::restrictions,
  415. RestrictionsWithMaxMilestone(35))))),
  416. ParsedIndexEntryLike(
  417. "erster verlust",
  418. UnorderedElementsAre(
  419. AllOf(ParsedIndexLeafWithPpdBasename("d-226.ppd.gz"),
  420. Field(&ParsedIndexLeaf::restrictions,
  421. RestrictionsWithMinAndMaxMilestones(45, 46)))))));
  422. }
  423. // Verifies that ParseForwardIndex() can parse forward index metadata
  424. // and ignore malformed restrictions.
  425. TEST(PpdMetadataParserTest, CanParseForwardIndexWithMalformedRestrictions) {
  426. // Same test data as the CanParseForwardIndexWithRestrictions test
  427. // above, but defines
  428. // * a PPD metadata leaf with a malformed minimum milestone,
  429. // * a PPD metadata leaf with a malformed maximum milestone, and
  430. // * a PPD metadata leaf with malformed minimum and maximum
  431. // milestones.
  432. constexpr base::StringPiece kJsonForwardIndex = R"({
  433. "ppdIndex": {
  434. "nähe des geliebten": {
  435. "ppdMetadata": [ {
  436. "name": "d-162.ppd.gz",
  437. "restriction": {
  438. "minMilestone": "garbage value",
  439. "maxMilestone": 25
  440. }
  441. } ]
  442. },
  443. "der fischer": {
  444. "ppdMetadata": [ {
  445. "name": "d-225.ppd.gz",
  446. "restriction": {
  447. "minMilestone": 35,
  448. "maxMilestone": "garbage value"
  449. }
  450. } ]
  451. },
  452. "erster verlust": {
  453. "ppdMetadata": [ {
  454. "name": "d-226.ppd.gz",
  455. "restriction": {
  456. "minMilestone": "garbage value",
  457. "maxMilestone": "garbage value"
  458. }
  459. } ]
  460. }
  461. }
  462. })";
  463. const auto parsed = ParseForwardIndex(kJsonForwardIndex);
  464. ASSERT_TRUE(parsed.has_value());
  465. EXPECT_THAT(
  466. parsed.value(),
  467. UnorderedElementsAre(
  468. ParsedIndexEntryLike(
  469. "nähe des geliebten",
  470. UnorderedElementsAre(
  471. AllOf(ParsedIndexLeafWithPpdBasename("d-162.ppd.gz"),
  472. Field(&ParsedIndexLeaf::restrictions,
  473. RestrictionsWithMaxMilestone(25))))),
  474. ParsedIndexEntryLike(
  475. "der fischer", UnorderedElementsAre(AllOf(
  476. ParsedIndexLeafWithPpdBasename("d-225.ppd.gz"),
  477. Field(&ParsedIndexLeaf::restrictions,
  478. RestrictionsWithMinMilestone(35))))),
  479. ParsedIndexEntryLike(
  480. "erster verlust",
  481. UnorderedElementsAre(
  482. AllOf(ParsedIndexLeafWithPpdBasename("d-226.ppd.gz"),
  483. Field(&ParsedIndexLeaf::restrictions,
  484. UnboundedRestrictions()))))));
  485. }
  486. // Verifies that ParseForwardIndex() can parse forward index metadata
  487. // specifying PPD licenses.
  488. TEST(PpdMetadataParserTest, CanParseForwardIndexWithLicenses) {
  489. // Specifies two PPDs, each with a license associated.
  490. constexpr base::StringPiece kJsonForwardIndex = R"({
  491. "ppdIndex": {
  492. "der fischer": {
  493. "ppdMetadata": [ {
  494. "name": "d-225.ppd.gz",
  495. "license": "two two five license"
  496. } ]
  497. },
  498. "erster verlust": {
  499. "ppdMetadata": [ {
  500. "name": "d-226.ppd.gz",
  501. "license": "two two six license"
  502. } ]
  503. }
  504. }
  505. })";
  506. const auto parsed = ParseForwardIndex(kJsonForwardIndex);
  507. ASSERT_TRUE(parsed.has_value());
  508. EXPECT_THAT(
  509. parsed.value(),
  510. UnorderedElementsAre(
  511. ParsedIndexEntryLike(
  512. "der fischer", UnorderedElementsAre(AllOf(
  513. ParsedIndexLeafWithPpdBasename("d-225.ppd.gz"),
  514. Field(&ParsedIndexLeaf::license,
  515. StrEq("two two five license"))))),
  516. ParsedIndexEntryLike(
  517. "erster verlust",
  518. UnorderedElementsAre(
  519. AllOf(ParsedIndexLeafWithPpdBasename("d-226.ppd.gz"),
  520. Field(&ParsedIndexLeaf::license,
  521. StrEq("two two six license")))))));
  522. }
  523. // Verifies that ParseForwardIndex() returns absl::nullopt rather than
  524. // an empty container.
  525. TEST(PpdMetadataParserTest, ParseForwardIndexDoesNotReturnEmptyContainer) {
  526. // Specifies a forward index that is valid JSON but which has
  527. // no PPDs whose leaf values are non-empty.
  528. constexpr base::StringPiece kJsonForwardIndex = R"({
  529. "ppdIndex": {
  530. "der könig in thule": {
  531. "ppdMetadata": [ {
  532. "garbage": "unused value"
  533. } ]
  534. }
  535. }
  536. })";
  537. EXPECT_FALSE(ParseForwardIndex(kJsonForwardIndex).has_value());
  538. }
  539. // Verifies that ParseForwardIndex() returns absl::nullopt on
  540. // irrecoverable parse error.
  541. TEST(PpdMetadataParserTest, ParseForwardIndexFailsGracefully) {
  542. EXPECT_FALSE(ParseForwardIndex(kInvalidJson).has_value());
  543. }
  544. // Verifies that ParseUsbIndex() can parse USB index metadata.
  545. TEST(PpdMetadataParserTest, CanParseUsbIndex) {
  546. constexpr base::StringPiece kJsonUsbIndex = R"({
  547. "usbIndex": {
  548. "1": {
  549. "effectiveMakeAndModel": "d 541"
  550. },
  551. "10": {
  552. "effectiveMakeAndModel": "d 504"
  553. }
  554. }
  555. })";
  556. EXPECT_THAT(ParseUsbIndex(kJsonUsbIndex),
  557. Optional(UnorderedElementsAre(Pair(1, StrEq("d 541")),
  558. Pair(10, StrEq("d 504")))));
  559. }
  560. // Verifies that ParseUsbIndex() can parse USB index metadata and return
  561. // a partial ParsedUsbIndex even when it encounters garbage values.
  562. TEST(PpdMetadataParserTest, CanPartiallyParseUsbIndex) {
  563. constexpr base::StringPiece kJsonUsbIndex = R"({
  564. "usbIndex": {
  565. "garbage key": {
  566. "effectiveMakeAndModel": "garbage value"
  567. },
  568. "1": {
  569. "effectiveMakeAndModel": "d 541"
  570. },
  571. "10": {
  572. "effectiveMakeAndModel": "d 504"
  573. }
  574. }
  575. })";
  576. EXPECT_THAT(ParseUsbIndex(kJsonUsbIndex),
  577. Optional(UnorderedElementsAre(Pair(1, StrEq("d 541")),
  578. Pair(10, StrEq("d 504")))));
  579. }
  580. // Verifies that ParseUsbIndex() returns absl::nullopt rather than an
  581. // empty container.
  582. TEST(PpdMetadataParserTest, ParseUsbIndexDoesNotReturnEmptyContainer) {
  583. constexpr base::StringPiece kEmptyJsonUsbIndex = R"({
  584. "usbIndex": { }
  585. })";
  586. ASSERT_THAT(base::JSONReader::Read(kEmptyJsonUsbIndex), Ne(absl::nullopt));
  587. EXPECT_THAT(ParseUsbIndex(kEmptyJsonUsbIndex), Eq(absl::nullopt));
  588. constexpr base::StringPiece kJsonUsbIndexWithBadStringKeys = R"({
  589. "usbIndex": {
  590. "non-integral key": { }
  591. }
  592. })";
  593. ASSERT_THAT(base::JSONReader::Read(kJsonUsbIndexWithBadStringKeys),
  594. Ne(absl::nullopt));
  595. EXPECT_THAT(ParseUsbIndex(kJsonUsbIndexWithBadStringKeys), Eq(absl::nullopt));
  596. constexpr base::StringPiece kJsonUsbIndexWithoutEmmAtLeaf = R"({
  597. "usbIndex": {
  598. "1": {
  599. "some key that is not ``effectiveMakeAndModel''": "d 504"
  600. }
  601. }
  602. })";
  603. ASSERT_THAT(base::JSONReader::Read(kJsonUsbIndexWithoutEmmAtLeaf),
  604. Ne(absl::nullopt));
  605. EXPECT_THAT(ParseUsbIndex(kJsonUsbIndexWithoutEmmAtLeaf), Eq(absl::nullopt));
  606. constexpr base::StringPiece kJsonUsbIndexWithEmptyEmmAtLeaf = R"({
  607. "usbIndex": {
  608. "1": {
  609. "effectiveMakeAndModel": ""
  610. }
  611. }
  612. })";
  613. ASSERT_THAT(base::JSONReader::Read(kJsonUsbIndexWithEmptyEmmAtLeaf),
  614. Ne(absl::nullopt));
  615. EXPECT_THAT(ParseUsbIndex(kJsonUsbIndexWithEmptyEmmAtLeaf),
  616. Eq(absl::nullopt));
  617. }
  618. // Verifies that ParseUsbIndex() returns absl::nullopt on irrecoverable
  619. // parse error.
  620. TEST(PpdMetadataParserTest, ParseUsbIndexFailsGracefully) {
  621. EXPECT_THAT(ParseUsbIndex(kInvalidJson), Eq(absl::nullopt));
  622. }
  623. // Verifies that ParseUsbvendorIdMap() can parse USB vendor ID maps.
  624. TEST(PpdMetadataParserTest, CanParseUsbVendorIdMap) {
  625. constexpr base::StringPiece kJsonUsbVendorIdMap = R"({
  626. "entries": [ {
  627. "vendorId": 1111,
  628. "vendorName": "One One One One"
  629. }, {
  630. "vendorId": 2222,
  631. "vendorName": "Two Two Two Two"
  632. }, {
  633. "vendorId": 3333,
  634. "vendorName": "Three Three Three Three"
  635. } ]
  636. })";
  637. EXPECT_THAT(ParseUsbVendorIdMap(kJsonUsbVendorIdMap),
  638. Optional(UnorderedElementsAre(
  639. Pair(1111, StrEq("One One One One")),
  640. Pair(2222, StrEq("Two Two Two Two")),
  641. Pair(3333, StrEq("Three Three Three Three")))));
  642. }
  643. // Verifies that ParseUsbvendorIdMap() can parse USB vendor ID maps and
  644. // return partial results even when it encounters garbage values.
  645. TEST(PpdMetadataParserTest, CanPartiallyParseUsbVendorIdMap) {
  646. // This USB vendor ID map has garbage values in it.
  647. // ParseUsbVendorIdMap() shall ignore these.
  648. constexpr base::StringPiece kJsonUsbVendorIdMap = R"({
  649. "garbage key": "garbage value",
  650. "entries": [
  651. "garbage value",
  652. {
  653. "vendorId": 1111,
  654. "garbage key": "garbage value",
  655. "vendorName": "One One One One"
  656. }, {
  657. "vendorId": 2222,
  658. "vendorName": "Two Two Two Two"
  659. }, {
  660. "vendorId": 3333,
  661. "vendorName": "Three Three Three Three"
  662. } ]
  663. })";
  664. EXPECT_THAT(ParseUsbVendorIdMap(kJsonUsbVendorIdMap),
  665. Optional(UnorderedElementsAre(
  666. Pair(1111, StrEq("One One One One")),
  667. Pair(2222, StrEq("Two Two Two Two")),
  668. Pair(3333, StrEq("Three Three Three Three")))));
  669. }
  670. // Verifies that ParseUsbvendorIdMap() returns absl::nullopt rather
  671. // than an empty container.
  672. TEST(PpdMetadataParserTest, ParseUsbVendorIdMapDoesNotReturnEmptyContainer) {
  673. // Defines a USB vendor ID map that is empty; it's valid JSON, but
  674. // has no values worth returning.
  675. constexpr base::StringPiece kJsonUsbVendorIdMap = "{}";
  676. EXPECT_THAT(ParseUsbVendorIdMap(kJsonUsbVendorIdMap), Eq(absl::nullopt));
  677. }
  678. // Verifies that ParseUsbvendorIdMap() returns absl::nullopt on
  679. // irrecoverable parse error.
  680. TEST(PpdMetadataParserTest, ParseUsbVendorIdMapFailsGracefully) {
  681. EXPECT_THAT(ParseUsbVendorIdMap(kInvalidJson), Eq(absl::nullopt));
  682. }
  683. // Verifies that ParseReverseIndex() can parse reverse index metadata.
  684. TEST(PpdMetadataParserTest, CanParseReverseIndex) {
  685. constexpr base::StringPiece kReverseIndexJson = R"(
  686. {
  687. "reverseIndex": {
  688. "Die Forelle D 550d": {
  689. "manufacturer": "metsukabi",
  690. "model": "kimebe"
  691. },
  692. "Gruppe aus dem Tartarus D 583": {
  693. "manufacturer": "teiga",
  694. "model": "dahuho"
  695. }
  696. }
  697. }
  698. )";
  699. const auto parsed = ParseReverseIndex(kReverseIndexJson);
  700. ASSERT_TRUE(parsed.has_value());
  701. EXPECT_THAT(*parsed, UnorderedElementsAre(
  702. Pair(StrEq("Die Forelle D 550d"),
  703. ReverseIndexLeafLike("metsukabi", "kimebe")),
  704. Pair(StrEq("Gruppe aus dem Tartarus D 583"),
  705. ReverseIndexLeafLike("teiga", "dahuho"))));
  706. }
  707. // Verifies that ParseReverseIndex() can parse reverse index metadata
  708. // and return a partial list even when it encounters unexpected values.
  709. TEST(PpdMetadataParserTest, CanPartiallyParseReverseIndex) {
  710. // Contains two unexpected values (keyed on "Dearie me" and "to go").
  711. // ParseReverseIndex() shall ignore these.
  712. constexpr base::StringPiece kReverseIndexJson = R"(
  713. {
  714. "reverseIndex": {
  715. "Dearie me": "one doesn't expect",
  716. "to go": "any deeper",
  717. "Elysium D 584": {
  718. "manufacturer": "nahopenu",
  719. "model": "sapudo"
  720. },
  721. "An den Tod D 518": {
  722. "manufacturer": "suwaka",
  723. "model": "zogegi"
  724. }
  725. }
  726. }
  727. )";
  728. const auto parsed = ParseReverseIndex(kReverseIndexJson);
  729. ASSERT_TRUE(parsed.has_value());
  730. EXPECT_THAT(*parsed, UnorderedElementsAre(
  731. Pair(StrEq("Elysium D 584"),
  732. ReverseIndexLeafLike("nahopenu", "sapudo")),
  733. Pair(StrEq("An den Tod D 518"),
  734. ReverseIndexLeafLike("suwaka", "zogegi"))));
  735. }
  736. // Verifies that ParseReverseIndex() returns absl::nullopt rather than
  737. // an empty container.
  738. TEST(PpdMetadataParserTest, ParseReverseIndexDoesNotReturnEmptyContainer) {
  739. // Contains two unexpected values (keyed on "Dearie me" and "to go").
  740. // ParseReverseIndex() shall ignore this, but in doing so shall make the
  741. // returned ParsedReverseIndex empty.
  742. constexpr base::StringPiece kReverseIndexJson = R"(
  743. {
  744. "reverseIndex": {
  745. "Dearie me": "one doesn't expect",
  746. "to go": "any deeper"
  747. }
  748. }
  749. )";
  750. EXPECT_FALSE(ParseReverseIndex(kReverseIndexJson).has_value());
  751. }
  752. // Verifies that ParseReverseIndex() returns absl::nullopt on
  753. // irrecoverable parse error.
  754. TEST(PpdMetadataParserTest, ParseReverseIndexFailsGracefully) {
  755. EXPECT_FALSE(ParseReverseIndex(kInvalidJson).has_value());
  756. }
  757. } // namespace
  758. } // namespace chromeos