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 src.clear_##field_name(); \
353 tmp.clear_##field_name(); \
354 FieldMaskUtil::MergeMessageTo(src, mask, options, &dst); \
355 EXPECT_EQ(tmp.DebugString(), dst.DebugString()); \
356 }
357 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_int32)
358 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_int64)
359 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_uint32)
360 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_uint64)
361 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_sint32)
362 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_sint64)
363 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_fixed32)
364 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_fixed64)
365 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_sfixed32)
366 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_sfixed64)
367 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_float)
368 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_double)
369 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_bool)
370 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_string)
371 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_bytes)
372 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_nested_enum)
373 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_foreign_enum)
374 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_import_enum)
375 #undef TEST_MERGE_ONE_PRIMITIVE_FIELD
376
377 #define TEST_MERGE_ONE_FIELD(field_name) \
378 { \
379 TestAllTypes tmp; \
380 *tmp.mutable_##field_name() = src.field_name(); \
381 FieldMask mask; \
382 mask.add_paths(#field_name); \
383 dst.Clear(); \
384 FieldMaskUtil::MergeMessageTo(src, mask, options, &dst); \
385 EXPECT_EQ(tmp.DebugString(), dst.DebugString()); \
386 }
387 TEST_MERGE_ONE_FIELD(optional_nested_message)
388 TEST_MERGE_ONE_FIELD(optional_foreign_message)
389 TEST_MERGE_ONE_FIELD(optional_import_message)
390
391 TEST_MERGE_ONE_FIELD(repeated_int32)
392 TEST_MERGE_ONE_FIELD(repeated_int64)
393 TEST_MERGE_ONE_FIELD(repeated_uint32)
394 TEST_MERGE_ONE_FIELD(repeated_uint64)
395 TEST_MERGE_ONE_FIELD(repeated_sint32)
396 TEST_MERGE_ONE_FIELD(repeated_sint64)
397 TEST_MERGE_ONE_FIELD(repeated_fixed32)
398 TEST_MERGE_ONE_FIELD(repeated_fixed64)
399 TEST_MERGE_ONE_FIELD(repeated_sfixed32)
400 TEST_MERGE_ONE_FIELD(repeated_sfixed64)
401 TEST_MERGE_ONE_FIELD(repeated_float)
402 TEST_MERGE_ONE_FIELD(repeated_double)
403 TEST_MERGE_ONE_FIELD(repeated_bool)
404 TEST_MERGE_ONE_FIELD(repeated_string)
405 TEST_MERGE_ONE_FIELD(repeated_bytes)
406 TEST_MERGE_ONE_FIELD(repeated_nested_message)
407 TEST_MERGE_ONE_FIELD(repeated_foreign_message)
408 TEST_MERGE_ONE_FIELD(repeated_import_message)
409 TEST_MERGE_ONE_FIELD(repeated_nested_enum)
410 TEST_MERGE_ONE_FIELD(repeated_foreign_enum)
411 TEST_MERGE_ONE_FIELD(repeated_import_enum)
412 #undef TEST_MERGE_ONE_FIELD
413
414 // Test merge nested fields.
415 NestedTestAllTypes nested_src, nested_dst;
416 nested_src.mutable_child()->mutable_payload()->set_optional_int32(1234);
417 nested_src.mutable_child()
418 ->mutable_child()
419 ->mutable_payload()
420 ->set_optional_int32(5678);
421 FieldMask mask;
422 FieldMaskUtil::FromString("child.payload", &mask);
423 FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
424 EXPECT_EQ(1234, nested_dst.child().payload().optional_int32());
425 EXPECT_EQ(0, nested_dst.child().child().payload().optional_int32());
426
427 FieldMaskUtil::FromString("child.child.payload", &mask);
428 FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
429 EXPECT_EQ(1234, nested_dst.child().payload().optional_int32());
430 EXPECT_EQ(5678, nested_dst.child().child().payload().optional_int32());
431
432 nested_dst.Clear();
433 FieldMaskUtil::FromString("child.child.payload", &mask);
434 FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
435 EXPECT_EQ(0, nested_dst.child().payload().optional_int32());
436 EXPECT_EQ(5678, nested_dst.child().child().payload().optional_int32());
437
438 nested_dst.Clear();
439 FieldMaskUtil::FromString("child", &mask);
440 FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
441 EXPECT_EQ(1234, nested_dst.child().payload().optional_int32());
442 EXPECT_EQ(5678, nested_dst.child().child().payload().optional_int32());
443
444 // Test MergeOptions.
445
446 nested_dst.Clear();
447 nested_dst.mutable_child()->mutable_payload()->set_optional_int64(4321);
448 // Message fields will be merged by default.
449 FieldMaskUtil::FromString("child.payload", &mask);
450 FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
451 EXPECT_EQ(1234, nested_dst.child().payload().optional_int32());
452 EXPECT_EQ(4321, nested_dst.child().payload().optional_int64());
453 // Change the behavior to replace message fields.
454 options.set_replace_message_fields(true);
455 FieldMaskUtil::FromString("child.payload", &mask);
456 FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
457 EXPECT_EQ(1234, nested_dst.child().payload().optional_int32());
458 EXPECT_EQ(0, nested_dst.child().payload().optional_int64());
459
460 // By default, fields missing in source are not cleared in destination.
461 options.set_replace_message_fields(false);
462 nested_dst.mutable_payload();
463 EXPECT_TRUE(nested_dst.has_payload());
464 FieldMaskUtil::FromString("payload", &mask);
465 FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
466 EXPECT_TRUE(nested_dst.has_payload());
467 // But they are cleared when replacing message fields.
468 options.set_replace_message_fields(true);
469 nested_dst.Clear();
470 nested_dst.mutable_payload();
471 FieldMaskUtil::FromString("payload", &mask);
472 FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
473 EXPECT_FALSE(nested_dst.has_payload());
474
475 nested_src.mutable_payload()->add_repeated_int32(1234);
476 nested_dst.mutable_payload()->add_repeated_int32(5678);
477 // Repeated fields will be appended by default.
478 FieldMaskUtil::FromString("payload.repeated_int32", &mask);
479 FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
480 ASSERT_EQ(2, nested_dst.payload().repeated_int32_size());
481 EXPECT_EQ(5678, nested_dst.payload().repeated_int32(0));
482 EXPECT_EQ(1234, nested_dst.payload().repeated_int32(1));
483 // Change the behavior to replace repeated fields.
484 options.set_replace_repeated_fields(true);
485 FieldMaskUtil::FromString("payload.repeated_int32", &mask);
486 FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
487 ASSERT_EQ(1, nested_dst.payload().repeated_int32_size());
488 EXPECT_EQ(1234, nested_dst.payload().repeated_int32(0));
489 }
490
TEST(FieldMaskUtilTest,TrimMessage)491 TEST(FieldMaskUtilTest, TrimMessage) {
492 #define TEST_TRIM_ONE_PRIMITIVE_FIELD(field_name) \
493 { \
494 TestAllTypes msg; \
495 TestUtil::SetAllFields(&msg); \
496 TestAllTypes tmp; \
497 tmp.set_##field_name(msg.field_name()); \
498 FieldMask mask; \
499 mask.add_paths(#field_name); \
500 FieldMaskUtil::TrimMessage(mask, &msg); \
501 EXPECT_EQ(tmp.DebugString(), msg.DebugString()); \
502 }
503 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_int32)
504 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_int64)
505 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_uint32)
506 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_uint64)
507 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_sint32)
508 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_sint64)
509 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_fixed32)
510 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_fixed64)
511 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_sfixed32)
512 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_sfixed64)
513 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_float)
514 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_double)
515 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_bool)
516 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_string)
517 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_bytes)
518 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_nested_enum)
519 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_foreign_enum)
520 TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_import_enum)
521 #undef TEST_TRIM_ONE_PRIMITIVE_FIELD
522
523 #define TEST_TRIM_ONE_FIELD(field_name) \
524 { \
525 TestAllTypes msg; \
526 TestUtil::SetAllFields(&msg); \
527 TestAllTypes tmp; \
528 *tmp.mutable_##field_name() = msg.field_name(); \
529 FieldMask mask; \
530 mask.add_paths(#field_name); \
531 FieldMaskUtil::TrimMessage(mask, &msg); \
532 EXPECT_EQ(tmp.DebugString(), msg.DebugString()); \
533 }
534 TEST_TRIM_ONE_FIELD(optional_nested_message)
535 TEST_TRIM_ONE_FIELD(optional_foreign_message)
536 TEST_TRIM_ONE_FIELD(optional_import_message)
537
538 TEST_TRIM_ONE_FIELD(repeated_int32)
539 TEST_TRIM_ONE_FIELD(repeated_int64)
540 TEST_TRIM_ONE_FIELD(repeated_uint32)
541 TEST_TRIM_ONE_FIELD(repeated_uint64)
542 TEST_TRIM_ONE_FIELD(repeated_sint32)
543 TEST_TRIM_ONE_FIELD(repeated_sint64)
544 TEST_TRIM_ONE_FIELD(repeated_fixed32)
545 TEST_TRIM_ONE_FIELD(repeated_fixed64)
546 TEST_TRIM_ONE_FIELD(repeated_sfixed32)
547 TEST_TRIM_ONE_FIELD(repeated_sfixed64)
548 TEST_TRIM_ONE_FIELD(repeated_float)
549 TEST_TRIM_ONE_FIELD(repeated_double)
550 TEST_TRIM_ONE_FIELD(repeated_bool)
551 TEST_TRIM_ONE_FIELD(repeated_string)
552 TEST_TRIM_ONE_FIELD(repeated_bytes)
553 TEST_TRIM_ONE_FIELD(repeated_nested_message)
554 TEST_TRIM_ONE_FIELD(repeated_foreign_message)
555 TEST_TRIM_ONE_FIELD(repeated_import_message)
556 TEST_TRIM_ONE_FIELD(repeated_nested_enum)
557 TEST_TRIM_ONE_FIELD(repeated_foreign_enum)
558 TEST_TRIM_ONE_FIELD(repeated_import_enum)
559 #undef TEST_TRIM_ONE_FIELD
560
561 // Test trim nested fields.
562 NestedTestAllTypes nested_msg;
563 nested_msg.mutable_child()->mutable_payload()->set_optional_int32(1234);
564 nested_msg.mutable_child()
565 ->mutable_child()
566 ->mutable_payload()
567 ->set_optional_int32(5678);
568 NestedTestAllTypes trimmed_msg(nested_msg);
569 FieldMask mask;
570 FieldMaskUtil::FromString("child.payload", &mask);
571 FieldMaskUtil::TrimMessage(mask, &trimmed_msg);
572 EXPECT_EQ(1234, trimmed_msg.child().payload().optional_int32());
573 EXPECT_EQ(0, trimmed_msg.child().child().payload().optional_int32());
574
575 trimmed_msg = nested_msg;
576 FieldMaskUtil::FromString("child.child.payload", &mask);
577 FieldMaskUtil::TrimMessage(mask, &trimmed_msg);
578 EXPECT_EQ(0, trimmed_msg.child().payload().optional_int32());
579 EXPECT_EQ(5678, trimmed_msg.child().child().payload().optional_int32());
580
581 trimmed_msg = nested_msg;
582 FieldMaskUtil::FromString("child", &mask);
583 FieldMaskUtil::TrimMessage(mask, &trimmed_msg);
584 EXPECT_EQ(1234, trimmed_msg.child().payload().optional_int32());
585 EXPECT_EQ(5678, trimmed_msg.child().child().payload().optional_int32());
586
587 trimmed_msg = nested_msg;
588 FieldMaskUtil::FromString("child.child", &mask);
589 FieldMaskUtil::TrimMessage(mask, &trimmed_msg);
590 EXPECT_EQ(0, trimmed_msg.child().payload().optional_int32());
591 EXPECT_EQ(5678, trimmed_msg.child().child().payload().optional_int32());
592
593 // Verify than an empty FieldMask trims nothing
594 TestAllTypes all_types_msg;
595 TestUtil::SetAllFields(&all_types_msg);
596 TestAllTypes trimmed_all_types(all_types_msg);
597 FieldMask empty_mask;
598 FieldMaskUtil::TrimMessage(empty_mask, &trimmed_all_types);
599 EXPECT_EQ(trimmed_all_types.DebugString(), all_types_msg.DebugString());
600 }
601
602
603 } // namespace
604 } // namespace util
605 } // namespace protobuf
606 } // namespace google
607