Skip to content

Commit b4721d9

Browse files
authored
[ProtoApiScrubber] Add missing UT in field checker and reformat comments. (#42277)
Signed-off-by: Sumit Kumar <[email protected]>
1 parent dc9a0de commit b4721d9

File tree

1 file changed

+58
-37
lines changed

1 file changed

+58
-37
lines changed

test/extensions/filters/http/proto_api_scrubber/scrubbing_util_lib/field_checker_test.cc

Lines changed: 58 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -102,15 +102,15 @@ class FieldCheckerTest : public ::testing::Test {
102102
.WillByDefault(testing::ReturnRef(server_factory_context_));
103103
}
104104

105-
// Helper to load descriptors (shared by all configs)
105+
// Helper to load descriptors (shared by all configs).
106106
void loadDescriptors(ProtoApiScrubberConfig& config) {
107107
*config.mutable_descriptor_set()->mutable_data_source()->mutable_inline_bytes() =
108108
api_->fileSystem()
109109
.fileReadToEnd(Envoy::TestEnvironment::runfilesPath(kApiKeysDescriptorRelativePath))
110110
.value();
111111
}
112112

113-
// Helper to initialize the filter config from a specific Proto config
113+
// Helper to initialize the filter config from a specific Proto config.
114114
void initializeFilterConfig(ProtoApiScrubberConfig& config) {
115115
loadDescriptors(config);
116116
absl::StatusOr<std::shared_ptr<const ProtoApiScrubberFilterConfig>> filter_config =
@@ -126,7 +126,7 @@ class FieldCheckerTest : public ::testing::Test {
126126
void addRestriction(ProtoApiScrubberConfig& config, const std::string& method_name,
127127
const std::string& field_path, FieldType field_type, bool match_result) {
128128

129-
// CEL Matcher Template
129+
// CEL Matcher Template.
130130
static constexpr absl::string_view matcher_template = R"pb(
131131
matcher_list: {
132132
matchers: {
@@ -320,6 +320,7 @@ TEST_F(RequestFieldCheckerTest, PrimitiveAndMessageType) {
320320
addRestriction(config, method,
321321
"filter_criteria.publication_details.original_release_info.region_code",
322322
FieldType::Request, true);
323+
addRestriction(config, method, "key.key.display_name", FieldType::Request, true);
323324

324325
initializeFilterConfig(config);
325326

@@ -373,13 +374,33 @@ TEST_F(RequestFieldCheckerTest, PrimitiveAndMessageType) {
373374
// The field `id` has a match tree configured which always evaluates to true and has a match
374375
// action configured of type
375376
// `envoy.extensions.filters.http.proto_api_scrubber.v3.RemoveFieldAction`
376-
// and hence, CheckField returns kInclude.
377+
// and hence, CheckField returns kExclude.
377378
Protobuf::Field field;
378379
field.set_name("id");
379380
field.set_kind(Protobuf::Field_Kind_TYPE_INT64);
380381
EXPECT_EQ(field_checker.CheckField({"id"}, &field), FieldCheckResults::kExclude);
381382
}
382383

384+
{
385+
// The field `key.key.display_name` has a match tree configured which always evaluates to true
386+
// and has a match action configured of type
387+
// `envoy.extensions.filters.http.proto_api_scrubber.v3.RemoveFieldAction`
388+
// and hence, CheckField returns kExclude.
389+
// While the field `key.key.internal_name` has a match tree configured which always evaluates
390+
// to false and hence, CheckField returns kInclude.
391+
Protobuf::Field field1;
392+
field1.set_name("display_name");
393+
field1.set_kind(Protobuf::Field_Kind_TYPE_STRING);
394+
EXPECT_EQ(field_checker.CheckField({"key", "key", "display_name"}, &field1),
395+
FieldCheckResults::kExclude);
396+
397+
Protobuf::Field field2;
398+
field2.set_name("internal_name");
399+
field2.set_kind(Protobuf::Field_Kind_TYPE_STRING);
400+
EXPECT_EQ(field_checker.CheckField({"key", "key", "internal_name"}, &field2),
401+
FieldCheckResults::kInclude);
402+
}
403+
383404
{
384405
// The field `filter_criteria.publication_details.original_release_info.region_code` has a match
385406
// tree configured which always evaluates to true and has a match action configured of type
@@ -421,13 +442,13 @@ TEST_F(RequestFieldCheckerTest, ArrayType) {
421442
ProtoApiScrubberConfig config;
422443
std::string method = "/library.BookService/UpdateBook";
423444

424-
// Top-level repeated primitive: "tags" -> Remove
445+
// Top-level repeated primitive: "tags" -> Remove.
425446
addRestriction(config, method, "tags", FieldType::Request, true);
426447

427-
// Nested repeated primitive: "metadata.history.edits" -> Remove
448+
// Nested repeated primitive: "metadata.history.edits" -> Remove.
428449
addRestriction(config, method, "metadata.history.edits", FieldType::Request, true);
429450

430-
// Repeated Message: "chapters" -> No Rule (Should result in Partial to scrub children)
451+
// Repeated Message: "chapters" -> No Rule (Should result in Partial to scrub children).
431452

432453
initializeFilterConfig(config);
433454

@@ -436,7 +457,7 @@ TEST_F(RequestFieldCheckerTest, ArrayType) {
436457
filter_config_.get());
437458

438459
{
439-
// Case 1: Top-level repeated primitive (e.g., repeated string tags)
460+
// Case 1: Top-level repeated primitive (e.g., repeated string tags).
440461
// Configured to be removed.
441462
Protobuf::Field field;
442463
field.set_name("tags");
@@ -447,8 +468,8 @@ TEST_F(RequestFieldCheckerTest, ArrayType) {
447468
}
448469

449470
{
450-
// Case 2: Deeply nested repeated primitive
451-
// Path: metadata.history.edits
471+
// Case 2: Deeply nested repeated primitive.
472+
// Path: metadata.history.edits.
452473
// Configured to be removed.
453474
Protobuf::Field field;
454475
field.set_name("edits");
@@ -460,7 +481,7 @@ TEST_F(RequestFieldCheckerTest, ArrayType) {
460481
}
461482

462483
{
463-
// Case 3: Repeated Message (e.g., repeated Chapter chapters)
484+
// Case 3: Repeated Message (e.g., repeated Chapter chapters).
464485
// No specific matcher on the list itself.
465486
// Should return kPartial so the scrubber iterates over the elements.
466487
Protobuf::Field field;
@@ -472,7 +493,7 @@ TEST_F(RequestFieldCheckerTest, ArrayType) {
472493
}
473494

474495
{
475-
// Case 4: Repeated Primitive with NO matcher
496+
// Case 4: Repeated Primitive with NO matcher.
476497
// Should return kInclude (keep the whole list).
477498
Protobuf::Field field;
478499
field.set_name("flags");
@@ -485,13 +506,13 @@ TEST_F(RequestFieldCheckerTest, ArrayType) {
485506

486507
// Tests CheckField() specifically for enum fields in the request.
487508
TEST_F(RequestFieldCheckerTest, EnumType) {
488-
// Setup local mock config
509+
// Setup local mock config.
489510
auto mock_config = std::make_shared<NiceMock<MockProtoApiScrubberFilterConfig>>();
490511
NiceMock<StreamInfo::MockStreamInfo> mock_stream_info;
491512
const std::string method = "/pkg.Service/UpdateConfig";
492513

493-
// Field-Level Rule: Remove 'legacy_status' entirely
494-
// Path passed to `CheckField()` method: "config.legacy_status" (No integer suffix yet)
514+
// Field-Level Rule: Remove 'legacy_status' entirely.
515+
// Path passed to `CheckField()` method: "config.legacy_status" (No integer suffix yet).
495516
auto exclude_tree = std::make_shared<NiceMock<MockMatchTree>>();
496517
auto remove_action = std::make_shared<NiceMock<MockAction>>();
497518
ON_CALL(*remove_action, typeUrl())
@@ -502,20 +523,20 @@ TEST_F(RequestFieldCheckerTest, EnumType) {
502523
ON_CALL(*mock_config, getRequestFieldMatcher(method, "config.legacy_status"))
503524
.WillByDefault(testing::Return(exclude_tree));
504525

505-
// Value-Level Rules: 'status' field
506-
// Rule 1: "config.status.DEBUG_MODE" (99) -> Remove
526+
// Value-Level Rules: 'status' field.
527+
// Rule 1: "config.status.DEBUG_MODE" (99) -> Remove.
507528
setupMockEnumRule(*mock_config, method, "config.status", "type.googleapis.com/pkg.Status", 99,
508529
"DEBUG_MODE", true);
509530

510-
// Rule 2: "config.status.OK" (0) -> Keep
531+
// Rule 2: "config.status.OK" (0) -> Keep.
511532
setupMockEnumRule(*mock_config, method, "config.status", "type.googleapis.com/pkg.Status", 0,
512533
"OK", false);
513534

514535
FieldChecker field_checker(ScrubberContext::kRequestScrubbing, &mock_stream_info, method,
515536
mock_config.get());
516537

517538
{
518-
// Scenario 1: Field-Level Scrubbing
539+
// Scenario 1: Field-Level Scrubbing.
519540
// The scrubber checks the field definition before reading values.
520541
Protobuf::Field field;
521542
field.set_name("legacy_status");
@@ -526,7 +547,7 @@ TEST_F(RequestFieldCheckerTest, EnumType) {
526547
}
527548

528549
{
529-
// Scenario 2: Value-Level Scrubbing (Specific Value matches Rule)
550+
// Scenario 2: Value-Level Scrubbing (Specific Value matches Rule).
530551
// The scrubber reads value 99, translates to DEBUG_MODE.
531552
Protobuf::Field field;
532553
field.set_name("status");
@@ -538,7 +559,7 @@ TEST_F(RequestFieldCheckerTest, EnumType) {
538559
}
539560

540561
{
541-
// Scenario 3: Value-Level Pass-through (Specific Value has no Rule/Keep)
562+
// Scenario 3: Value-Level Pass-through (Specific Value has no Rule/Keep).
542563
// The scrubber reads value 0, translates to OK.
543564
Protobuf::Field field;
544565
field.set_name("status");
@@ -550,8 +571,8 @@ TEST_F(RequestFieldCheckerTest, EnumType) {
550571
}
551572

552573
{
553-
// Scenario 4: Unknown Enum Value (Fallback)
554-
// Input: Value 123
574+
// Scenario 4: Unknown Enum Value (Fallback).
575+
// Input: Value 123.
555576
// Logic: getEnumName returns error.
556577
// FieldChecker constructs mask "config.status.123".
557578
// No matcher for that mask -> kInclude.
@@ -676,13 +697,13 @@ TEST_F(ResponseFieldCheckerTest, ArrayType) {
676697
ProtoApiScrubberConfig config;
677698
std::string method = "/library.BookService/GetBook";
678699

679-
// Top-level repeated primitive: "comments" -> Remove
700+
// Top-level repeated primitive: "comments" -> Remove.
680701
addRestriction(config, method, "comments", FieldType::Response, true);
681702

682-
// Nested repeated primitive: "author.awards" -> Remove
703+
// Nested repeated primitive: "author.awards" -> Remove.
683704
addRestriction(config, method, "author.awards", FieldType::Response, true);
684705

685-
// Repeated Message: "tags" -> No Rule (Should result in Partial to scrub children)
706+
// Repeated Message: "tags" -> No Rule (Should result in Partial to scrub children).
686707

687708
initializeFilterConfig(config);
688709

@@ -691,7 +712,7 @@ TEST_F(ResponseFieldCheckerTest, ArrayType) {
691712
filter_config_.get());
692713

693714
{
694-
// Case 1: Top-level repeated primitive
715+
// Case 1: Top-level repeated primitive.
695716
Protobuf::Field field;
696717
field.set_name("comments");
697718
field.set_kind(Protobuf::Field_Kind_TYPE_STRING);
@@ -701,7 +722,7 @@ TEST_F(ResponseFieldCheckerTest, ArrayType) {
701722
}
702723

703724
{
704-
// Case 2: Nested repeated primitive
725+
// Case 2: Nested repeated primitive.
705726
Protobuf::Field field;
706727
field.set_name("awards");
707728
field.set_kind(Protobuf::Field_Kind_TYPE_STRING);
@@ -711,7 +732,7 @@ TEST_F(ResponseFieldCheckerTest, ArrayType) {
711732
}
712733

713734
{
714-
// Case 3: Repeated Message (e.g., repeated Book related_books)
735+
// Case 3: Repeated Message (e.g., repeated Book related_books).
715736
// No restriction on the list itself.
716737
// Should return kPartial to allow scrubbing inside individual books.
717738
Protobuf::Field field;
@@ -723,7 +744,7 @@ TEST_F(ResponseFieldCheckerTest, ArrayType) {
723744
}
724745

725746
{
726-
// Case 4: Repeated Primitive with NO matcher
747+
// Case 4: Repeated Primitive with NO matcher.
727748
// Should return kInclude (keep the whole list).
728749
Protobuf::Field field;
729750
field.set_name("tags");
@@ -740,7 +761,7 @@ TEST_F(ResponseFieldCheckerTest, EnumType) {
740761
NiceMock<StreamInfo::MockStreamInfo> mock_stream_info;
741762
const std::string method = "/pkg.Service/GetConfig";
742763

743-
// Field-Level Rule: Remove 'internal_flags' entirely
764+
// Field-Level Rule: Remove 'internal_flags' entirely.
744765
auto exclude_tree = std::make_shared<NiceMock<MockMatchTree>>();
745766
auto remove_action = std::make_shared<NiceMock<MockAction>>();
746767
ON_CALL(*remove_action, typeUrl())
@@ -751,16 +772,16 @@ TEST_F(ResponseFieldCheckerTest, EnumType) {
751772
ON_CALL(*mock_config, getResponseFieldMatcher(method, "config.internal_flags"))
752773
.WillByDefault(testing::Return(exclude_tree));
753774

754-
// Value-Level Rules: 'state' field
755-
// Rule: "config.state.DEPRECATED" (2) -> Remove
775+
// Value-Level Rules: 'state' field.
776+
// Rule: "config.state.DEPRECATED" (2) -> Remove.
756777
setupMockEnumRule(*mock_config, method, "config.state", "type.googleapis.com/pkg.State", 2,
757778
"DEPRECATED", true);
758779

759780
FieldChecker field_checker(ScrubberContext::kResponseScrubbing, &mock_stream_info, method,
760781
mock_config.get());
761782

762783
{
763-
// Scenario 1: Field-Level Scrubbing
784+
// Scenario 1: Field-Level Scrubbing.
764785
Protobuf::Field field;
765786
field.set_name("internal_flags");
766787
field.set_kind(Protobuf::Field::TYPE_ENUM);
@@ -770,7 +791,7 @@ TEST_F(ResponseFieldCheckerTest, EnumType) {
770791
}
771792

772793
{
773-
// Scenario 2: Value-Level Scrubbing (Specific Value matches Rule)
794+
// Scenario 2: Value-Level Scrubbing (Specific Value matches Rule).
774795
Protobuf::Field field;
775796
field.set_name("state");
776797
field.set_kind(Protobuf::Field::TYPE_ENUM);
@@ -781,8 +802,8 @@ TEST_F(ResponseFieldCheckerTest, EnumType) {
781802
}
782803

783804
{
784-
// Scenario 3: Value-Level Pass-through (No Rule for this value)
785-
// Value 1 ("ACTIVE") -> No rule -> Include
805+
// Scenario 3: Value-Level Pass-through (No Rule for this value).
806+
// Value 1 ("ACTIVE") -> No rule -> Include.
786807
Protobuf::Field field;
787808
field.set_name("state");
788809
field.set_kind(Protobuf::Field::TYPE_ENUM);

0 commit comments

Comments
 (0)