1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 #include <google/protobuf/util/field_mask_util.h>
32
33 #include <algorithm>
34
35 #include <google/protobuf/stubs/logging.h>
36 #include <google/protobuf/stubs/common.h>
37 #include <google/protobuf/field_mask.pb.h>
38 #include <google/protobuf/test_util.h>
39 #include <google/protobuf/unittest.pb.h>
40 #include <gtest/gtest.h>
41
42 namespace google {
43 namespace protobuf {
44 namespace util {
45
46 class SnakeCaseCamelCaseTest : public ::testing::Test {
47 protected:
SnakeCaseToCamelCase(const std::string & input)48 string SnakeCaseToCamelCase(const std::string& input) {
49 std::string output;
50 if (FieldMaskUtil::SnakeCaseToCamelCase(input, &output)) {
51 return output;
52 } else {
53 return "#FAIL#";
54 }
55 }
56
CamelCaseToSnakeCase(const std::string & input)57 string CamelCaseToSnakeCase(const std::string& input) {
58 std::string output;
59 if (FieldMaskUtil::CamelCaseToSnakeCase(input, &output)) {
60 return output;
61 } else {
62 return "#FAIL#";
63 }
64 }
65 };
66
67 namespace {
68
TEST_F(SnakeCaseCamelCaseTest,SnakeToCamel)69 TEST_F(SnakeCaseCamelCaseTest, SnakeToCamel) {
70 EXPECT_EQ("fooBar", SnakeCaseToCamelCase("foo_bar"));
71 EXPECT_EQ("FooBar", SnakeCaseToCamelCase("_foo_bar"));
72 EXPECT_EQ("foo3Bar", SnakeCaseToCamelCase("foo3_bar"));
73 // No uppercase letter is allowed.
74 EXPECT_EQ("#FAIL#", SnakeCaseToCamelCase("Foo"));
75 // Any character after a "_" must be a lowercase letter.
76 // 1. "_" cannot be followed by another "_".
77 // 2. "_" cannot be followed by a digit.
78 // 3. "_" cannot appear as the last character.
79 EXPECT_EQ("#FAIL#", SnakeCaseToCamelCase("foo__bar"));
80 EXPECT_EQ("#FAIL#", SnakeCaseToCamelCase("foo_3bar"));
81 EXPECT_EQ("#FAIL#", SnakeCaseToCamelCase("foo_bar_"));
82 }
83
TEST_F(SnakeCaseCamelCaseTest,CamelToSnake)84 TEST_F(SnakeCaseCamelCaseTest, CamelToSnake) {
85 EXPECT_EQ("foo_bar", CamelCaseToSnakeCase("fooBar"));
86 EXPECT_EQ("_foo_bar", CamelCaseToSnakeCase("FooBar"));
87 EXPECT_EQ("foo3_bar", CamelCaseToSnakeCase("foo3Bar"));
88 // "_"s are not allowed.
89 EXPECT_EQ("#FAIL#", CamelCaseToSnakeCase("foo_bar"));
90 }
91
TEST_F(SnakeCaseCamelCaseTest,RoundTripTest)92 TEST_F(SnakeCaseCamelCaseTest, RoundTripTest) {
93 // Enumerates all possible snake_case names and test that converting it to
94 // camelCase and then to snake_case again will yield the original name.
95 std::string name = "___abc123";
96 std::sort(name.begin(), name.end());
97 do {
98 std::string camelName = SnakeCaseToCamelCase(name);
99 if (camelName != "#FAIL#") {
100 EXPECT_EQ(name, CamelCaseToSnakeCase(camelName));
101 }
102 } while (std::next_permutation(name.begin(), name.end()));
103
104 // Enumerates all possible camelCase names and test that converting it to
105 // snake_case and then to camelCase again will yield the original name.
106 name = "abcABC123";
107 std::sort(name.begin(), name.end());
108 do {
109 std::string camelName = CamelCaseToSnakeCase(name);
110 if (camelName != "#FAIL#") {
111 EXPECT_EQ(name, SnakeCaseToCamelCase(camelName));
112 }
113 } while (std::next_permutation(name.begin(), name.end()));
114 }
115
116 using google::protobuf::FieldMask;
117 using protobuf_unittest::NestedTestAllTypes;
118 using protobuf_unittest::TestAllTypes;
119 using protobuf_unittest::TestRequired;
120 using protobuf_unittest::TestRequiredMessage;
121
TEST(FieldMaskUtilTest,StringFormat)122 TEST(FieldMaskUtilTest, StringFormat) {
123 FieldMask mask;
124 EXPECT_EQ("", FieldMaskUtil::ToString(mask));
125 mask.add_paths("foo_bar");
126 EXPECT_EQ("foo_bar", FieldMaskUtil::ToString(mask));
127 mask.add_paths("baz_quz");
128 EXPECT_EQ("foo_bar,baz_quz", FieldMaskUtil::ToString(mask));
129
130 FieldMaskUtil::FromString("", &mask);
131 EXPECT_EQ(0, mask.paths_size());
132 FieldMaskUtil::FromString("fooBar", &mask);
133 EXPECT_EQ(1, mask.paths_size());
134 EXPECT_EQ("fooBar", mask.paths(0));
135 FieldMaskUtil::FromString("fooBar,bazQuz", &mask);
136 EXPECT_EQ(2, mask.paths_size());
137 EXPECT_EQ("fooBar", mask.paths(0));
138 EXPECT_EQ("bazQuz", mask.paths(1));
139 }
140
TEST(FieldMaskUtilTest,JsonStringFormat)141 TEST(FieldMaskUtilTest, JsonStringFormat) {
142 FieldMask mask;
143 std::string value;
144 EXPECT_TRUE(FieldMaskUtil::ToJsonString(mask, &value));
145 EXPECT_EQ("", value);
146 mask.add_paths("foo_bar");
147 EXPECT_TRUE(FieldMaskUtil::ToJsonString(mask, &value));
148 EXPECT_EQ("fooBar", value);
149 mask.add_paths("bar_quz");
150 EXPECT_TRUE(FieldMaskUtil::ToJsonString(mask, &value));
151 EXPECT_EQ("fooBar,barQuz", value);
152
153 FieldMaskUtil::FromJsonString("", &mask);
154 EXPECT_EQ(0, mask.paths_size());
155 FieldMaskUtil::FromJsonString("fooBar", &mask);
156 EXPECT_EQ(1, mask.paths_size());
157 EXPECT_EQ("foo_bar", mask.paths(0));
158 FieldMaskUtil::FromJsonString("fooBar,bazQuz", &mask);
159 EXPECT_EQ(2, mask.paths_size());
160 EXPECT_EQ("foo_bar", mask.paths(0));
161 EXPECT_EQ("baz_quz", mask.paths(1));
162 }
163
TEST(FieldMaskUtilTest,GetFieldDescriptors)164 TEST(FieldMaskUtilTest, GetFieldDescriptors) {
165 std::vector<const FieldDescriptor*> field_descriptors;
166 EXPECT_TRUE(FieldMaskUtil::GetFieldDescriptors(
167 TestAllTypes::descriptor(), "optional_int32", &field_descriptors));
168 EXPECT_EQ(1, field_descriptors.size());
169 EXPECT_EQ("optional_int32", field_descriptors[0]->name());
170 EXPECT_FALSE(FieldMaskUtil::GetFieldDescriptors(
171 TestAllTypes::descriptor(), "optional_nonexist", nullptr));
172 EXPECT_TRUE(FieldMaskUtil::GetFieldDescriptors(TestAllTypes::descriptor(),
173 "optional_nested_message.bb",
174 &field_descriptors));
175 EXPECT_EQ(2, field_descriptors.size());
176 EXPECT_EQ("optional_nested_message", field_descriptors[0]->name());
177 EXPECT_EQ("bb", field_descriptors[1]->name());
178 EXPECT_FALSE(FieldMaskUtil::GetFieldDescriptors(
179 TestAllTypes::descriptor(), "optional_nested_message.nonexist", nullptr));
180 // FieldMask cannot be used to specify sub-fields of a repeated message.
181 EXPECT_FALSE(FieldMaskUtil::GetFieldDescriptors(
182 TestAllTypes::descriptor(), "repeated_nested_message.bb", nullptr));
183 }
184
TEST(FieldMaskUtilTest,TestIsVaildPath)185 TEST(FieldMaskUtilTest, TestIsVaildPath) {
186 EXPECT_TRUE(FieldMaskUtil::IsValidPath<TestAllTypes>("optional_int32"));
187 EXPECT_FALSE(FieldMaskUtil::IsValidPath<TestAllTypes>("optional_nonexist"));
188 EXPECT_TRUE(
189 FieldMaskUtil::IsValidPath<TestAllTypes>("optional_nested_message.bb"));
190 EXPECT_FALSE(FieldMaskUtil::IsValidPath<TestAllTypes>(
191 "optional_nested_message.nonexist"));
192 // FieldMask cannot be used to specify sub-fields of a repeated message.
193 EXPECT_FALSE(
194 FieldMaskUtil::IsValidPath<TestAllTypes>("repeated_nested_message.bb"));
195 }
196
TEST(FieldMaskUtilTest,TestIsValidFieldMask)197 TEST(FieldMaskUtilTest, TestIsValidFieldMask) {
198 FieldMask mask;
199 FieldMaskUtil::FromString("optional_int32,optional_nested_message.bb", &mask);
200 EXPECT_TRUE(FieldMaskUtil::IsValidFieldMask<TestAllTypes>(mask));
201
202 FieldMaskUtil::FromString(
203 "optional_int32,optional_nested_message.bb,optional_nonexist", &mask);
204 EXPECT_FALSE(FieldMaskUtil::IsValidFieldMask<TestAllTypes>(mask));
205 }
206
TEST(FieldMaskUtilTest,TestGetFieldMaskForAllFields)207 TEST(FieldMaskUtilTest, TestGetFieldMaskForAllFields) {
208 FieldMask mask;
209 mask = FieldMaskUtil::GetFieldMaskForAllFields<TestAllTypes::NestedMessage>();
210 EXPECT_EQ(1, mask.paths_size());
211 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("bb", mask));
212
213 mask = FieldMaskUtil::GetFieldMaskForAllFields<TestAllTypes>();
214 EXPECT_EQ(75, mask.paths_size());
215 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_int32", mask));
216 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_int64", mask));
217 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_uint32", mask));
218 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_uint64", mask));
219 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_sint32", mask));
220 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_sint64", mask));
221 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_fixed32", mask));
222 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_fixed64", mask));
223 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_sfixed32", mask));
224 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_sfixed64", mask));
225 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_float", mask));
226 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_double", mask));
227 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_bool", mask));
228 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_string", mask));
229 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_bytes", mask));
230 EXPECT_TRUE(
231 FieldMaskUtil::IsPathInFieldMask("optional_nested_message", mask));
232 EXPECT_TRUE(
233 FieldMaskUtil::IsPathInFieldMask("optional_foreign_message", mask));
234 EXPECT_TRUE(
235 FieldMaskUtil::IsPathInFieldMask("optional_import_message", mask));
236 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_nested_enum", mask));
237 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_foreign_enum", mask));
238 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_import_enum", mask));
239 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_int32", mask));
240 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_int64", mask));
241 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_uint32", mask));
242 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_uint64", mask));
243 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_sint32", mask));
244 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_sint64", mask));
245 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_fixed32", mask));
246 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_fixed64", mask));
247 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_sfixed32", mask));
248 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_sfixed64", mask));
249 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_float", mask));
250 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_double", mask));
251 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_bool", mask));
252 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_string", mask));
253 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_bytes", mask));
254 EXPECT_TRUE(
255 FieldMaskUtil::IsPathInFieldMask("repeated_nested_message", mask));
256 EXPECT_TRUE(
257 FieldMaskUtil::IsPathInFieldMask("repeated_foreign_message", mask));
258 EXPECT_TRUE(
259 FieldMaskUtil::IsPathInFieldMask("repeated_import_message", mask));
260 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_nested_enum", mask));
261 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_foreign_enum", mask));
262 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_import_enum", mask));
263 }
264
TEST(FieldMaskUtilTest,TestToCanonicalForm)265 TEST(FieldMaskUtilTest, TestToCanonicalForm) {
266 FieldMask in, out;
267 // Paths will be sorted.
268 FieldMaskUtil::FromString("baz.quz,bar,foo", &in);
269 FieldMaskUtil::ToCanonicalForm(in, &out);
270 EXPECT_EQ("bar,baz.quz,foo", FieldMaskUtil::ToString(out));
271 // Duplicated paths will be removed.
272 FieldMaskUtil::FromString("foo,bar,foo", &in);
273 FieldMaskUtil::ToCanonicalForm(in, &out);
274 EXPECT_EQ("bar,foo", FieldMaskUtil::ToString(out));
275 // Sub-paths of other paths will be removed.
276 FieldMaskUtil::FromString("foo.b1,bar.b1,foo.b2,bar", &in);
277 FieldMaskUtil::ToCanonicalForm(in, &out);
278 EXPECT_EQ("bar,foo.b1,foo.b2", FieldMaskUtil::ToString(out));
279
280 // Test more deeply nested cases.
281 FieldMaskUtil::FromString(
282 "foo.bar.baz1,"
283 "foo.bar.baz2.quz,"
284 "foo.bar.baz2",
285 &in);
286 FieldMaskUtil::ToCanonicalForm(in, &out);
287 EXPECT_EQ("foo.bar.baz1,foo.bar.baz2", FieldMaskUtil::ToString(out));
288 FieldMaskUtil::FromString(
289 "foo.bar.baz1,"
290 "foo.bar.baz2,"
291 "foo.bar.baz2.quz",
292 &in);
293 FieldMaskUtil::ToCanonicalForm(in, &out);
294 EXPECT_EQ("foo.bar.baz1,foo.bar.baz2", FieldMaskUtil::ToString(out));
295 FieldMaskUtil::FromString(
296 "foo.bar.baz1,"
297 "foo.bar.baz2,"
298 "foo.bar.baz2.quz,"
299 "foo.bar",
300 &in);
301 FieldMaskUtil::ToCanonicalForm(in, &out);
302 EXPECT_EQ("foo.bar", FieldMaskUtil::ToString(out));
303 FieldMaskUtil::FromString(
304 "foo.bar.baz1,"
305 "foo.bar.baz2,"
306 "foo.bar.baz2.quz,"
307 "foo",
308 &in);
309 FieldMaskUtil::ToCanonicalForm(in, &out);
310 EXPECT_EQ("foo", FieldMaskUtil::ToString(out));
311 }
312
TEST(FieldMaskUtilTest,TestUnion)313 TEST(FieldMaskUtilTest, TestUnion) {
314 FieldMask mask1, mask2, out;
315 // Test cases without overlapping.
316 FieldMaskUtil::FromString("foo,baz", &mask1);
317 FieldMaskUtil::FromString("bar,quz", &mask2);
318 FieldMaskUtil::Union(mask1, mask2, &out);
319 EXPECT_EQ("bar,baz,foo,quz", FieldMaskUtil::ToString(out));
320 // Overlap with duplicated paths.
321 FieldMaskUtil::FromString("foo,baz.bb", &mask1);
322 FieldMaskUtil::FromString("baz.bb,quz", &mask2);
323 FieldMaskUtil::Union(mask1, mask2, &out);
324 EXPECT_EQ("baz.bb,foo,quz", FieldMaskUtil::ToString(out));
325 // Overlap with paths covering some other paths.
326 FieldMaskUtil::FromString("foo.bar.baz,quz", &mask1);
327 FieldMaskUtil::FromString("foo.bar,bar", &mask2);
328 FieldMaskUtil::Union(mask1, mask2, &out);
329 EXPECT_EQ("bar,foo.bar,quz", FieldMaskUtil::ToString(out));
330 }
331
TEST(FieldMaskUtilTest,TestIntersect)332 TEST(FieldMaskUtilTest, TestIntersect) {
333 FieldMask mask1, mask2, out;
334 // Test cases without overlapping.
335 FieldMaskUtil::FromString("foo,baz", &mask1);
336 FieldMaskUtil::FromString("bar,quz", &mask2);
337 FieldMaskUtil::Intersect(mask1, mask2, &out);
338 EXPECT_EQ("", FieldMaskUtil::ToString(out));
339 // Overlap with duplicated paths.
340 FieldMaskUtil::FromString("foo,baz.bb", &mask1);
341 FieldMaskUtil::FromString("baz.bb,quz", &mask2);
342 FieldMaskUtil::Intersect(mask1, mask2, &out);
343 EXPECT_EQ("baz.bb", FieldMaskUtil::ToString(out));
344 // Overlap with paths covering some other paths.
345 FieldMaskUtil::FromString("foo.bar.baz,quz", &mask1);
346 FieldMaskUtil::FromString("foo.bar,bar", &mask2);
347 FieldMaskUtil::Intersect(mask1, mask2, &out);
348 EXPECT_EQ("foo.bar.baz", FieldMaskUtil::ToString(out));
349 }
350
TEST(FieldMaskUtilTest,TestSubtract)351 TEST(FieldMaskUtilTest, TestSubtract) {
352 FieldMask mask1, mask2, out;
353 // Normal case.
354 FieldMaskUtil::FromString(
355 "optional_int32,optional_uint64,optional_nested_message,optional_foreign_"
356 "message,repeated_int32,repeated_foreign_message,repeated_nested_message."
357 "bb",
358 &mask1);
359
360 FieldMaskUtil::FromString(
361 "optional_int32,optional_nested_message.bb,optional_foreign_message.c,"
362 "repeated_int32,repeated_nested_message.bb,repeated_foreign_message.f,"
363 "repeated_foreign_message.d,repeated_nested_message.bb,repeated_uint32",
364 &mask2);
365
366 FieldMaskUtil::Subtract<TestAllTypes>(mask1, mask2, &out);
367 EXPECT_EQ(
368 "optional_foreign_message.d,optional_uint64,repeated_foreign_message.c",
369 FieldMaskUtil::ToString(out));
370
371 // mask1 is empty.
372 FieldMaskUtil::FromString("", &mask1);
373 FieldMaskUtil::Subtract<TestAllTypes>(mask1, mask2, &out);
374 EXPECT_EQ("", FieldMaskUtil::ToString(out));
375
376 // mask1 is "optional_nested_message" and mask2 is
377 // "optional_nested_message.nonexist_field".
378 FieldMaskUtil::FromString("optional_nested_message", &mask1);
379 FieldMaskUtil::FromString("optional_nested_message.nonexist_field", &mask2);
380 FieldMaskUtil::Subtract<TestAllTypes>(mask1, mask2, &out);
381 EXPECT_EQ("optional_nested_message", FieldMaskUtil::ToString(out));
382
383 // mask1 is "optional_nested_message" and mask2 is
384 // "optional_nested_message".
385 FieldMaskUtil::FromString("optional_nested_message", &mask1);
386 FieldMaskUtil::FromString("optional_nested_message", &mask2);
387 FieldMaskUtil::Subtract<TestAllTypes>(mask1, mask2, &out);
388 EXPECT_EQ("", FieldMaskUtil::ToString(out));
389
390 // Regression test for b/72727550
391 FieldMaskUtil::FromString("optional_foreign_message.c", &mask1);
392 FieldMaskUtil::FromString("optional_foreign_message,optional_nested_message",
393 &mask2);
394 FieldMaskUtil::Subtract<TestAllTypes>(mask1, mask2, &out);
395 EXPECT_EQ("", FieldMaskUtil::ToString(out));
396 }
397
TEST(FieldMaskUtilTest,TestIspathInFieldMask)398 TEST(FieldMaskUtilTest, TestIspathInFieldMask) {
399 FieldMask mask;
400 FieldMaskUtil::FromString("foo.bar", &mask);
401 EXPECT_FALSE(FieldMaskUtil::IsPathInFieldMask("", mask));
402 EXPECT_FALSE(FieldMaskUtil::IsPathInFieldMask("foo", mask));
403 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("foo.bar", mask));
404 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("foo.bar.baz", mask));
405 EXPECT_FALSE(FieldMaskUtil::IsPathInFieldMask("foo.bar0.baz", mask));
406 }
407
TEST(FieldMaskUtilTest,MergeMessage)408 TEST(FieldMaskUtilTest, MergeMessage) {
409 TestAllTypes src, dst;
410 TestUtil::SetAllFields(&src);
411 FieldMaskUtil::MergeOptions options;
412
413 #define TEST_MERGE_ONE_PRIMITIVE_FIELD(field_name) \
414 { \
415 TestAllTypes tmp; \
416 tmp.set_##field_name(src.field_name()); \
417 FieldMask mask; \
418 mask.add_paths(#field_name); \
419 dst.Clear(); \
420 FieldMaskUtil::MergeMessageTo(src, mask, options, &dst); \
421 EXPECT_EQ(tmp.DebugString(), dst.DebugString()); \
422 src.clear_##field_name(); \
423 tmp.clear_##field_name(); \
424 FieldMaskUtil::MergeMessageTo(src, mask, options, &dst); \
425 EXPECT_EQ(tmp.DebugString(), dst.DebugString()); \
426 }
427 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_int32)
428 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_int64)
429 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_uint32)
430 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_uint64)
431 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_sint32)
432 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_sint64)
433 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_fixed32)
434 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_fixed64)
435 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_sfixed32)
436 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_sfixed64)
437 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_float)
438 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_double)
439 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_bool)
440 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_string)
441 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_bytes)
442 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_nested_enum)
443 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_foreign_enum)
444 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_import_enum)
445 #undef TEST_MERGE_ONE_PRIMITIVE_FIELD
446
447 #define TEST_MERGE_ONE_FIELD(field_name) \
448 { \
449 TestAllTypes tmp; \
450 *tmp.mutable_##field_name() = src.field_name(); \
451 FieldMask mask; \
452 mask.add_paths(#field_name); \
453 dst.Clear(); \
454 FieldMaskUtil::MergeMessageTo(src, mask, options, &dst); \
455 EXPECT_EQ(tmp.DebugString(), dst.DebugString()); \
456 }
457 TEST_MERGE_ONE_FIELD(optional_nested_message)
458 TEST_MERGE_ONE_FIELD(optional_foreign_message)
459 TEST_MERGE_ONE_FIELD(optional_import_message)
460
461 TEST_MERGE_ONE_FIELD(repeated_int32)
462 TEST_MERGE_ONE_FIELD(repeated_int64)
463 TEST_MERGE_ONE_FIELD(repeated_uint32)
464 TEST_MERGE_ONE_FIELD(repeated_uint64)
465 TEST_MERGE_ONE_FIELD(repeated_sint32)
466 TEST_MERGE_ONE_FIELD(repeated_sint64)
467 TEST_MERGE_ONE_FIELD(repeated_fixed32)
468 TEST_MERGE_ONE_FIELD(repeated_fixed64)
469 TEST_MERGE_ONE_FIELD(repeated_sfixed32)
470 TEST_MERGE_ONE_FIELD(repeated_sfixed64)
471 TEST_MERGE_ONE_FIELD(repeated_float)
472 TEST_MERGE_ONE_FIELD(repeated_double)
473 TEST_MERGE_ONE_FIELD(repeated_bool)
474 TEST_MERGE_ONE_FIELD(repeated_string)
475 TEST_MERGE_ONE_FIELD(repeated_bytes)
476 TEST_MERGE_ONE_FIELD(repeated_nested_message)
477 TEST_MERGE_ONE_FIELD(repeated_foreign_message)
478 TEST_MERGE_ONE_FIELD(repeated_import_message)
479 TEST_MERGE_ONE_FIELD(repeated_nested_enum)
480 TEST_MERGE_ONE_FIELD(repeated_foreign_enum)
481 TEST_MERGE_ONE_FIELD(repeated_import_enum)
482 #undef TEST_MERGE_ONE_FIELD
483
484 // Test merge nested fields.
485 NestedTestAllTypes nested_src, nested_dst;
486 nested_src.mutable_child()->mutable_payload()->set_optional_int32(1234);
487 nested_src.mutable_child()
488 ->mutable_child()
489 ->mutable_payload()
490 ->set_optional_int32(5678);
491 FieldMask mask;
492 FieldMaskUtil::FromString("child.payload", &mask);
493 FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
494 EXPECT_EQ(1234, nested_dst.child().payload().optional_int32());
495 EXPECT_EQ(0, nested_dst.child().child().payload().optional_int32());
496
497 FieldMaskUtil::FromString("child.child.payload", &mask);
498 FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
499 EXPECT_EQ(1234, nested_dst.child().payload().optional_int32());
500 EXPECT_EQ(5678, nested_dst.child().child().payload().optional_int32());
501
502 nested_dst.Clear();
503 FieldMaskUtil::FromString("child.child.payload", &mask);
504 FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
505 EXPECT_EQ(0, nested_dst.child().payload().optional_int32());
506 EXPECT_EQ(5678, nested_dst.child().child().payload().optional_int32());
507
508 nested_dst.Clear();
509 FieldMaskUtil::FromString("child", &mask);
510 FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
511 EXPECT_EQ(1234, nested_dst.child().payload().optional_int32());
512 EXPECT_EQ(5678, nested_dst.child().child().payload().optional_int32());
513
514 // Test MergeOptions.
515
516 nested_dst.Clear();
517 nested_dst.mutable_child()->mutable_payload()->set_optional_int64(4321);
518 // Message fields will be merged by default.
519 FieldMaskUtil::FromString("child.payload", &mask);
520 FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
521 EXPECT_EQ(1234, nested_dst.child().payload().optional_int32());
522 EXPECT_EQ(4321, nested_dst.child().payload().optional_int64());
523 // Change the behavior to replace message fields.
524 options.set_replace_message_fields(true);
525 FieldMaskUtil::FromString("child.payload", &mask);
526 FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
527 EXPECT_EQ(1234, nested_dst.child().payload().optional_int32());
528 EXPECT_EQ(0, nested_dst.child().payload().optional_int64());
529
530 // By default, fields missing in source are not cleared in destination.
531 options.set_replace_message_fields(false);
532 nested_dst.mutable_payload();
533 EXPECT_TRUE(nested_dst.has_payload());
534 FieldMaskUtil::FromString("payload", &mask);
535 FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
536 EXPECT_TRUE(nested_dst.has_payload());
537 // But they are cleared when replacing message fields.
538 options.set_replace_message_fields(true);
539 nested_dst.Clear();
540 nested_dst.mutable_payload();
541 FieldMaskUtil::FromString("payload", &mask);
542 FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
543 EXPECT_FALSE(nested_dst.has_payload());
544
545 nested_src.mutable_payload()->add_repeated_int32(1234);
546 nested_dst.mutable_payload()->add_repeated_int32(5678);
547 // Repeated fields will be appended by default.
548 FieldMaskUtil::FromString("payload.repeated_int32", &mask);
549 FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
550 ASSERT_EQ(2, nested_dst.payload().repeated_int32_size());
551 EXPECT_EQ(5678, nested_dst.payload().repeated_int32(0));
552 EXPECT_EQ(1234, nested_dst.payload().repeated_int32(1));
553 // Change the behavior to replace repeated fields.
554 options.set_replace_repeated_fields(true);
555 FieldMaskUtil::FromString("payload.repeated_int32", &mask);
556 FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
557 ASSERT_EQ(1, nested_dst.payload().repeated_int32_size());
558 EXPECT_EQ(1234, nested_dst.payload().repeated_int32(0));
559 }
560
TEST(FieldMaskUtilTest,TrimMessage)561 TEST(FieldMaskUtilTest, TrimMessage) {
562 #define TEST_TRIM_ONE_PRIMITIVE_FIELD(field_name) \
563 { \
564 TestAllTypes msg; \
565 TestUtil::SetAllFields(&msg); \
566 TestAllTypes tmp; \
567 tmp.set_##field_name(msg.field_name()); \
568 FieldMask mask; \
569 mask.add_paths(#field_name); \
570 FieldMaskUtil::TrimMessage(mask, &msg); \
571 EXPECT_EQ(tmp.DebugString(), msg.DebugString()); \
572 }
573 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_int32)
574 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_int64)
575 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_uint32)
576 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_uint64)
577 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_sint32)
578 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_sint64)
579 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_fixed32)
580 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_fixed64)
581 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_sfixed32)
582 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_sfixed64)
583 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_float)
584 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_double)
585 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_bool)
586 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_string)
587 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_bytes)
588 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_nested_enum)
589 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_foreign_enum)
590 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_import_enum)
591 #undef TEST_TRIM_ONE_PRIMITIVE_FIELD
592
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 FieldMaskUtil::TrimMessage(mask, &msg); \
602 EXPECT_EQ(tmp.DebugString(), msg.DebugString()); \
603 }
604 TEST_TRIM_ONE_FIELD(optional_nested_message)
605 TEST_TRIM_ONE_FIELD(optional_foreign_message)
606 TEST_TRIM_ONE_FIELD(optional_import_message)
607
608 TEST_TRIM_ONE_FIELD(repeated_int32)
609 TEST_TRIM_ONE_FIELD(repeated_int64)
610 TEST_TRIM_ONE_FIELD(repeated_uint32)
611 TEST_TRIM_ONE_FIELD(repeated_uint64)
612 TEST_TRIM_ONE_FIELD(repeated_sint32)
613 TEST_TRIM_ONE_FIELD(repeated_sint64)
614 TEST_TRIM_ONE_FIELD(repeated_fixed32)
615 TEST_TRIM_ONE_FIELD(repeated_fixed64)
616 TEST_TRIM_ONE_FIELD(repeated_sfixed32)
617 TEST_TRIM_ONE_FIELD(repeated_sfixed64)
618 TEST_TRIM_ONE_FIELD(repeated_float)
619 TEST_TRIM_ONE_FIELD(repeated_double)
620 TEST_TRIM_ONE_FIELD(repeated_bool)
621 TEST_TRIM_ONE_FIELD(repeated_string)
622 TEST_TRIM_ONE_FIELD(repeated_bytes)
623 TEST_TRIM_ONE_FIELD(repeated_nested_message)
624 TEST_TRIM_ONE_FIELD(repeated_foreign_message)
625 TEST_TRIM_ONE_FIELD(repeated_import_message)
626 TEST_TRIM_ONE_FIELD(repeated_nested_enum)
627 TEST_TRIM_ONE_FIELD(repeated_foreign_enum)
628 TEST_TRIM_ONE_FIELD(repeated_import_enum)
629 #undef TEST_TRIM_ONE_FIELD
630
631 // Test trim nested fields.
632 NestedTestAllTypes nested_msg;
633 nested_msg.mutable_child()->mutable_payload()->set_optional_int32(1234);
634 nested_msg.mutable_child()
635 ->mutable_child()
636 ->mutable_payload()
637 ->set_optional_int32(5678);
638 NestedTestAllTypes trimmed_msg(nested_msg);
639 FieldMask mask;
640 FieldMaskUtil::FromString("child.payload", &mask);
641 FieldMaskUtil::TrimMessage(mask, &trimmed_msg);
642 EXPECT_EQ(1234, trimmed_msg.child().payload().optional_int32());
643 EXPECT_EQ(0, trimmed_msg.child().child().payload().optional_int32());
644
645 trimmed_msg = nested_msg;
646 FieldMaskUtil::FromString("child.child.payload", &mask);
647 FieldMaskUtil::TrimMessage(mask, &trimmed_msg);
648 EXPECT_EQ(0, trimmed_msg.child().payload().optional_int32());
649 EXPECT_EQ(5678, trimmed_msg.child().child().payload().optional_int32());
650
651 trimmed_msg = nested_msg;
652 FieldMaskUtil::FromString("child", &mask);
653 FieldMaskUtil::TrimMessage(mask, &trimmed_msg);
654 EXPECT_EQ(1234, trimmed_msg.child().payload().optional_int32());
655 EXPECT_EQ(5678, trimmed_msg.child().child().payload().optional_int32());
656
657 trimmed_msg = nested_msg;
658 FieldMaskUtil::FromString("child.child", &mask);
659 FieldMaskUtil::TrimMessage(mask, &trimmed_msg);
660 EXPECT_EQ(0, trimmed_msg.child().payload().optional_int32());
661 EXPECT_EQ(5678, trimmed_msg.child().child().payload().optional_int32());
662
663 // Verify than an empty FieldMask trims nothing
664 TestAllTypes all_types_msg;
665 TestUtil::SetAllFields(&all_types_msg);
666 TestAllTypes trimmed_all_types(all_types_msg);
667 FieldMask empty_mask;
668 FieldMaskUtil::TrimMessage(empty_mask, &trimmed_all_types);
669 EXPECT_EQ(trimmed_all_types.DebugString(), all_types_msg.DebugString());
670
671 // Test trim required fields with keep_required_fields is set true.
672 FieldMaskUtil::TrimOptions options;
673 TestRequired required_msg_1;
674 required_msg_1.set_a(1234);
675 required_msg_1.set_b(3456);
676 required_msg_1.set_c(5678);
677 TestRequired trimmed_required_msg_1(required_msg_1);
678 FieldMaskUtil::FromString("dummy2", &mask);
679 options.set_keep_required_fields(true);
680 FieldMaskUtil::TrimMessage(mask, &trimmed_required_msg_1, options);
681 EXPECT_EQ(trimmed_required_msg_1.DebugString(), required_msg_1.DebugString());
682
683 // Test trim required fields with keep_required_fields is set false.
684 required_msg_1.clear_a();
685 required_msg_1.clear_b();
686 required_msg_1.clear_c();
687 options.set_keep_required_fields(false);
688 FieldMaskUtil::TrimMessage(mask, &trimmed_required_msg_1, options);
689 EXPECT_EQ(trimmed_required_msg_1.DebugString(), required_msg_1.DebugString());
690
691 // Test trim required message with keep_required_fields is set true.
692 TestRequiredMessage required_msg_2;
693 required_msg_2.mutable_optional_message()->set_a(1234);
694 required_msg_2.mutable_optional_message()->set_b(3456);
695 required_msg_2.mutable_optional_message()->set_c(5678);
696 required_msg_2.mutable_required_message()->set_a(1234);
697 required_msg_2.mutable_required_message()->set_b(3456);
698 required_msg_2.mutable_required_message()->set_c(5678);
699 required_msg_2.mutable_required_message()->set_dummy2(7890);
700 TestRequired* repeated_msg = required_msg_2.add_repeated_message();
701 repeated_msg->set_a(1234);
702 repeated_msg->set_b(3456);
703 repeated_msg->set_c(5678);
704 TestRequiredMessage trimmed_required_msg_2(required_msg_2);
705 FieldMaskUtil::FromString("optional_message.dummy2", &mask);
706 options.set_keep_required_fields(true);
707 required_msg_2.clear_repeated_message();
708 required_msg_2.mutable_required_message()->clear_dummy2();
709 FieldMaskUtil::TrimMessage(mask, &trimmed_required_msg_2, options);
710 EXPECT_EQ(trimmed_required_msg_2.DebugString(), required_msg_2.DebugString());
711
712 FieldMaskUtil::FromString("required_message", &mask);
713 required_msg_2.mutable_required_message()->set_dummy2(7890);
714 trimmed_required_msg_2.mutable_required_message()->set_dummy2(7890);
715 required_msg_2.clear_optional_message();
716 FieldMaskUtil::TrimMessage(mask, &trimmed_required_msg_2, options);
717 EXPECT_EQ(trimmed_required_msg_2.DebugString(), required_msg_2.DebugString());
718
719 // Test trim required message with keep_required_fields is set false.
720 FieldMaskUtil::FromString("required_message.dummy2", &mask);
721 required_msg_2.mutable_required_message()->clear_a();
722 required_msg_2.mutable_required_message()->clear_b();
723 required_msg_2.mutable_required_message()->clear_c();
724 options.set_keep_required_fields(false);
725 FieldMaskUtil::TrimMessage(mask, &trimmed_required_msg_2, options);
726 EXPECT_EQ(trimmed_required_msg_2.DebugString(), required_msg_2.DebugString());
727
728 // Verify that trimming an empty message has no effect. In particular, fields
729 // mentioned in the field mask should not be created or changed.
730 TestAllTypes empty_msg;
731 FieldMaskUtil::FromString(
732 "optional_int32,optional_bytes,optional_nested_message.bb", &mask);
733 FieldMaskUtil::TrimMessage(mask, &empty_msg);
734 EXPECT_FALSE(empty_msg.has_optional_int32());
735 EXPECT_FALSE(empty_msg.has_optional_bytes());
736 EXPECT_FALSE(empty_msg.has_optional_nested_message());
737
738 // Verify trimming of oneof fields. This should work as expected even if
739 // multiple elements of the same oneof are included in the FieldMask.
740 TestAllTypes oneof_msg;
741 oneof_msg.set_oneof_uint32(11);
742 FieldMaskUtil::FromString("oneof_uint32,oneof_nested_message.bb", &mask);
743 FieldMaskUtil::TrimMessage(mask, &oneof_msg);
744 EXPECT_EQ(11, oneof_msg.oneof_uint32());
745 }
746
TEST(FieldMaskUtilTest,TrimMessageReturnValue)747 TEST(FieldMaskUtilTest, TrimMessageReturnValue) {
748 FieldMask mask;
749 TestAllTypes trimed_msg;
750 TestAllTypes default_msg;
751
752 // Field mask on optional field.
753 FieldMaskUtil::FromString("optional_int32", &mask);
754
755 // Verify that if a message is updted by FieldMaskUtil::TrimMessage(), the
756 // function returns true.
757 // Test on primary field.
758 trimed_msg.set_optional_string("abc");
759 EXPECT_TRUE(FieldMaskUtil::TrimMessage(mask, &trimed_msg));
760 EXPECT_EQ(trimed_msg.DebugString(), default_msg.DebugString());
761 trimed_msg.Clear();
762
763 // Test on repeated primary field.
764 trimed_msg.add_repeated_string("abc");
765 trimed_msg.add_repeated_string("def");
766 EXPECT_TRUE(FieldMaskUtil::TrimMessage(mask, &trimed_msg));
767 EXPECT_EQ(trimed_msg.DebugString(), default_msg.DebugString());
768 trimed_msg.Clear();
769
770 // Test on nested message.
771 trimed_msg.mutable_optional_nested_message()->set_bb(123);
772 EXPECT_TRUE(FieldMaskUtil::TrimMessage(mask, &trimed_msg));
773 EXPECT_EQ(trimed_msg.DebugString(), default_msg.DebugString());
774 trimed_msg.Clear();
775
776 // Test on repeated nested message.
777 trimed_msg.add_repeated_nested_message()->set_bb(123);
778 trimed_msg.add_repeated_nested_message()->set_bb(456);
779 EXPECT_TRUE(FieldMaskUtil::TrimMessage(mask, &trimed_msg));
780 EXPECT_EQ(trimed_msg.DebugString(), default_msg.DebugString());
781 trimed_msg.Clear();
782
783 // Test on oneof field.
784 trimed_msg.set_oneof_uint32(123);
785 EXPECT_TRUE(FieldMaskUtil::TrimMessage(mask, &trimed_msg));
786 EXPECT_EQ(trimed_msg.DebugString(), default_msg.DebugString());
787 trimed_msg.Clear();
788
789 // If there is no field set other then those whitelisted,
790 // FieldMaskUtil::TrimMessage() should return false.
791 trimed_msg.set_optional_int32(123);
792 EXPECT_FALSE(FieldMaskUtil::TrimMessage(mask, &trimed_msg));
793 EXPECT_EQ(trimed_msg.optional_int32(), 123);
794 trimed_msg.Clear();
795
796 // Field mask on repated field.
797 FieldMaskUtil::FromString("repeated_string", &mask);
798 trimed_msg.add_repeated_string("abc");
799 trimed_msg.add_repeated_string("def");
800 EXPECT_FALSE(FieldMaskUtil::TrimMessage(mask, &trimed_msg));
801 EXPECT_EQ(trimed_msg.repeated_string(0), "abc");
802 EXPECT_EQ(trimed_msg.repeated_string(1), "def");
803 trimed_msg.Clear();
804
805 // Field mask on nested message.
806 FieldMaskUtil::FromString("optional_nested_message.bb", &mask);
807 trimed_msg.mutable_optional_nested_message()->set_bb(123);
808 EXPECT_FALSE(FieldMaskUtil::TrimMessage(mask, &trimed_msg));
809 EXPECT_EQ(trimed_msg.optional_nested_message().bb(), 123);
810 trimed_msg.Clear();
811
812 // TODO(b/32443320): field mask on repeated nested message is not yet
813 // supported.
814 }
815
816
817 } // namespace
818 } // namespace util
819 } // namespace protobuf
820 } // namespace google
821