Skip to content

Commit c8f774f

Browse files
Internal change
PiperOrigin-RevId: 837446658
1 parent 40863fe commit c8f774f

File tree

3 files changed

+79
-27
lines changed

3 files changed

+79
-27
lines changed

src/google/protobuf/unittest.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ message TestAllTypes {
4949
// a local variable named "b" in one of the generated methods. Doh.
5050
// This file needs to compile in proto1 to test backwards-compatibility.
5151
int32 bb = 1;
52+
int32 cc = 2;
5253
}
5354

5455
enum NestedEnum {

src/google/protobuf/util/field_mask_util.cc

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@
1717
#include "absl/log/absl_log.h"
1818
#include "absl/log/die_if_null.h"
1919
#include "absl/memory/memory.h"
20+
#include "absl/strings/str_cat.h"
2021
#include "absl/strings/str_join.h"
2122
#include "absl/strings/str_split.h"
2223
#include "absl/strings/string_view.h"
2324
#include "absl/strings/strip.h"
25+
#include "google/protobuf/descriptor.h"
2426
#include "google/protobuf/message.h"
2527

2628
// Must be included last.
@@ -584,9 +586,17 @@ bool FieldMaskTree::TrimMessage(const Node* node, Message* message) {
584586
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
585587
Node* child = it->second.get();
586588
if (!child->children.empty() && reflection->HasField(*message, field)) {
587-
bool nestedMessageChanged =
588-
TrimMessage(child, reflection->MutableMessage(message, field));
589-
modified = nestedMessageChanged || modified;
589+
if (field->is_repeated()) {
590+
for (int i = 0; i < reflection->FieldSize(*message, field); ++i) {
591+
bool nestedMessageChanged = TrimMessage(
592+
child, reflection->MutableRepeatedMessage(message, field, i));
593+
modified = nestedMessageChanged || modified;
594+
}
595+
} else {
596+
bool nestedMessageChanged =
597+
TrimMessage(child, reflection->MutableMessage(message, field));
598+
modified = nestedMessageChanged || modified;
599+
}
590600
}
591601
}
592602
}

src/google/protobuf/util/field_mask_util_test.cc

Lines changed: 65 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,17 @@
99

1010
#include <algorithm>
1111
#include <cstdint>
12+
#include <string>
1213
#include <vector>
1314

1415
#include "google/protobuf/field_mask.pb.h"
16+
#include "net/proto2/contrib/parse_proto/parse_text_proto.h"
17+
#include <gmock/gmock.h>
1518
#include <gtest/gtest.h>
19+
#include "absl/base/log_severity.h"
1620
#include "google/protobuf/test_util.h"
1721
#include "google/protobuf/unittest.pb.h"
22+
#include "google/protobuf/util/field_mask_util.h"
1823

