| OLD | NEW |
| (Empty) | |
| 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 <google/protobuf/field_mask.pb.h> |
| 34 #include <google/protobuf/unittest.pb.h> |
| 35 #include <google/protobuf/test_util.h> |
| 36 #include <gtest/gtest.h> |
| 37 |
| 38 namespace google { |
| 39 namespace protobuf { |
| 40 namespace util { |
| 41 namespace { |
| 42 |
| 43 using protobuf_unittest::TestAllTypes; |
| 44 using protobuf_unittest::NestedTestAllTypes; |
| 45 using google::protobuf::FieldMask; |
| 46 |
| 47 TEST(FieldMaskUtilTest, StringFormat) { |
| 48 FieldMask mask; |
| 49 EXPECT_EQ("", FieldMaskUtil::ToString(mask)); |
| 50 mask.add_paths("foo"); |
| 51 EXPECT_EQ("foo", FieldMaskUtil::ToString(mask)); |
| 52 mask.add_paths("bar"); |
| 53 EXPECT_EQ("foo,bar", FieldMaskUtil::ToString(mask)); |
| 54 |
| 55 FieldMaskUtil::FromString("", &mask); |
| 56 EXPECT_EQ(0, mask.paths_size()); |
| 57 FieldMaskUtil::FromString("foo", &mask); |
| 58 EXPECT_EQ(1, mask.paths_size()); |
| 59 EXPECT_EQ("foo", mask.paths(0)); |
| 60 FieldMaskUtil::FromString("foo,bar", &mask); |
| 61 EXPECT_EQ(2, mask.paths_size()); |
| 62 EXPECT_EQ("foo", mask.paths(0)); |
| 63 EXPECT_EQ("bar", mask.paths(1)); |
| 64 } |
| 65 |
| 66 TEST(FieldMaskUtilTest, TestIsVaildPath) { |
| 67 EXPECT_TRUE(FieldMaskUtil::IsValidPath<TestAllTypes>("optional_int32")); |
| 68 EXPECT_FALSE(FieldMaskUtil::IsValidPath<TestAllTypes>("optional_nonexist")); |
| 69 EXPECT_TRUE( |
| 70 FieldMaskUtil::IsValidPath<TestAllTypes>("optional_nested_message.bb")); |
| 71 EXPECT_FALSE(FieldMaskUtil::IsValidPath<TestAllTypes>( |
| 72 "optional_nested_message.nonexist")); |
| 73 // FieldMask cannot be used to specify sub-fields of a repeated message. |
| 74 EXPECT_FALSE( |
| 75 FieldMaskUtil::IsValidPath<TestAllTypes>("repeated_nested_message.bb")); |
| 76 } |
| 77 |
| 78 TEST(FieldMaskUtilTest, TestIsValidFieldMask) { |
| 79 FieldMask mask; |
| 80 FieldMaskUtil::FromString("optional_int32,optional_nested_message.bb", &mask); |
| 81 EXPECT_TRUE(FieldMaskUtil::IsValidFieldMask<TestAllTypes>(mask)); |
| 82 |
| 83 FieldMaskUtil::FromString( |
| 84 "optional_int32,optional_nested_message.bb,optional_nonexist", &mask); |
| 85 EXPECT_FALSE(FieldMaskUtil::IsValidFieldMask<TestAllTypes>(mask)); |
| 86 } |
| 87 |
| 88 TEST(FieldMaskUtilTest, TestGetFieldMaskForAllFields) { |
| 89 FieldMask mask; |
| 90 FieldMaskUtil::GetFieldMaskForAllFields<TestAllTypes::NestedMessage>(&mask); |
| 91 EXPECT_EQ(1, mask.paths_size()); |
| 92 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("bb", mask)); |
| 93 |
| 94 FieldMaskUtil::GetFieldMaskForAllFields<TestAllTypes>(&mask); |
| 95 EXPECT_EQ(76, mask.paths_size()); |
| 96 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_int32", mask)); |
| 97 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_int64", mask)); |
| 98 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_uint32", mask)); |
| 99 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_uint64", mask)); |
| 100 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_sint32", mask)); |
| 101 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_sint64", mask)); |
| 102 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_fixed32", mask)); |
| 103 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_fixed64", mask)); |
| 104 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_sfixed32", mask)); |
| 105 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_sfixed64", mask)); |
| 106 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_float", mask)); |
| 107 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_double", mask)); |
| 108 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_bool", mask)); |
| 109 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_string", mask)); |
| 110 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_bytes", mask)); |
| 111 EXPECT_TRUE( |
| 112 FieldMaskUtil::IsPathInFieldMask("optional_nested_message", mask)); |
| 113 EXPECT_TRUE( |
| 114 FieldMaskUtil::IsPathInFieldMask("optional_foreign_message", mask)); |
| 115 EXPECT_TRUE( |
| 116 FieldMaskUtil::IsPathInFieldMask("optional_import_message", mask)); |
| 117 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_nested_enum", mask)); |
| 118 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_foreign_enum", mask)); |
| 119 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_import_enum", mask)); |
| 120 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_int32", mask)); |
| 121 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_int64", mask)); |
| 122 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_uint32", mask)); |
| 123 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_uint64", mask)); |
| 124 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_sint32", mask)); |
| 125 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_sint64", mask)); |
| 126 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_fixed32", mask)); |
| 127 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_fixed64", mask)); |
| 128 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_sfixed32", mask)); |
| 129 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_sfixed64", mask)); |
| 130 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_float", mask)); |
| 131 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_double", mask)); |
| 132 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_bool", mask)); |
| 133 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_string", mask)); |
| 134 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_bytes", mask)); |
| 135 EXPECT_TRUE( |
| 136 FieldMaskUtil::IsPathInFieldMask("repeated_nested_message", mask)); |
| 137 EXPECT_TRUE( |
| 138 FieldMaskUtil::IsPathInFieldMask("repeated_foreign_message", mask)); |
| 139 EXPECT_TRUE( |
| 140 FieldMaskUtil::IsPathInFieldMask("repeated_import_message", mask)); |
| 141 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_nested_enum", mask)); |
| 142 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_foreign_enum", mask)); |
| 143 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_import_enum", mask)); |
| 144 } |
| 145 |
| 146 TEST(FieldMaskUtilTest, TestToCanonicalForm) { |
| 147 FieldMask in, out; |
| 148 // Paths will be sorted. |
| 149 FieldMaskUtil::FromString("baz.quz,bar,foo", &in); |
| 150 FieldMaskUtil::ToCanonicalForm(in, &out); |
| 151 EXPECT_EQ("bar,baz.quz,foo", FieldMaskUtil::ToString(out)); |
| 152 // Duplicated paths will be removed. |
| 153 FieldMaskUtil::FromString("foo,bar,foo", &in); |
| 154 FieldMaskUtil::ToCanonicalForm(in, &out); |
| 155 EXPECT_EQ("bar,foo", FieldMaskUtil::ToString(out)); |
| 156 // Sub-paths of other paths will be removed. |
| 157 FieldMaskUtil::FromString("foo.b1,bar.b1,foo.b2,bar", &in); |
| 158 FieldMaskUtil::ToCanonicalForm(in, &out); |
| 159 EXPECT_EQ("bar,foo.b1,foo.b2", FieldMaskUtil::ToString(out)); |
| 160 |
| 161 // Test more deeply nested cases. |
| 162 FieldMaskUtil::FromString( |
| 163 "foo.bar.baz1," |
| 164 "foo.bar.baz2.quz," |
| 165 "foo.bar.baz2", |
| 166 &in); |
| 167 FieldMaskUtil::ToCanonicalForm(in, &out); |
| 168 EXPECT_EQ("foo.bar.baz1,foo.bar.baz2", FieldMaskUtil::ToString(out)); |
| 169 FieldMaskUtil::FromString( |
| 170 "foo.bar.baz1," |
| 171 "foo.bar.baz2," |
| 172 "foo.bar.baz2.quz", |
| 173 &in); |
| 174 FieldMaskUtil::ToCanonicalForm(in, &out); |
| 175 EXPECT_EQ("foo.bar.baz1,foo.bar.baz2", FieldMaskUtil::ToString(out)); |
| 176 FieldMaskUtil::FromString( |
| 177 "foo.bar.baz1," |
| 178 "foo.bar.baz2," |
| 179 "foo.bar.baz2.quz," |
| 180 "foo.bar", |
| 181 &in); |
| 182 FieldMaskUtil::ToCanonicalForm(in, &out); |
| 183 EXPECT_EQ("foo.bar", FieldMaskUtil::ToString(out)); |
| 184 FieldMaskUtil::FromString( |
| 185 "foo.bar.baz1," |
| 186 "foo.bar.baz2," |
| 187 "foo.bar.baz2.quz," |
| 188 "foo", |
| 189 &in); |
| 190 FieldMaskUtil::ToCanonicalForm(in, &out); |
| 191 EXPECT_EQ("foo", FieldMaskUtil::ToString(out)); |
| 192 } |
| 193 |
| 194 TEST(FieldMaskUtilTest, TestUnion) { |
| 195 FieldMask mask1, mask2, out; |
| 196 // Test cases without overlapping. |
| 197 FieldMaskUtil::FromString("foo,baz", &mask1); |
| 198 FieldMaskUtil::FromString("bar,quz", &mask2); |
| 199 FieldMaskUtil::Union(mask1, mask2, &out); |
| 200 EXPECT_EQ("bar,baz,foo,quz", FieldMaskUtil::ToString(out)); |
| 201 // Overlap with duplicated paths. |
| 202 FieldMaskUtil::FromString("foo,baz.bb", &mask1); |
| 203 FieldMaskUtil::FromString("baz.bb,quz", &mask2); |
| 204 FieldMaskUtil::Union(mask1, mask2, &out); |
| 205 EXPECT_EQ("baz.bb,foo,quz", FieldMaskUtil::ToString(out)); |
| 206 // Overlap with paths covering some other paths. |
| 207 FieldMaskUtil::FromString("foo.bar.baz,quz", &mask1); |
| 208 FieldMaskUtil::FromString("foo.bar,bar", &mask2); |
| 209 FieldMaskUtil::Union(mask1, mask2, &out); |
| 210 EXPECT_EQ("bar,foo.bar,quz", FieldMaskUtil::ToString(out)); |
| 211 } |
| 212 |
| 213 TEST(FieldMaskUtilTest, TestIntersect) { |
| 214 FieldMask mask1, mask2, out; |
| 215 // Test cases without overlapping. |
| 216 FieldMaskUtil::FromString("foo,baz", &mask1); |
| 217 FieldMaskUtil::FromString("bar,quz", &mask2); |
| 218 FieldMaskUtil::Intersect(mask1, mask2, &out); |
| 219 EXPECT_EQ("", FieldMaskUtil::ToString(out)); |
| 220 // Overlap with duplicated paths. |
| 221 FieldMaskUtil::FromString("foo,baz.bb", &mask1); |
| 222 FieldMaskUtil::FromString("baz.bb,quz", &mask2); |
| 223 FieldMaskUtil::Intersect(mask1, mask2, &out); |
| 224 EXPECT_EQ("baz.bb", FieldMaskUtil::ToString(out)); |
| 225 // Overlap with paths covering some other paths. |
| 226 FieldMaskUtil::FromString("foo.bar.baz,quz", &mask1); |
| 227 FieldMaskUtil::FromString("foo.bar,bar", &mask2); |
| 228 FieldMaskUtil::Intersect(mask1, mask2, &out); |
| 229 EXPECT_EQ("foo.bar.baz", FieldMaskUtil::ToString(out)); |
| 230 } |
| 231 |
| 232 TEST(FieldMaskUtilTest, TestIspathInFieldMask) { |
| 233 FieldMask mask; |
| 234 FieldMaskUtil::FromString("foo.bar", &mask); |
| 235 EXPECT_FALSE(FieldMaskUtil::IsPathInFieldMask("", mask)); |
| 236 EXPECT_FALSE(FieldMaskUtil::IsPathInFieldMask("foo", mask)); |
| 237 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("foo.bar", mask)); |
| 238 EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("foo.bar.baz", mask)); |
| 239 EXPECT_FALSE(FieldMaskUtil::IsPathInFieldMask("foo.bar0.baz", mask)); |
| 240 } |
| 241 |
| 242 TEST(FieldMaskUtilTest, MergeMessage) { |
| 243 TestAllTypes src, dst; |
| 244 TestUtil::SetAllFields(&src); |
| 245 FieldMaskUtil::MergeOptions options; |
| 246 |
| 247 #define TEST_MERGE_ONE_PRIMITIVE_FIELD(field_name) \ |
| 248 { \ |
| 249 TestAllTypes tmp; \ |
| 250 tmp.set_##field_name(src.field_name()); \ |
| 251 FieldMask mask; \ |
| 252 mask.add_paths(#field_name); \ |
| 253 dst.Clear(); \ |
| 254 FieldMaskUtil::MergeMessageTo(src, mask, options, &dst); \ |
| 255 EXPECT_EQ(tmp.DebugString(), dst.DebugString()); \ |
| 256 } |
| 257 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_int32) |
| 258 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_int64) |
| 259 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_uint32) |
| 260 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_uint64) |
| 261 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_sint32) |
| 262 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_sint64) |
| 263 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_fixed32) |
| 264 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_fixed64) |
| 265 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_sfixed32) |
| 266 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_sfixed64) |
| 267 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_float) |
| 268 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_double) |
| 269 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_bool) |
| 270 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_string) |
| 271 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_bytes) |
| 272 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_nested_enum) |
| 273 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_foreign_enum) |
| 274 TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_import_enum) |
| 275 #undef TEST_MERGE_ONE_PRIMITIVE_FIELD |
| 276 |
| 277 #define TEST_MERGE_ONE_FIELD(field_name) \ |
| 278 { \ |
| 279 TestAllTypes tmp; \ |
| 280 *tmp.mutable_##field_name() = src.field_name(); \ |
| 281 FieldMask mask; \ |
| 282 mask.add_paths(#field_name); \ |
| 283 dst.Clear(); \ |
| 284 FieldMaskUtil::MergeMessageTo(src, mask, options, &dst); \ |
| 285 EXPECT_EQ(tmp.DebugString(), dst.DebugString()); \ |
| 286 } |
| 287 TEST_MERGE_ONE_FIELD(optional_nested_message) |
| 288 TEST_MERGE_ONE_FIELD(optional_foreign_message) |
| 289 TEST_MERGE_ONE_FIELD(optional_import_message) |
| 290 |
| 291 TEST_MERGE_ONE_FIELD(repeated_int32) |
| 292 TEST_MERGE_ONE_FIELD(repeated_int64) |
| 293 TEST_MERGE_ONE_FIELD(repeated_uint32) |
| 294 TEST_MERGE_ONE_FIELD(repeated_uint64) |
| 295 TEST_MERGE_ONE_FIELD(repeated_sint32) |
| 296 TEST_MERGE_ONE_FIELD(repeated_sint64) |
| 297 TEST_MERGE_ONE_FIELD(repeated_fixed32) |
| 298 TEST_MERGE_ONE_FIELD(repeated_fixed64) |
| 299 TEST_MERGE_ONE_FIELD(repeated_sfixed32) |
| 300 TEST_MERGE_ONE_FIELD(repeated_sfixed64) |
| 301 TEST_MERGE_ONE_FIELD(repeated_float) |
| 302 TEST_MERGE_ONE_FIELD(repeated_double) |
| 303 TEST_MERGE_ONE_FIELD(repeated_bool) |
| 304 TEST_MERGE_ONE_FIELD(repeated_string) |
| 305 TEST_MERGE_ONE_FIELD(repeated_bytes) |
| 306 TEST_MERGE_ONE_FIELD(repeated_nested_message) |
| 307 TEST_MERGE_ONE_FIELD(repeated_foreign_message) |
| 308 TEST_MERGE_ONE_FIELD(repeated_import_message) |
| 309 TEST_MERGE_ONE_FIELD(repeated_nested_enum) |
| 310 TEST_MERGE_ONE_FIELD(repeated_foreign_enum) |
| 311 TEST_MERGE_ONE_FIELD(repeated_import_enum) |
| 312 #undef TEST_MERGE_ONE_FIELD |
| 313 |
| 314 // Test merge nested fields. |
| 315 NestedTestAllTypes nested_src, nested_dst; |
| 316 nested_src.mutable_child()->mutable_payload()->set_optional_int32(1234); |
| 317 nested_src.mutable_child() |
| 318 ->mutable_child() |
| 319 ->mutable_payload() |
| 320 ->set_optional_int32(5678); |
| 321 FieldMask mask; |
| 322 FieldMaskUtil::FromString("child.payload", &mask); |
| 323 FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst); |
| 324 EXPECT_EQ(1234, nested_dst.child().payload().optional_int32()); |
| 325 EXPECT_EQ(0, nested_dst.child().child().payload().optional_int32()); |
| 326 |
| 327 FieldMaskUtil::FromString("child.child.payload", &mask); |
| 328 FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst); |
| 329 EXPECT_EQ(1234, nested_dst.child().payload().optional_int32()); |
| 330 EXPECT_EQ(5678, nested_dst.child().child().payload().optional_int32()); |
| 331 |
| 332 nested_dst.Clear(); |
| 333 FieldMaskUtil::FromString("child.child.payload", &mask); |
| 334 FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst); |
| 335 EXPECT_EQ(0, nested_dst.child().payload().optional_int32()); |
| 336 EXPECT_EQ(5678, nested_dst.child().child().payload().optional_int32()); |
| 337 |
| 338 nested_dst.Clear(); |
| 339 FieldMaskUtil::FromString("child", &mask); |
| 340 FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst); |
| 341 EXPECT_EQ(1234, nested_dst.child().payload().optional_int32()); |
| 342 EXPECT_EQ(5678, nested_dst.child().child().payload().optional_int32()); |
| 343 |
| 344 // Test MergeOptions. |
| 345 |
| 346 nested_dst.Clear(); |
| 347 nested_dst.mutable_child()->mutable_payload()->set_optional_int64(4321); |
| 348 // Message fields will be merged by default. |
| 349 FieldMaskUtil::FromString("child.payload", &mask); |
| 350 FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst); |
| 351 EXPECT_EQ(1234, nested_dst.child().payload().optional_int32()); |
| 352 EXPECT_EQ(4321, nested_dst.child().payload().optional_int64()); |
| 353 // Change the behavior to replace message fields. |
| 354 options.set_replace_message_fields(true); |
| 355 FieldMaskUtil::FromString("child.payload", &mask); |
| 356 FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst); |
| 357 EXPECT_EQ(1234, nested_dst.child().payload().optional_int32()); |
| 358 EXPECT_EQ(0, nested_dst.child().payload().optional_int64()); |
| 359 |
| 360 // By default, fields missing in source are not cleared in destination. |
| 361 options.set_replace_message_fields(false); |
| 362 nested_dst.mutable_payload(); |
| 363 EXPECT_TRUE(nested_dst.has_payload()); |
| 364 FieldMaskUtil::FromString("payload", &mask); |
| 365 FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst); |
| 366 EXPECT_TRUE(nested_dst.has_payload()); |
| 367 // But they are cleared when replacing message fields. |
| 368 options.set_replace_message_fields(true); |
| 369 nested_dst.Clear(); |
| 370 nested_dst.mutable_payload(); |
| 371 FieldMaskUtil::FromString("payload", &mask); |
| 372 FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst); |
| 373 EXPECT_FALSE(nested_dst.has_payload()); |
| 374 |
| 375 nested_src.mutable_payload()->add_repeated_int32(1234); |
| 376 nested_dst.mutable_payload()->add_repeated_int32(5678); |
| 377 // Repeated fields will be appended by default. |
| 378 FieldMaskUtil::FromString("payload.repeated_int32", &mask); |
| 379 FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst); |
| 380 ASSERT_EQ(2, nested_dst.payload().repeated_int32_size()); |
| 381 EXPECT_EQ(5678, nested_dst.payload().repeated_int32(0)); |
| 382 EXPECT_EQ(1234, nested_dst.payload().repeated_int32(1)); |
| 383 // Change the behavior to replace repeated fields. |
| 384 options.set_replace_repeated_fields(true); |
| 385 FieldMaskUtil::FromString("payload.repeated_int32", &mask); |
| 386 FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst); |
| 387 ASSERT_EQ(1, nested_dst.payload().repeated_int32_size()); |
| 388 EXPECT_EQ(1234, nested_dst.payload().repeated_int32(0)); |
| 389 } |
| 390 |
| 391 |
| 392 } // namespace |
| 393 } // namespace util |
| 394 } // namespace protobuf |
| 395 } // namespace google |
| OLD | NEW |