• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/unittest.pb.h>
39 #include <google/protobuf/test_util.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 string & input)48   string SnakeCaseToCamelCase(const string& input) {
49     string output;
50     if (FieldMaskUtil::SnakeCaseToCamelCase(input, &output)) {
51       return output;
52     } else {
53       return "#FAIL#";
54     }
55   }
56 
CamelCaseToSnakeCase(const string & input)57   string CamelCaseToSnakeCase(const string& input) {
58     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   string name = "___abc123";
96   std::sort(name.begin(), name.end());
97   do {
98     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     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 protobuf_unittest::TestAllTypes;
117 using protobuf_unittest::NestedTestAllTypes;
118 using google::protobuf::FieldMask;
119 
TEST(FieldMaskUtilTest,StringFormat)120 TEST(FieldMaskUtilTest, StringFormat) {
121   FieldMask mask;
122   EXPECT_EQ("", FieldMaskUtil::ToString(mask));
123   mask.add_paths("foo_bar");
124   EXPECT_EQ("foo_bar", FieldMaskUtil::ToString(mask));
125   mask.add_paths("baz_quz");
126   EXPECT_EQ("foo_bar,baz_quz", FieldMaskUtil::ToString(mask));
127 
128   FieldMaskUtil::FromString("", &mask);
129   EXPECT_EQ(0, mask.paths_size());
130   FieldMaskUtil::FromString("fooBar", &mask);
131   EXPECT_EQ(1, mask.paths_size());
132   EXPECT_EQ("fooBar", mask.paths(0));
133   FieldMaskUtil::FromString("fooBar,bazQuz", &mask);
134   EXPECT_EQ(2, mask.paths_size());
135   EXPECT_EQ("fooBar", mask.paths(0));
136   EXPECT_EQ("bazQuz", mask.paths(1));
137 }
138 
TEST(FieldMaskUtilTest,JsonStringFormat)139 TEST(FieldMaskUtilTest, JsonStringFormat) {
140   FieldMask mask;
141   string value;
142   EXPECT_TRUE(FieldMaskUtil::ToJsonString(mask, &value));
143   EXPECT_EQ("", value);
144   mask.add_paths("foo_bar");
145   EXPECT_TRUE(FieldMaskUtil::ToJsonString(mask, &value));
146   EXPECT_EQ("fooBar", value);
147   mask.add_paths("bar_quz");
148   EXPECT_TRUE(FieldMaskUtil::ToJsonString(mask, &value));
149   EXPECT_EQ("fooBar,barQuz", value);
150 
151   FieldMaskUtil::FromJsonString("", &mask);
152   EXPECT_EQ(0, mask.paths_size());
153   FieldMaskUtil::FromJsonString("fooBar", &mask);
154   EXPECT_EQ(1, mask.paths_size());
155   EXPECT_EQ("foo_bar", mask.paths(0));
156   FieldMaskUtil::FromJsonString("fooBar,bazQuz", &mask);
157   EXPECT_EQ(2, mask.paths_size());
158   EXPECT_EQ("foo_bar", mask.paths(0));
159   EXPECT_EQ("baz_quz", mask.paths(1));
160 }
161 
TEST(FieldMaskUtilTest,TestIsVaildPath)162 TEST(FieldMaskUtilTest, TestIsVaildPath) {
163   EXPECT_TRUE(FieldMaskUtil::IsValidPath<TestAllTypes>("optional_int32"));
164   EXPECT_FALSE(FieldMaskUtil::IsValidPath<TestAllTypes>("optional_nonexist"));
165   EXPECT_TRUE(
166       FieldMaskUtil::IsValidPath<TestAllTypes>("optional_nested_message.bb"));
167   EXPECT_FALSE(FieldMaskUtil::IsValidPath<TestAllTypes>(
168       "optional_nested_message.nonexist"));
169   // FieldMask cannot be used to specify sub-fields of a repeated message.
170   EXPECT_FALSE(
171       FieldMaskUtil::IsValidPath<TestAllTypes>("repeated_nested_message.bb"));
172 }
173 
TEST(FieldMaskUtilTest,TestIsValidFieldMask)174 TEST(FieldMaskUtilTest, TestIsValidFieldMask) {
175   FieldMask mask;
176   FieldMaskUtil::FromString("optional_int32,optional_nested_message.bb", &mask);
177   EXPECT_TRUE(FieldMaskUtil::IsValidFieldMask<TestAllTypes>(mask));
178 
179   FieldMaskUtil::FromString(
180       "optional_int32,optional_nested_message.bb,optional_nonexist", &mask);
181   EXPECT_FALSE(FieldMaskUtil::IsValidFieldMask<TestAllTypes>(mask));
182 }
183 
TEST(FieldMaskUtilTest,TestGetFieldMaskForAllFields)184 TEST(FieldMaskUtilTest, TestGetFieldMaskForAllFields) {
185   FieldMask mask;
186   FieldMaskUtil::GetFieldMaskForAllFields<TestAllTypes::NestedMessage>(&mask);
187   EXPECT_EQ(1, mask.paths_size());
188   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("bb", mask));
189 
190   FieldMaskUtil::GetFieldMaskForAllFields<TestAllTypes>(&mask);
191   EXPECT_EQ(76, mask.paths_size());
192   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_int32", mask));
193   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_int64", mask));
194   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_uint32", mask));
195   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_uint64", mask));
196   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_sint32", mask));
197   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_sint64", mask));
198   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_fixed32", mask));
199   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_fixed64", mask));
200   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_sfixed32", mask));
201   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_sfixed64", mask));
202   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_float", mask));
203   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_double", mask));
204   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_bool", mask));
205   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_string", mask));
206   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_bytes", mask));
207   EXPECT_TRUE(
208       FieldMaskUtil::IsPathInFieldMask("optional_nested_message", mask));
209   EXPECT_TRUE(
210       FieldMaskUtil::IsPathInFieldMask("optional_foreign_message", mask));
211   EXPECT_TRUE(
212       FieldMaskUtil::IsPathInFieldMask("optional_import_message", mask));
213   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_nested_enum", mask));
214   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_foreign_enum", mask));
215   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_import_enum", mask));
216   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_int32", mask));
217   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_int64", mask));
218   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_uint32", mask));
219   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_uint64", mask));
220   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_sint32", mask));
221   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_sint64", mask));
222   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_fixed32", mask));
223   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_fixed64", mask));
224   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_sfixed32", mask));
225   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_sfixed64", mask));
226   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_float", mask));
227   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_double", mask));
228   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_bool", mask));
229   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_string", mask));
230   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_bytes", mask));
231   EXPECT_TRUE(
232       FieldMaskUtil::IsPathInFieldMask("repeated_nested_message", mask));
233   EXPECT_TRUE(
234       FieldMaskUtil::IsPathInFieldMask("repeated_foreign_message", mask));
235   EXPECT_TRUE(
236       FieldMaskUtil::IsPathInFieldMask("repeated_import_message", mask));
237   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_nested_enum", mask));
238   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_foreign_enum", mask));
239   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_import_enum", mask));
240 }
241 
TEST(FieldMaskUtilTest,TestToCanonicalForm)242 TEST(FieldMaskUtilTest, TestToCanonicalForm) {
243   FieldMask in, out;
244   // Paths will be sorted.
245   FieldMaskUtil::FromString("baz.quz,bar,foo", &in);
246   FieldMaskUtil::ToCanonicalForm(in, &out);
247   EXPECT_EQ("bar,baz.quz,foo", FieldMaskUtil::ToString(out));
248   // Duplicated paths will be removed.
249   FieldMaskUtil::FromString("foo,bar,foo", &in);
250   FieldMaskUtil::ToCanonicalForm(in, &out);
251   EXPECT_EQ("bar,foo", FieldMaskUtil::ToString(out));
252   // Sub-paths of other paths will be removed.
253   FieldMaskUtil::FromString("foo.b1,bar.b1,foo.b2,bar", &in);
254   FieldMaskUtil::ToCanonicalForm(in, &out);
255   EXPECT_EQ("bar,foo.b1,foo.b2", FieldMaskUtil::ToString(out));
256 
257   // Test more deeply nested cases.
258   FieldMaskUtil::FromString(
259       "foo.bar.baz1,"
260       "foo.bar.baz2.quz,"
261       "foo.bar.baz2",
262       &in);
263   FieldMaskUtil::ToCanonicalForm(in, &out);
264   EXPECT_EQ("foo.bar.baz1,foo.bar.baz2", FieldMaskUtil::ToString(out));
265   FieldMaskUtil::FromString(
266       "foo.bar.baz1,"
267       "foo.bar.baz2,"
268       "foo.bar.baz2.quz",
269       &in);
270   FieldMaskUtil::ToCanonicalForm(in, &out);
271   EXPECT_EQ("foo.bar.baz1,foo.bar.baz2", FieldMaskUtil::ToString(out));
272   FieldMaskUtil::FromString(
273       "foo.bar.baz1,"
274       "foo.bar.baz2,"
275       "foo.bar.baz2.quz,"
276       "foo.bar",
277       &in);
278   FieldMaskUtil::ToCanonicalForm(in, &out);
279   EXPECT_EQ("foo.bar", FieldMaskUtil::ToString(out));
280   FieldMaskUtil::FromString(
281       "foo.bar.baz1,"
282       "foo.bar.baz2,"
283       "foo.bar.baz2.quz,"
284       "foo",
285       &in);
286   FieldMaskUtil::ToCanonicalForm(in, &out);
287   EXPECT_EQ("foo", FieldMaskUtil::ToString(out));
288 }
289 
TEST(FieldMaskUtilTest,TestUnion)290 TEST(FieldMaskUtilTest, TestUnion) {
291   FieldMask mask1, mask2, out;
292   // Test cases without overlapping.
293   FieldMaskUtil::FromString("foo,baz", &mask1);
294   FieldMaskUtil::FromString("bar,quz", &mask2);
295   FieldMaskUtil::Union(mask1, mask2, &out);
296   EXPECT_EQ("bar,baz,foo,quz", FieldMaskUtil::ToString(out));
297   // Overlap with duplicated paths.
298   FieldMaskUtil::FromString("foo,baz.bb", &mask1);
299   FieldMaskUtil::FromString("baz.bb,quz", &mask2);
300   FieldMaskUtil::Union(mask1, mask2, &out);
301   EXPECT_EQ("baz.bb,foo,quz", FieldMaskUtil::ToString(out));
302   // Overlap with paths covering some other paths.
303   FieldMaskUtil::FromString("foo.bar.baz,quz", &mask1);
304   FieldMaskUtil::FromString("foo.bar,bar", &mask2);
305   FieldMaskUtil::Union(mask1, mask2, &out);
306   EXPECT_EQ("bar,foo.bar,quz", FieldMaskUtil::ToString(out));
307 }
308 
TEST(FieldMaskUtilTest,TestIntersect)309 TEST(FieldMaskUtilTest, TestIntersect) {
310   FieldMask mask1, mask2, out;
311   // Test cases without overlapping.
312   FieldMaskUtil::FromString("foo,baz", &mask1);
313   FieldMaskUtil::FromString("bar,quz", &mask2);
314   FieldMaskUtil::Intersect(mask1, mask2, &out);
315   EXPECT_EQ("", FieldMaskUtil::ToString(out));
316   // Overlap with duplicated paths.
317   FieldMaskUtil::FromString("foo,baz.bb", &mask1);
318   FieldMaskUtil::FromString("baz.bb,quz", &mask2);
319   FieldMaskUtil::Intersect(mask1, mask2, &out);
320   EXPECT_EQ("baz.bb", FieldMaskUtil::ToString(out));
321   // Overlap with paths covering some other paths.
322   FieldMaskUtil::FromString("foo.bar.baz,quz", &mask1);
323   FieldMaskUtil::FromString("foo.bar,bar", &mask2);
324   FieldMaskUtil::Intersect(mask1, mask2, &out);
325   EXPECT_EQ("foo.bar.baz", FieldMaskUtil::ToString(out));
326 }
327 
TEST(FieldMaskUtilTest,TestIspathInFieldMask)328 TEST(FieldMaskUtilTest, TestIspathInFieldMask) {
329   FieldMask mask;
330   FieldMaskUtil::FromString("foo.bar", &mask);
331   EXPECT_FALSE(FieldMaskUtil::IsPathInFieldMask("", mask));
332   EXPECT_FALSE(FieldMaskUtil::IsPathInFieldMask("foo", mask));
333   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("foo.bar", mask));
334   EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("foo.bar.baz", mask));
335   EXPECT_FALSE(FieldMaskUtil::IsPathInFieldMask("foo.bar0.baz", mask));
336 }
337 
TEST(FieldMaskUtilTest,MergeMessage)338 TEST(FieldMaskUtilTest, MergeMessage) {
339   TestAllTypes src, dst;
340   TestUtil::SetAllFields(&src);
341   FieldMaskUtil::MergeOptions options;
342 
343 #define TEST_MERGE_ONE_PRIMITIVE_FIELD(field_name)           \
344   {                                                          \
345     TestAllTypes tmp;                                        \
346     tmp.set_##field_name(src.field_name());                  \
347     FieldMask mask;                                          \
348     mask.add_paths(#field_name);                             \
349     dst.Clear();                                             \
350     FieldMaskUtil::MergeMessageTo(src, mask, options, &dst); \
351     EXPECT_EQ(tmp.DebugString(), dst.DebugString());         \
352   }
353   TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_int32)
354   TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_int64)
355   TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_uint32)
356   TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_uint64)
357   TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_sint32)
358   TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_sint64)
359   TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_fixed32)
360   TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_fixed64)
361   TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_sfixed32)
362   TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_sfixed64)
363   TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_float)
364   TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_double)
365   TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_bool)
366   TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_string)
367   TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_bytes)
368   TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_nested_enum)
369   TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_foreign_enum)
370   TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_import_enum)
371 #undef TEST_MERGE_ONE_PRIMITIVE_FIELD
372 
373 #define TEST_MERGE_ONE_FIELD(field_name)                     \
374   {                                                          \
375     TestAllTypes tmp;                                        \
376     *tmp.mutable_##field_name() = src.field_name();          \
377     FieldMask mask;                                          \
378     mask.add_paths(#field_name);                             \
379     dst.Clear();                                             \
380     FieldMaskUtil::MergeMessageTo(src, mask, options, &dst); \
381     EXPECT_EQ(tmp.DebugString(), dst.DebugString());         \
382   }
383   TEST_MERGE_ONE_FIELD(optional_nested_message)
384   TEST_MERGE_ONE_FIELD(optional_foreign_message)
385   TEST_MERGE_ONE_FIELD(optional_import_message)
386 
387   TEST_MERGE_ONE_FIELD(repeated_int32)
388   TEST_MERGE_ONE_FIELD(repeated_int64)
389   TEST_MERGE_ONE_FIELD(repeated_uint32)
390   TEST_MERGE_ONE_FIELD(repeated_uint64)
391   TEST_MERGE_ONE_FIELD(repeated_sint32)
392   TEST_MERGE_ONE_FIELD(repeated_sint64)
393   TEST_MERGE_ONE_FIELD(repeated_fixed32)
394   TEST_MERGE_ONE_FIELD(repeated_fixed64)
395   TEST_MERGE_ONE_FIELD(repeated_sfixed32)
396   TEST_MERGE_ONE_FIELD(repeated_sfixed64)
397   TEST_MERGE_ONE_FIELD(repeated_float)
398   TEST_MERGE_ONE_FIELD(repeated_double)
399   TEST_MERGE_ONE_FIELD(repeated_bool)
400   TEST_MERGE_ONE_FIELD(repeated_string)
401   TEST_MERGE_ONE_FIELD(repeated_bytes)
402   TEST_MERGE_ONE_FIELD(repeated_nested_message)
403   TEST_MERGE_ONE_FIELD(repeated_foreign_message)
404   TEST_MERGE_ONE_FIELD(repeated_import_message)
405   TEST_MERGE_ONE_FIELD(repeated_nested_enum)
406   TEST_MERGE_ONE_FIELD(repeated_foreign_enum)
407   TEST_MERGE_ONE_FIELD(repeated_import_enum)
408 #undef TEST_MERGE_ONE_FIELD
409 
410   // Test merge nested fields.
411   NestedTestAllTypes nested_src, nested_dst;
412   nested_src.mutable_child()->mutable_payload()->set_optional_int32(1234);
413   nested_src.mutable_child()
414       ->mutable_child()
415       ->mutable_payload()
416       ->set_optional_int32(5678);
417   FieldMask mask;
418   FieldMaskUtil::FromString("child.payload", &mask);
419   FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
420   EXPECT_EQ(1234, nested_dst.child().payload().optional_int32());
421   EXPECT_EQ(0, nested_dst.child().child().payload().optional_int32());
422 
423   FieldMaskUtil::FromString("child.child.payload", &mask);
424   FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
425   EXPECT_EQ(1234, nested_dst.child().payload().optional_int32());
426   EXPECT_EQ(5678, nested_dst.child().child().payload().optional_int32());
427 
428   nested_dst.Clear();
429   FieldMaskUtil::FromString("child.child.payload", &mask);
430   FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
431   EXPECT_EQ(0, nested_dst.child().payload().optional_int32());
432   EXPECT_EQ(5678, nested_dst.child().child().payload().optional_int32());
433 
434   nested_dst.Clear();
435   FieldMaskUtil::FromString("child", &mask);
436   FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
437   EXPECT_EQ(1234, nested_dst.child().payload().optional_int32());
438   EXPECT_EQ(5678, nested_dst.child().child().payload().optional_int32());
439 
440   // Test MergeOptions.
441 
442   nested_dst.Clear();
443   nested_dst.mutable_child()->mutable_payload()->set_optional_int64(4321);
444   // Message fields will be merged by default.
445   FieldMaskUtil::FromString("child.payload", &mask);
446   FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
447   EXPECT_EQ(1234, nested_dst.child().payload().optional_int32());
448   EXPECT_EQ(4321, nested_dst.child().payload().optional_int64());
449   // Change the behavior to replace message fields.
450   options.set_replace_message_fields(true);
451   FieldMaskUtil::FromString("child.payload", &mask);
452   FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
453   EXPECT_EQ(1234, nested_dst.child().payload().optional_int32());
454   EXPECT_EQ(0, nested_dst.child().payload().optional_int64());
455 
456   // By default, fields missing in source are not cleared in destination.
457   options.set_replace_message_fields(false);
458   nested_dst.mutable_payload();
459   EXPECT_TRUE(nested_dst.has_payload());
460   FieldMaskUtil::FromString("payload", &mask);
461   FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
462   EXPECT_TRUE(nested_dst.has_payload());
463   // But they are cleared when replacing message fields.
464   options.set_replace_message_fields(true);
465   nested_dst.Clear();
466   nested_dst.mutable_payload();
467   FieldMaskUtil::FromString("payload", &mask);
468   FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
469   EXPECT_FALSE(nested_dst.has_payload());
470 
471   nested_src.mutable_payload()->add_repeated_int32(1234);
472   nested_dst.mutable_payload()->add_repeated_int32(5678);
473   // Repeated fields will be appended by default.
474   FieldMaskUtil::FromString("payload.repeated_int32", &mask);
475   FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
476   ASSERT_EQ(2, nested_dst.payload().repeated_int32_size());
477   EXPECT_EQ(5678, nested_dst.payload().repeated_int32(0));
478   EXPECT_EQ(1234, nested_dst.payload().repeated_int32(1));
479   // Change the behavior to replace repeated fields.
480   options.set_replace_repeated_fields(true);
481   FieldMaskUtil::FromString("payload.repeated_int32", &mask);
482   FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
483   ASSERT_EQ(1, nested_dst.payload().repeated_int32_size());
484   EXPECT_EQ(1234, nested_dst.payload().repeated_int32(0));
485 }
486 
487 
488 }  // namespace
489 }  // namespace util
490 }  // namespace protobuf
491 }  // namespace google
492