1924
namespace google {
2025
namespace protobuf {
@@ -90,11 +95,13 @@ TEST_F(SnakeCaseCamelCaseTest, RoundTripTest) {
9095
} while (std::next_permutation(name.begin(), name.end()));
9196
}
9297

98+
using contrib::parse_proto::ParseTextProtoOrDie;
9399
using google::protobuf::FieldMask;
94100
using proto2_unittest::NestedTestAllTypes;
95101
using proto2_unittest::TestAllTypes;
96102
using proto2_unittest::TestRequired;
97103
using proto2_unittest::TestRequiredMessage;
104+
using testing::EqualsProto;
98105

99106
TEST(FieldMaskUtilTest, StringFormat) {
100107
FieldMask mask;
@@ -198,8 +205,9 @@ TEST(FieldMaskUtilTest, TestIsValidFieldMask) {
198205
TEST(FieldMaskUtilTest, TestGetFieldMaskForAllFields) {
199206
FieldMask mask;
200207
mask = FieldMaskUtil::GetFieldMaskForAllFields<TestAllTypes::NestedMessage>();
201-
EXPECT_EQ(1, mask.paths_size());
208+
EXPECT_EQ(2, mask.paths_size());
202209
EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("bb", mask));
210+
EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("cc", mask));
203211

204212
mask = FieldMaskUtil::GetFieldMaskForAllFields<TestAllTypes>();
205213
EXPECT_EQ(80, mask.paths_size());
@@ -356,7 +364,8 @@ TEST(FieldMaskUtilTest, TestSubtract) {
356364

357365
FieldMaskUtil::Subtract<TestAllTypes>(mask1, mask2, &out);
358366
EXPECT_EQ(
359-
"optional_foreign_message.d,optional_uint64,repeated_foreign_message.c",
367+
"optional_foreign_message.d,optional_nested_message.cc,optional_uint64,"
368+
"repeated_foreign_message.c",
360369
FieldMaskUtil::ToString(out));
361370

362371
// mask1 is empty.
@@ -581,16 +590,16 @@ TEST(FieldMaskUtilTest, TrimMessage) {
581590
TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_import_enum)
582591
#undef TEST_TRIM_ONE_PRIMITIVE_FIELD
583592

584-
#define TEST_TRIM_ONE_FIELD(field_name) \
585-
{ \
586-
TestAllTypes msg; \
587-
TestUtil::SetAllFields(&msg); \
588-
TestAllTypes tmp; \
589-
*tmp.mutable_##field_name() = msg.field_name(); \
590-
FieldMask mask; \
591-
mask.add_paths(#field_name); \
592-
FieldMaskUtil::TrimMessage(mask, &msg); \
593-
EXPECT_EQ(tmp.DebugString(), msg.DebugString()); \
593+
#define TEST_TRIM_ONE_FIELD(field_name) \
594+
{ \
595+
TestAllTypes msg; \
596+
TestUtil::SetAllFields(&msg); \
597+
TestAllTypes tmp; \
598+
*tmp.mutable_##field_name() = msg.field_name(); \
599+
FieldMask mask; \
600+
mask.add_paths(#field_name); \
601+
EXPECT_TRUE(FieldMaskUtil::TrimMessage(mask, &msg)); \
602+
EXPECT_EQ(tmp.DebugString(), msg.DebugString()); \
594603
}
595604
TEST_TRIM_ONE_FIELD(optional_nested_message)
596605
TEST_TRIM_ONE_FIELD(optional_foreign_message)
@@ -629,25 +638,25 @@ TEST(FieldMaskUtilTest, TrimMessage) {
629638
NestedTestAllTypes trimmed_msg(nested_msg);
630639
FieldMask mask;
631640
FieldMaskUtil::FromString("child.payload", &mask);
632-
FieldMaskUtil::TrimMessage(mask, &trimmed_msg);
641+
EXPECT_TRUE(FieldMaskUtil::TrimMessage(mask, &trimmed_msg));
633642
EXPECT_EQ(1234, trimmed_msg.child().payload().optional_int32());
634643
EXPECT_EQ(0, trimmed_msg.child().child().payload().optional_int32());
635644

636645
trimmed_msg = nested_msg;
637646
FieldMaskUtil::FromString("child.child.payload", &mask);
638-
FieldMaskUtil::TrimMessage(mask, &trimmed_msg);
647+
EXPECT_TRUE(FieldMaskUtil::TrimMessage(mask, &trimmed_msg));
639648
EXPECT_EQ(0, trimmed_msg.child().payload().optional_int32());
640649
EXPECT_EQ(5678, trimmed_msg.child().child().payload().optional_int32());
641650

642651
trimmed_msg = nested_msg;
643652
FieldMaskUtil::FromString("child", &mask);
644-
FieldMaskUtil::TrimMessage(mask, &trimmed_msg);
653+
EXPECT_FALSE(FieldMaskUtil::TrimMessage(mask, &trimmed_msg));
645654
EXPECT_EQ(1234, trimmed_msg.child().payload().optional_int32());
646655
EXPECT_EQ(5678, trimmed_msg.child().child().payload().optional_int32());
647656

648657
trimmed_msg = nested_msg;
649658
FieldMaskUtil::FromString("child.child", &mask);
650-
FieldMaskUtil::TrimMessage(mask, &trimmed_msg);
659+
EXPECT_TRUE(FieldMaskUtil::TrimMessage(mask, &trimmed_msg));
651660
EXPECT_EQ(0, trimmed_msg.child().payload().optional_int32());
652661
EXPECT_EQ(5678, trimmed_msg.child().child().payload().optional_int32());
653662

@@ -656,7 +665,7 @@ TEST(FieldMaskUtilTest, TrimMessage) {
656665
TestUtil::SetAllFields(&all_types_msg);
657666
TestAllTypes trimmed_all_types(all_types_msg);
658667
FieldMask empty_mask;
659-
FieldMaskUtil::TrimMessage(empty_mask, &trimmed_all_types);
668+
EXPECT_FALSE(FieldMaskUtil::TrimMessage(empty_mask, &trimmed_all_types));
660669
EXPECT_EQ(trimmed_all_types.DebugString(), all_types_msg.DebugString());
661670

662671
// Test trim required fields with keep_required_fields is set true.
@@ -668,15 +677,17 @@ TEST(FieldMaskUtilTest, TrimMessage) {
668677
TestRequired trimmed_required_msg_1(required_msg_1);
669678
FieldMaskUtil::FromString("dummy2", &mask);
670679
options.set_keep_required_fields(true);
671-
FieldMaskUtil::TrimMessage(mask, &trimmed_required_msg_1, options);
680+
EXPECT_FALSE(
681+
FieldMaskUtil::TrimMessage(mask, &trimmed_required_msg_1, options));
672682
EXPECT_EQ(trimmed_required_msg_1.DebugString(), required_msg_1.DebugString());
673683

674684
// Test trim required fields with keep_required_fields is set false.
675685
required_msg_1.clear_a();
676686
required_msg_1.clear_b();
677687
required_msg_1.clear_c();
678688
options.set_keep_required_fields(false);
679-
FieldMaskUtil::TrimMessage(mask, &trimmed_required_msg_1, options);
689+
EXPECT_TRUE(
690+
FieldMaskUtil::TrimMessage(mask, &trimmed_required_msg_1, options));
680691
EXPECT_EQ(trimmed_required_msg_1.DebugString(), required_msg_1.DebugString());
681692

682693
// Test trim required message with keep_required_fields is set true.
@@ -697,14 +708,16 @@ TEST(FieldMaskUtilTest, TrimMessage) {
697708
options.set_keep_required_fields(true);
698709
required_msg_2.clear_repeated_message();
699710
required_msg_2.mutable_required_message()->clear_dummy2();
700-
FieldMaskUtil::TrimMessage(mask, &trimmed_required_msg_2, options);
711+
EXPECT_TRUE(
712+
FieldMaskUtil::TrimMessage(mask, &trimmed_required_msg_2, options));
701713
EXPECT_EQ(trimmed_required_msg_2.DebugString(), required_msg_2.DebugString());
702714

703715
FieldMaskUtil::FromString("required_message", &mask);
704716
required_msg_2.mutable_required_message()->set_dummy2(7890);
705717
trimmed_required_msg_2.mutable_required_message()->set_dummy2(7890);
706718
required_msg_2.clear_optional_message();
707-
FieldMaskUtil::TrimMessage(mask, &trimmed_required_msg_2, options);
719+
EXPECT_TRUE(
720+
FieldMaskUtil::TrimMessage(mask, &trimmed_required_msg_2, options));
708721
EXPECT_EQ(trimmed_required_msg_2.DebugString(), required_msg_2.DebugString());
709722

710723
// Test trim required message with keep_required_fields is set false.
@@ -713,15 +726,16 @@ TEST(FieldMaskUtilTest, TrimMessage) {
713726
required_msg_2.mutable_required_message()->clear_b();
714727
required_msg_2.mutable_required_message()->clear_c();
715728
options.set_keep_required_fields(false);
716-
FieldMaskUtil::TrimMessage(mask, &trimmed_required_msg_2, options);
729+
EXPECT_TRUE(
730+
FieldMaskUtil::TrimMessage(mask, &trimmed_required_msg_2, options));
717731
EXPECT_EQ(trimmed_required_msg_2.DebugString(), required_msg_2.DebugString());
718732

719733
// Verify that trimming an empty message has no effect. In particular, fields
720734
// mentioned in the field mask should not be created or changed.
721735
TestAllTypes empty_msg;
722736
FieldMaskUtil::FromString(
723737
"optional_int32,optional_bytes,optional_nested_message.bb", &mask);
724-
FieldMaskUtil::TrimMessage(mask, &empty_msg);
738+
EXPECT_FALSE(FieldMaskUtil::TrimMessage(mask, &empty_msg));
725739
EXPECT_FALSE(empty_msg.has_optional_int32());
726740
EXPECT_FALSE(empty_msg.has_optional_bytes());
727741
EXPECT_FALSE(empty_msg.has_optional_nested_message());
@@ -731,10 +745,37 @@ TEST(FieldMaskUtilTest, TrimMessage) {
731745
TestAllTypes oneof_msg;
732746
oneof_msg.set_oneof_uint32(11);
733747
FieldMaskUtil::FromString("oneof_uint32,oneof_nested_message.bb", &mask);
734-
FieldMaskUtil::TrimMessage(mask, &oneof_msg);
748+
EXPECT_FALSE(FieldMaskUtil::TrimMessage(mask, &oneof_msg));
735749
EXPECT_EQ(11, oneof_msg.oneof_uint32());
736750
}
737751

752+
TEST(FieldMaskUtilTest, TrimMessageRepeatedField) {
753+
FieldMask bb_mask;
754+
FieldMaskUtil::FromString("repeated_nested_message.bb", &bb_mask);
755+
{
756+
TestAllTypes repeated_nested_msg;
757+
TestUtil::SetAllFields(&repeated_nested_msg);
758+
repeated_nested_msg.add_repeated_nested_message()->set_bb(1234);
759+
TestAllTypes trimmed_repeated_nested_msg;
760+
*trimmed_repeated_nested_msg.mutable_repeated_nested_message() =
761+
repeated_nested_msg.repeated_nested_message();
762+
EXPECT_TRUE(FieldMaskUtil::TrimMessage(bb_mask, &repeated_nested_msg));
763+
EXPECT_THAT(repeated_nested_msg, EqualsProto(trimmed_repeated_nested_msg));
764+
}
765+
{
766+
// Repeated field has multiple elements
767+
TestAllTypes msg = ParseTextProtoOrDie(R"pb(
768+
repeated_nested_message { bb: 1234 }
769+
repeated_nested_message { bb: 5678 cc: 9012 }
770+
)pb");
771+
EXPECT_TRUE(FieldMaskUtil::TrimMessage(bb_mask, &msg));
772+
EXPECT_THAT(msg, EqualsProto(R"pb(
773+
repeated_nested_message { bb: 1234 }
774+
repeated_nested_message { bb: 5678 }
775+
)pb"));
776+
}
777+
}
778+
738779
TEST(FieldMaskUtilTest, TrimMessageReturnValue) {
739780
FieldMask mask;
740781
TestAllTypes trimmed_msg;

0 commit comments

Comments
 (0)