Commit f8c588cc authored by Kalvin Lee's avatar Kalvin Lee Committed by Commit Bot

PpdProvider v3: parse USB indices

This change implements ParseUsbIndex().

Bug: chromium:888189
Test: chromeos_unittests --gtest_filter='PpdMetadataParserTest.*'
Change-Id: Ieec6f0f1a8d68d7ebf09b3d7ce971512896a5dfd
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2335410
Commit-Queue: Kalvin Lee <kdlee@chromium.org>
Reviewed-by: default avatarLuum Habtemariam <luum@chromium.org>
Cr-Commit-Position: refs/heads/master@{#797885}
parent cb2b7dc7
...@@ -255,6 +255,34 @@ base::Optional<ParsedIndex> ParseForwardIndex( ...@@ -255,6 +255,34 @@ base::Optional<ParsedIndex> ParseForwardIndex(
return parsed_index; return parsed_index;
} }
base::Optional<ParsedUsbIndex> ParseUsbIndex(base::StringPiece usb_index_json) {
base::Optional<base::Value> usb_index = ParseJsonAndUnnestKey(
usb_index_json, "usbIndex", base::Value::Type::DICTIONARY);
if (!usb_index || usb_index->DictSize() == 0) {
return base::nullopt;
}
ParsedUsbIndex parsed_usb_index;
for (const auto& kv : usb_index->DictItems()) {
int product_id;
if (!base::StringToInt(kv.first, &product_id)) {
continue;
}
const std::string* effective_make_and_model =
kv.second.FindStringKey("effectiveMakeAndModel");
if (!effective_make_and_model || effective_make_and_model->empty()) {
continue;
}
parsed_usb_index.insert_or_assign(product_id, *effective_make_and_model);
}
if (parsed_usb_index.empty()) {
return base::nullopt;
}
return parsed_usb_index;
}
base::Optional<ParsedPrinters> ParsePrinters(base::StringPiece printers_json) { base::Optional<ParsedPrinters> ParsePrinters(base::StringPiece printers_json) {
const auto as_value = const auto as_value =
ParseJsonAndUnnestKey(printers_json, "printers", base::Value::Type::LIST); ParseJsonAndUnnestKey(printers_json, "printers", base::Value::Type::LIST);
......
...@@ -80,6 +80,9 @@ using ParsedPrinters = std::vector<ParsedPrinter>; ...@@ -80,6 +80,9 @@ using ParsedPrinters = std::vector<ParsedPrinter>;
// * Googlers, see also: go/cros-printing:ppd-metadata#index // * Googlers, see also: go/cros-printing:ppd-metadata#index
using ParsedIndex = base::flat_map<std::string, ParsedIndexValues>; using ParsedIndex = base::flat_map<std::string, ParsedIndexValues>;
// Maps USB product IDs to effective-make-and-model strings.
using ParsedUsbIndex = base::flat_map<int, std::string>;
// Keyed on effective-make-and-model strings. // Keyed on effective-make-and-model strings.
using ParsedReverseIndex = base::flat_map<std::string, ReverseIndexLeaf>; using ParsedReverseIndex = base::flat_map<std::string, ReverseIndexLeaf>;
...@@ -99,6 +102,11 @@ CHROMEOS_EXPORT base::Optional<ParsedPrinters> ParsePrinters( ...@@ -99,6 +102,11 @@ CHROMEOS_EXPORT base::Optional<ParsedPrinters> ParsePrinters(
CHROMEOS_EXPORT base::Optional<ParsedIndex> ParseForwardIndex( CHROMEOS_EXPORT base::Optional<ParsedIndex> ParseForwardIndex(
base::StringPiece forward_index_json); base::StringPiece forward_index_json);
// Parses |usb_index_json| and returns a map of USB product IDs to
// effective-make-and-model strings.
CHROMEOS_EXPORT base::Optional<ParsedUsbIndex> ParseUsbIndex(
base::StringPiece usb_index_json);
// Parses |reverse_index_json| and returns the parsed map type. // Parses |reverse_index_json| and returns the parsed map type.
CHROMEOS_EXPORT base::Optional<ParsedReverseIndex> ParseReverseIndex( CHROMEOS_EXPORT base::Optional<ParsedReverseIndex> ParseReverseIndex(
base::StringPiece reverse_index_json); base::StringPiece reverse_index_json);
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "chromeos/printing/ppd_metadata_parser.h" #include "chromeos/printing/ppd_metadata_parser.h"
#include "base/json/json_reader.h"
#include "base/strings/string_piece.h" #include "base/strings/string_piece.h"
#include "chromeos/printing/ppd_metadata_matchers.h" #include "chromeos/printing/ppd_metadata_matchers.h"
#include "testing/gmock/include/gmock/gmock-matchers.h" #include "testing/gmock/include/gmock/gmock-matchers.h"
...@@ -15,8 +16,10 @@ namespace { ...@@ -15,8 +16,10 @@ namespace {
using ::testing::AllOf; using ::testing::AllOf;
using ::testing::ElementsAre; using ::testing::ElementsAre;
using ::testing::Eq;
using ::testing::ExplainMatchResult; using ::testing::ExplainMatchResult;
using ::testing::Field; using ::testing::Field;
using ::testing::Ne;
using ::testing::Optional; using ::testing::Optional;
using ::testing::Pair; using ::testing::Pair;
using ::testing::StrEq; using ::testing::StrEq;
...@@ -554,6 +557,94 @@ TEST(PpdMetadataParserTest, ParseForwardIndexFailsGracefully) { ...@@ -554,6 +557,94 @@ TEST(PpdMetadataParserTest, ParseForwardIndexFailsGracefully) {
EXPECT_FALSE(ParseForwardIndex(kInvalidJson).has_value()); EXPECT_FALSE(ParseForwardIndex(kInvalidJson).has_value());
} }
// Verifies that ParseUsbIndex() can parse USB index metadata.
TEST(PpdMetadataParserTest, CanParseUsbIndex) {
constexpr base::StringPiece kJsonUsbIndex = R"({
"usbIndex": {
"1": {
"effectiveMakeAndModel": "d 541"
},
"10": {
"effectiveMakeAndModel": "d 504"
}
}
})";
EXPECT_THAT(ParseUsbIndex(kJsonUsbIndex),
Optional(UnorderedElementsAre(Pair(1, StrEq("d 541")),
Pair(10, StrEq("d 504")))));
}
// Verifies that ParseUsbIndex() can parse USB index metadata and return
// a partial ParsedUsbIndex even when it encounters garbage values.
TEST(PpdMetadataParserTest, CanPartiallyParseUsbIndex) {
constexpr base::StringPiece kJsonUsbIndex = R"({
"usbIndex": {
"garbage key": {
"effectiveMakeAndModel": "garbage value"
},
"1": {
"effectiveMakeAndModel": "d 541"
},
"10": {
"effectiveMakeAndModel": "d 504"
}
}
})";
EXPECT_THAT(ParseUsbIndex(kJsonUsbIndex),
Optional(UnorderedElementsAre(Pair(1, StrEq("d 541")),
Pair(10, StrEq("d 504")))));
}
// Verifies that ParseUsbIndex() returns base::nullopt rather than an
// empty container.
TEST(PpdMetadataParserTest, ParseUsbIndexDoesNotReturnEmptyContainer) {
constexpr base::StringPiece kEmptyJsonUsbIndex = R"({
"usbIndex": { }
})";
ASSERT_THAT(base::JSONReader::Read(kEmptyJsonUsbIndex), Ne(base::nullopt));
EXPECT_THAT(ParseUsbIndex(kEmptyJsonUsbIndex), Eq(base::nullopt));
constexpr base::StringPiece kJsonUsbIndexWithBadStringKeys = R"({
"usbIndex": {
"non-integral key": { }
}
})";
ASSERT_THAT(base::JSONReader::Read(kJsonUsbIndexWithBadStringKeys),
Ne(base::nullopt));
EXPECT_THAT(ParseUsbIndex(kJsonUsbIndexWithBadStringKeys), Eq(base::nullopt));
constexpr base::StringPiece kJsonUsbIndexWithoutEmmAtLeaf = R"({
"usbIndex": {
"1": {
"some key that is not ``effectiveMakeAndModel''": "d 504"
}
}
})";
ASSERT_THAT(base::JSONReader::Read(kJsonUsbIndexWithoutEmmAtLeaf),
Ne(base::nullopt));
EXPECT_THAT(ParseUsbIndex(kJsonUsbIndexWithoutEmmAtLeaf), Eq(base::nullopt));
constexpr base::StringPiece kJsonUsbIndexWithEmptyEmmAtLeaf = R"({
"usbIndex": {
"1": {
"effectiveMakeAndModel": ""
}
}
})";
ASSERT_THAT(base::JSONReader::Read(kJsonUsbIndexWithEmptyEmmAtLeaf),
Ne(base::nullopt));
EXPECT_THAT(ParseUsbIndex(kJsonUsbIndexWithEmptyEmmAtLeaf),
Eq(base::nullopt));
}
// Verifies that ParseUsbIndex() returns base::nullopt on irrecoverable
// parse error.
TEST(PpdMetadataParserTest, ParseUsbIndexFailsGracefully) {
EXPECT_THAT(ParseUsbIndex(kInvalidJson), Eq(base::nullopt));
}
// Verifies that ParseReverseIndex() can parse reverse index metadata. // Verifies that ParseReverseIndex() can parse reverse index metadata.
TEST(PpdMetadataParserTest, CanParseReverseIndex) { TEST(PpdMetadataParserTest, CanParseReverseIndex) {
constexpr base::StringPiece kReverseIndexJson = R"( constexpr base::StringPiece kReverseIndexJson = R"(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment