@@ -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.
487508TEST_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