| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754 |
- // Protocol Buffers - Google's data interchange format
- // Copyright 2008 Google Inc. All rights reserved.
- // https://developers.google.com/protocol-buffers/
- //
- // Redistribution and use in source and binary forms, with or without
- // modification, are permitted provided that the following conditions are
- // met:
- //
- // * Redistributions of source code must retain the above copyright
- // notice, this list of conditions and the following disclaimer.
- // * Redistributions in binary form must reproduce the above
- // copyright notice, this list of conditions and the following disclaimer
- // in the documentation and/or other materials provided with the
- // distribution.
- // * Neither the name of Google Inc. nor the names of its
- // contributors may be used to endorse or promote products derived from
- // this software without specific prior written permission.
- //
- // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- #include <google/protobuf/util/field_mask_util.h>
- #include <algorithm>
- #include <google/protobuf/stubs/logging.h>
- #include <google/protobuf/stubs/common.h>
- #include <google/protobuf/field_mask.pb.h>
- #include <google/protobuf/unittest.pb.h>
- #include <google/protobuf/test_util.h>
- #include <gtest/gtest.h>
- namespace google {
- namespace protobuf {
- namespace util {
- class SnakeCaseCamelCaseTest : public ::testing::Test {
- protected:
- string SnakeCaseToCamelCase(const string& input) {
- string output;
- if (FieldMaskUtil::SnakeCaseToCamelCase(input, &output)) {
- return output;
- } else {
- return "#FAIL#";
- }
- }
- string CamelCaseToSnakeCase(const string& input) {
- string output;
- if (FieldMaskUtil::CamelCaseToSnakeCase(input, &output)) {
- return output;
- } else {
- return "#FAIL#";
- }
- }
- };
- namespace {
- TEST_F(SnakeCaseCamelCaseTest, SnakeToCamel) {
- EXPECT_EQ("fooBar", SnakeCaseToCamelCase("foo_bar"));
- EXPECT_EQ("FooBar", SnakeCaseToCamelCase("_foo_bar"));
- EXPECT_EQ("foo3Bar", SnakeCaseToCamelCase("foo3_bar"));
- // No uppercase letter is allowed.
- EXPECT_EQ("#FAIL#", SnakeCaseToCamelCase("Foo"));
- // Any character after a "_" must be a lowercase letter.
- // 1. "_" cannot be followed by another "_".
- // 2. "_" cannot be followed by a digit.
- // 3. "_" cannot appear as the last character.
- EXPECT_EQ("#FAIL#", SnakeCaseToCamelCase("foo__bar"));
- EXPECT_EQ("#FAIL#", SnakeCaseToCamelCase("foo_3bar"));
- EXPECT_EQ("#FAIL#", SnakeCaseToCamelCase("foo_bar_"));
- }
- TEST_F(SnakeCaseCamelCaseTest, CamelToSnake) {
- EXPECT_EQ("foo_bar", CamelCaseToSnakeCase("fooBar"));
- EXPECT_EQ("_foo_bar", CamelCaseToSnakeCase("FooBar"));
- EXPECT_EQ("foo3_bar", CamelCaseToSnakeCase("foo3Bar"));
- // "_"s are not allowed.
- EXPECT_EQ("#FAIL#", CamelCaseToSnakeCase("foo_bar"));
- }
- TEST_F(SnakeCaseCamelCaseTest, RoundTripTest) {
- // Enumerates all possible snake_case names and test that converting it to
- // camelCase and then to snake_case again will yield the original name.
- string name = "___abc123";
- std::sort(name.begin(), name.end());
- do {
- string camelName = SnakeCaseToCamelCase(name);
- if (camelName != "#FAIL#") {
- EXPECT_EQ(name, CamelCaseToSnakeCase(camelName));
- }
- } while (std::next_permutation(name.begin(), name.end()));
- // Enumerates all possible camelCase names and test that converting it to
- // snake_case and then to camelCase again will yield the original name.
- name = "abcABC123";
- std::sort(name.begin(), name.end());
- do {
- string camelName = CamelCaseToSnakeCase(name);
- if (camelName != "#FAIL#") {
- EXPECT_EQ(name, SnakeCaseToCamelCase(camelName));
- }
- } while (std::next_permutation(name.begin(), name.end()));
- }
- using protobuf_unittest::TestAllTypes;
- using protobuf_unittest::TestRequired;
- using protobuf_unittest::TestRequiredMessage;
- using protobuf_unittest::NestedTestAllTypes;
- using google::protobuf::FieldMask;
- TEST(FieldMaskUtilTest, StringFormat) {
- FieldMask mask;
- EXPECT_EQ("", FieldMaskUtil::ToString(mask));
- mask.add_paths("foo_bar");
- EXPECT_EQ("foo_bar", FieldMaskUtil::ToString(mask));
- mask.add_paths("baz_quz");
- EXPECT_EQ("foo_bar,baz_quz", FieldMaskUtil::ToString(mask));
- FieldMaskUtil::FromString("", &mask);
- EXPECT_EQ(0, mask.paths_size());
- FieldMaskUtil::FromString("fooBar", &mask);
- EXPECT_EQ(1, mask.paths_size());
- EXPECT_EQ("fooBar", mask.paths(0));
- FieldMaskUtil::FromString("fooBar,bazQuz", &mask);
- EXPECT_EQ(2, mask.paths_size());
- EXPECT_EQ("fooBar", mask.paths(0));
- EXPECT_EQ("bazQuz", mask.paths(1));
- }
- TEST(FieldMaskUtilTest, JsonStringFormat) {
- FieldMask mask;
- string value;
- EXPECT_TRUE(FieldMaskUtil::ToJsonString(mask, &value));
- EXPECT_EQ("", value);
- mask.add_paths("foo_bar");
- EXPECT_TRUE(FieldMaskUtil::ToJsonString(mask, &value));
- EXPECT_EQ("fooBar", value);
- mask.add_paths("bar_quz");
- EXPECT_TRUE(FieldMaskUtil::ToJsonString(mask, &value));
- EXPECT_EQ("fooBar,barQuz", value);
- FieldMaskUtil::FromJsonString("", &mask);
- EXPECT_EQ(0, mask.paths_size());
- FieldMaskUtil::FromJsonString("fooBar", &mask);
- EXPECT_EQ(1, mask.paths_size());
- EXPECT_EQ("foo_bar", mask.paths(0));
- FieldMaskUtil::FromJsonString("fooBar,bazQuz", &mask);
- EXPECT_EQ(2, mask.paths_size());
- EXPECT_EQ("foo_bar", mask.paths(0));
- EXPECT_EQ("baz_quz", mask.paths(1));
- }
- TEST(FieldMaskUtilTest, GetFieldDescriptors) {
- std::vector<const FieldDescriptor*> field_descriptors;
- EXPECT_TRUE(FieldMaskUtil::GetFieldDescriptors(
- TestAllTypes::descriptor(), "optional_int32", &field_descriptors));
- EXPECT_EQ(1, field_descriptors.size());
- EXPECT_EQ("optional_int32", field_descriptors[0]->name());
- EXPECT_FALSE(FieldMaskUtil::GetFieldDescriptors(
- TestAllTypes::descriptor(), "optional_nonexist", nullptr));
- EXPECT_TRUE(FieldMaskUtil::GetFieldDescriptors(TestAllTypes::descriptor(),
- "optional_nested_message.bb",
- &field_descriptors));
- EXPECT_EQ(2, field_descriptors.size());
- EXPECT_EQ("optional_nested_message", field_descriptors[0]->name());
- EXPECT_EQ("bb", field_descriptors[1]->name());
- EXPECT_FALSE(FieldMaskUtil::GetFieldDescriptors(
- TestAllTypes::descriptor(), "optional_nested_message.nonexist", nullptr));
- // FieldMask cannot be used to specify sub-fields of a repeated message.
- EXPECT_FALSE(FieldMaskUtil::GetFieldDescriptors(
- TestAllTypes::descriptor(), "repeated_nested_message.bb", nullptr));
- }
- TEST(FieldMaskUtilTest, TestIsVaildPath) {
- EXPECT_TRUE(FieldMaskUtil::IsValidPath<TestAllTypes>("optional_int32"));
- EXPECT_FALSE(FieldMaskUtil::IsValidPath<TestAllTypes>("optional_nonexist"));
- EXPECT_TRUE(
- FieldMaskUtil::IsValidPath<TestAllTypes>("optional_nested_message.bb"));
- EXPECT_FALSE(FieldMaskUtil::IsValidPath<TestAllTypes>(
- "optional_nested_message.nonexist"));
- // FieldMask cannot be used to specify sub-fields of a repeated message.
- EXPECT_FALSE(
- FieldMaskUtil::IsValidPath<TestAllTypes>("repeated_nested_message.bb"));
- }
- TEST(FieldMaskUtilTest, TestIsValidFieldMask) {
- FieldMask mask;
- FieldMaskUtil::FromString("optional_int32,optional_nested_message.bb", &mask);
- EXPECT_TRUE(FieldMaskUtil::IsValidFieldMask<TestAllTypes>(mask));
- FieldMaskUtil::FromString(
- "optional_int32,optional_nested_message.bb,optional_nonexist", &mask);
- EXPECT_FALSE(FieldMaskUtil::IsValidFieldMask<TestAllTypes>(mask));
- }
- TEST(FieldMaskUtilTest, TestGetFieldMaskForAllFields) {
- FieldMask mask;
- mask = FieldMaskUtil::GetFieldMaskForAllFields<TestAllTypes::NestedMessage>();
- EXPECT_EQ(1, mask.paths_size());
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("bb", mask));
- mask = FieldMaskUtil::GetFieldMaskForAllFields<TestAllTypes>();
- EXPECT_EQ(75, mask.paths_size());
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_int32", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_int64", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_uint32", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_uint64", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_sint32", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_sint64", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_fixed32", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_fixed64", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_sfixed32", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_sfixed64", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_float", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_double", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_bool", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_string", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_bytes", mask));
- EXPECT_TRUE(
- FieldMaskUtil::IsPathInFieldMask("optional_nested_message", mask));
- EXPECT_TRUE(
- FieldMaskUtil::IsPathInFieldMask("optional_foreign_message", mask));
- EXPECT_TRUE(
- FieldMaskUtil::IsPathInFieldMask("optional_import_message", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_nested_enum", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_foreign_enum", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("optional_import_enum", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_int32", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_int64", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_uint32", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_uint64", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_sint32", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_sint64", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_fixed32", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_fixed64", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_sfixed32", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_sfixed64", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_float", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_double", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_bool", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_string", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_bytes", mask));
- EXPECT_TRUE(
- FieldMaskUtil::IsPathInFieldMask("repeated_nested_message", mask));
- EXPECT_TRUE(
- FieldMaskUtil::IsPathInFieldMask("repeated_foreign_message", mask));
- EXPECT_TRUE(
- FieldMaskUtil::IsPathInFieldMask("repeated_import_message", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_nested_enum", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_foreign_enum", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("repeated_import_enum", mask));
- }
- TEST(FieldMaskUtilTest, TestToCanonicalForm) {
- FieldMask in, out;
- // Paths will be sorted.
- FieldMaskUtil::FromString("baz.quz,bar,foo", &in);
- FieldMaskUtil::ToCanonicalForm(in, &out);
- EXPECT_EQ("bar,baz.quz,foo", FieldMaskUtil::ToString(out));
- // Duplicated paths will be removed.
- FieldMaskUtil::FromString("foo,bar,foo", &in);
- FieldMaskUtil::ToCanonicalForm(in, &out);
- EXPECT_EQ("bar,foo", FieldMaskUtil::ToString(out));
- // Sub-paths of other paths will be removed.
- FieldMaskUtil::FromString("foo.b1,bar.b1,foo.b2,bar", &in);
- FieldMaskUtil::ToCanonicalForm(in, &out);
- EXPECT_EQ("bar,foo.b1,foo.b2", FieldMaskUtil::ToString(out));
- // Test more deeply nested cases.
- FieldMaskUtil::FromString(
- "foo.bar.baz1,"
- "foo.bar.baz2.quz,"
- "foo.bar.baz2",
- &in);
- FieldMaskUtil::ToCanonicalForm(in, &out);
- EXPECT_EQ("foo.bar.baz1,foo.bar.baz2", FieldMaskUtil::ToString(out));
- FieldMaskUtil::FromString(
- "foo.bar.baz1,"
- "foo.bar.baz2,"
- "foo.bar.baz2.quz",
- &in);
- FieldMaskUtil::ToCanonicalForm(in, &out);
- EXPECT_EQ("foo.bar.baz1,foo.bar.baz2", FieldMaskUtil::ToString(out));
- FieldMaskUtil::FromString(
- "foo.bar.baz1,"
- "foo.bar.baz2,"
- "foo.bar.baz2.quz,"
- "foo.bar",
- &in);
- FieldMaskUtil::ToCanonicalForm(in, &out);
- EXPECT_EQ("foo.bar", FieldMaskUtil::ToString(out));
- FieldMaskUtil::FromString(
- "foo.bar.baz1,"
- "foo.bar.baz2,"
- "foo.bar.baz2.quz,"
- "foo",
- &in);
- FieldMaskUtil::ToCanonicalForm(in, &out);
- EXPECT_EQ("foo", FieldMaskUtil::ToString(out));
- }
- TEST(FieldMaskUtilTest, TestUnion) {
- FieldMask mask1, mask2, out;
- // Test cases without overlapping.
- FieldMaskUtil::FromString("foo,baz", &mask1);
- FieldMaskUtil::FromString("bar,quz", &mask2);
- FieldMaskUtil::Union(mask1, mask2, &out);
- EXPECT_EQ("bar,baz,foo,quz", FieldMaskUtil::ToString(out));
- // Overlap with duplicated paths.
- FieldMaskUtil::FromString("foo,baz.bb", &mask1);
- FieldMaskUtil::FromString("baz.bb,quz", &mask2);
- FieldMaskUtil::Union(mask1, mask2, &out);
- EXPECT_EQ("baz.bb,foo,quz", FieldMaskUtil::ToString(out));
- // Overlap with paths covering some other paths.
- FieldMaskUtil::FromString("foo.bar.baz,quz", &mask1);
- FieldMaskUtil::FromString("foo.bar,bar", &mask2);
- FieldMaskUtil::Union(mask1, mask2, &out);
- EXPECT_EQ("bar,foo.bar,quz", FieldMaskUtil::ToString(out));
- }
- TEST(FieldMaskUtilTest, TestIntersect) {
- FieldMask mask1, mask2, out;
- // Test cases without overlapping.
- FieldMaskUtil::FromString("foo,baz", &mask1);
- FieldMaskUtil::FromString("bar,quz", &mask2);
- FieldMaskUtil::Intersect(mask1, mask2, &out);
- EXPECT_EQ("", FieldMaskUtil::ToString(out));
- // Overlap with duplicated paths.
- FieldMaskUtil::FromString("foo,baz.bb", &mask1);
- FieldMaskUtil::FromString("baz.bb,quz", &mask2);
- FieldMaskUtil::Intersect(mask1, mask2, &out);
- EXPECT_EQ("baz.bb", FieldMaskUtil::ToString(out));
- // Overlap with paths covering some other paths.
- FieldMaskUtil::FromString("foo.bar.baz,quz", &mask1);
- FieldMaskUtil::FromString("foo.bar,bar", &mask2);
- FieldMaskUtil::Intersect(mask1, mask2, &out);
- EXPECT_EQ("foo.bar.baz", FieldMaskUtil::ToString(out));
- }
- TEST(FieldMaskUtilTest, TestSubtract) {
- FieldMask mask1, mask2, out;
- // Normal case.
- FieldMaskUtil::FromString(
- "optional_int32,optional_uint64,optional_nested_message,optional_foreign_"
- "message,repeated_int32,repeated_foreign_message,repeated_nested_message."
- "bb",
- &mask1);
- FieldMaskUtil::FromString(
- "optional_int32,optional_nested_message.bb,optional_foreign_message.c,"
- "repeated_int32,repeated_nested_message.bb,repeated_foreign_message.f,"
- "repeated_foreign_message.d,repeated_nested_message.bb,repeated_uint32",
- &mask2);
- FieldMaskUtil::Subtract<TestAllTypes>(mask1, mask2, &out);
- EXPECT_EQ(
- "optional_foreign_message.d,optional_uint64,repeated_foreign_message.c",
- FieldMaskUtil::ToString(out));
- // mask1 is empty.
- FieldMaskUtil::FromString("", &mask1);
- FieldMaskUtil::Subtract<TestAllTypes>(mask1, mask2, &out);
- EXPECT_EQ("", FieldMaskUtil::ToString(out));
- // mask1 is "optional_nested_message" and mask2 is
- // "optional_nested_message.nonexist_field".
- FieldMaskUtil::FromString("optional_nested_message", &mask1);
- FieldMaskUtil::FromString("optional_nested_message.nonexist_field", &mask2);
- FieldMaskUtil::Subtract<TestAllTypes>(mask1, mask2, &out);
- EXPECT_EQ("optional_nested_message", FieldMaskUtil::ToString(out));
- // mask1 is "optional_nested_message" and mask2 is
- // "optional_nested_message".
- FieldMaskUtil::FromString("optional_nested_message", &mask1);
- FieldMaskUtil::FromString("optional_nested_message", &mask2);
- FieldMaskUtil::Subtract<TestAllTypes>(mask1, mask2, &out);
- EXPECT_EQ("", FieldMaskUtil::ToString(out));
- // Regression test for b/72727550
- FieldMaskUtil::FromString("optional_foreign_message.c", &mask1);
- FieldMaskUtil::FromString("optional_foreign_message,optional_nested_message",
- &mask2);
- FieldMaskUtil::Subtract<TestAllTypes>(mask1, mask2, &out);
- EXPECT_EQ("", FieldMaskUtil::ToString(out));
- }
- TEST(FieldMaskUtilTest, TestIspathInFieldMask) {
- FieldMask mask;
- FieldMaskUtil::FromString("foo.bar", &mask);
- EXPECT_FALSE(FieldMaskUtil::IsPathInFieldMask("", mask));
- EXPECT_FALSE(FieldMaskUtil::IsPathInFieldMask("foo", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("foo.bar", mask));
- EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("foo.bar.baz", mask));
- EXPECT_FALSE(FieldMaskUtil::IsPathInFieldMask("foo.bar0.baz", mask));
- }
- TEST(FieldMaskUtilTest, MergeMessage) {
- TestAllTypes src, dst;
- TestUtil::SetAllFields(&src);
- FieldMaskUtil::MergeOptions options;
- #define TEST_MERGE_ONE_PRIMITIVE_FIELD(field_name) \
- { \
- TestAllTypes tmp; \
- tmp.set_##field_name(src.field_name()); \
- FieldMask mask; \
- mask.add_paths(#field_name); \
- dst.Clear(); \
- FieldMaskUtil::MergeMessageTo(src, mask, options, &dst); \
- EXPECT_EQ(tmp.DebugString(), dst.DebugString()); \
- src.clear_##field_name(); \
- tmp.clear_##field_name(); \
- FieldMaskUtil::MergeMessageTo(src, mask, options, &dst); \
- EXPECT_EQ(tmp.DebugString(), dst.DebugString()); \
- }
- TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_int32)
- TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_int64)
- TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_uint32)
- TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_uint64)
- TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_sint32)
- TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_sint64)
- TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_fixed32)
- TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_fixed64)
- TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_sfixed32)
- TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_sfixed64)
- TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_float)
- TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_double)
- TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_bool)
- TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_string)
- TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_bytes)
- TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_nested_enum)
- TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_foreign_enum)
- TEST_MERGE_ONE_PRIMITIVE_FIELD(optional_import_enum)
- #undef TEST_MERGE_ONE_PRIMITIVE_FIELD
- #define TEST_MERGE_ONE_FIELD(field_name) \
- { \
- TestAllTypes tmp; \
- *tmp.mutable_##field_name() = src.field_name(); \
- FieldMask mask; \
- mask.add_paths(#field_name); \
- dst.Clear(); \
- FieldMaskUtil::MergeMessageTo(src, mask, options, &dst); \
- EXPECT_EQ(tmp.DebugString(), dst.DebugString()); \
- }
- TEST_MERGE_ONE_FIELD(optional_nested_message)
- TEST_MERGE_ONE_FIELD(optional_foreign_message)
- TEST_MERGE_ONE_FIELD(optional_import_message)
- TEST_MERGE_ONE_FIELD(repeated_int32)
- TEST_MERGE_ONE_FIELD(repeated_int64)
- TEST_MERGE_ONE_FIELD(repeated_uint32)
- TEST_MERGE_ONE_FIELD(repeated_uint64)
- TEST_MERGE_ONE_FIELD(repeated_sint32)
- TEST_MERGE_ONE_FIELD(repeated_sint64)
- TEST_MERGE_ONE_FIELD(repeated_fixed32)
- TEST_MERGE_ONE_FIELD(repeated_fixed64)
- TEST_MERGE_ONE_FIELD(repeated_sfixed32)
- TEST_MERGE_ONE_FIELD(repeated_sfixed64)
- TEST_MERGE_ONE_FIELD(repeated_float)
- TEST_MERGE_ONE_FIELD(repeated_double)
- TEST_MERGE_ONE_FIELD(repeated_bool)
- TEST_MERGE_ONE_FIELD(repeated_string)
- TEST_MERGE_ONE_FIELD(repeated_bytes)
- TEST_MERGE_ONE_FIELD(repeated_nested_message)
- TEST_MERGE_ONE_FIELD(repeated_foreign_message)
- TEST_MERGE_ONE_FIELD(repeated_import_message)
- TEST_MERGE_ONE_FIELD(repeated_nested_enum)
- TEST_MERGE_ONE_FIELD(repeated_foreign_enum)
- TEST_MERGE_ONE_FIELD(repeated_import_enum)
- #undef TEST_MERGE_ONE_FIELD
- // Test merge nested fields.
- NestedTestAllTypes nested_src, nested_dst;
- nested_src.mutable_child()->mutable_payload()->set_optional_int32(1234);
- nested_src.mutable_child()
- ->mutable_child()
- ->mutable_payload()
- ->set_optional_int32(5678);
- FieldMask mask;
- FieldMaskUtil::FromString("child.payload", &mask);
- FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
- EXPECT_EQ(1234, nested_dst.child().payload().optional_int32());
- EXPECT_EQ(0, nested_dst.child().child().payload().optional_int32());
- FieldMaskUtil::FromString("child.child.payload", &mask);
- FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
- EXPECT_EQ(1234, nested_dst.child().payload().optional_int32());
- EXPECT_EQ(5678, nested_dst.child().child().payload().optional_int32());
- nested_dst.Clear();
- FieldMaskUtil::FromString("child.child.payload", &mask);
- FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
- EXPECT_EQ(0, nested_dst.child().payload().optional_int32());
- EXPECT_EQ(5678, nested_dst.child().child().payload().optional_int32());
- nested_dst.Clear();
- FieldMaskUtil::FromString("child", &mask);
- FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
- EXPECT_EQ(1234, nested_dst.child().payload().optional_int32());
- EXPECT_EQ(5678, nested_dst.child().child().payload().optional_int32());
- // Test MergeOptions.
- nested_dst.Clear();
- nested_dst.mutable_child()->mutable_payload()->set_optional_int64(4321);
- // Message fields will be merged by default.
- FieldMaskUtil::FromString("child.payload", &mask);
- FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
- EXPECT_EQ(1234, nested_dst.child().payload().optional_int32());
- EXPECT_EQ(4321, nested_dst.child().payload().optional_int64());
- // Change the behavior to replace message fields.
- options.set_replace_message_fields(true);
- FieldMaskUtil::FromString("child.payload", &mask);
- FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
- EXPECT_EQ(1234, nested_dst.child().payload().optional_int32());
- EXPECT_EQ(0, nested_dst.child().payload().optional_int64());
- // By default, fields missing in source are not cleared in destination.
- options.set_replace_message_fields(false);
- nested_dst.mutable_payload();
- EXPECT_TRUE(nested_dst.has_payload());
- FieldMaskUtil::FromString("payload", &mask);
- FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
- EXPECT_TRUE(nested_dst.has_payload());
- // But they are cleared when replacing message fields.
- options.set_replace_message_fields(true);
- nested_dst.Clear();
- nested_dst.mutable_payload();
- FieldMaskUtil::FromString("payload", &mask);
- FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
- EXPECT_FALSE(nested_dst.has_payload());
- nested_src.mutable_payload()->add_repeated_int32(1234);
- nested_dst.mutable_payload()->add_repeated_int32(5678);
- // Repeated fields will be appended by default.
- FieldMaskUtil::FromString("payload.repeated_int32", &mask);
- FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
- ASSERT_EQ(2, nested_dst.payload().repeated_int32_size());
- EXPECT_EQ(5678, nested_dst.payload().repeated_int32(0));
- EXPECT_EQ(1234, nested_dst.payload().repeated_int32(1));
- // Change the behavior to replace repeated fields.
- options.set_replace_repeated_fields(true);
- FieldMaskUtil::FromString("payload.repeated_int32", &mask);
- FieldMaskUtil::MergeMessageTo(nested_src, mask, options, &nested_dst);
- ASSERT_EQ(1, nested_dst.payload().repeated_int32_size());
- EXPECT_EQ(1234, nested_dst.payload().repeated_int32(0));
- }
- TEST(FieldMaskUtilTest, TrimMessage) {
- #define TEST_TRIM_ONE_PRIMITIVE_FIELD(field_name) \
- { \
- TestAllTypes msg; \
- TestUtil::SetAllFields(&msg); \
- TestAllTypes tmp; \
- tmp.set_##field_name(msg.field_name()); \
- FieldMask mask; \
- mask.add_paths(#field_name); \
- FieldMaskUtil::TrimMessage(mask, &msg); \
- EXPECT_EQ(tmp.DebugString(), msg.DebugString()); \
- }
- TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_int32)
- TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_int64)
- TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_uint32)
- TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_uint64)
- TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_sint32)
- TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_sint64)
- TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_fixed32)
- TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_fixed64)
- TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_sfixed32)
- TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_sfixed64)
- TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_float)
- TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_double)
- TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_bool)
- TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_string)
- TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_bytes)
- TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_nested_enum)
- TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_foreign_enum)
- TEST_TRIM_ONE_PRIMITIVE_FIELD(optional_import_enum)
- #undef TEST_TRIM_ONE_PRIMITIVE_FIELD
- #define TEST_TRIM_ONE_FIELD(field_name) \
- { \
- TestAllTypes msg; \
- TestUtil::SetAllFields(&msg); \
- TestAllTypes tmp; \
- *tmp.mutable_##field_name() = msg.field_name(); \
- FieldMask mask; \
- mask.add_paths(#field_name); \
- FieldMaskUtil::TrimMessage(mask, &msg); \
- EXPECT_EQ(tmp.DebugString(), msg.DebugString()); \
- }
- TEST_TRIM_ONE_FIELD(optional_nested_message)
- TEST_TRIM_ONE_FIELD(optional_foreign_message)
- TEST_TRIM_ONE_FIELD(optional_import_message)
- TEST_TRIM_ONE_FIELD(repeated_int32)
- TEST_TRIM_ONE_FIELD(repeated_int64)
- TEST_TRIM_ONE_FIELD(repeated_uint32)
- TEST_TRIM_ONE_FIELD(repeated_uint64)
- TEST_TRIM_ONE_FIELD(repeated_sint32)
- TEST_TRIM_ONE_FIELD(repeated_sint64)
- TEST_TRIM_ONE_FIELD(repeated_fixed32)
- TEST_TRIM_ONE_FIELD(repeated_fixed64)
- TEST_TRIM_ONE_FIELD(repeated_sfixed32)
- TEST_TRIM_ONE_FIELD(repeated_sfixed64)
- TEST_TRIM_ONE_FIELD(repeated_float)
- TEST_TRIM_ONE_FIELD(repeated_double)
- TEST_TRIM_ONE_FIELD(repeated_bool)
- TEST_TRIM_ONE_FIELD(repeated_string)
- TEST_TRIM_ONE_FIELD(repeated_bytes)
- TEST_TRIM_ONE_FIELD(repeated_nested_message)
- TEST_TRIM_ONE_FIELD(repeated_foreign_message)
- TEST_TRIM_ONE_FIELD(repeated_import_message)
- TEST_TRIM_ONE_FIELD(repeated_nested_enum)
- TEST_TRIM_ONE_FIELD(repeated_foreign_enum)
- TEST_TRIM_ONE_FIELD(repeated_import_enum)
- #undef TEST_TRIM_ONE_FIELD
- // Test trim nested fields.
- NestedTestAllTypes nested_msg;
- nested_msg.mutable_child()->mutable_payload()->set_optional_int32(1234);
- nested_msg.mutable_child()
- ->mutable_child()
- ->mutable_payload()
- ->set_optional_int32(5678);
- NestedTestAllTypes trimmed_msg(nested_msg);
- FieldMask mask;
- FieldMaskUtil::FromString("child.payload", &mask);
- FieldMaskUtil::TrimMessage(mask, &trimmed_msg);
- EXPECT_EQ(1234, trimmed_msg.child().payload().optional_int32());
- EXPECT_EQ(0, trimmed_msg.child().child().payload().optional_int32());
- trimmed_msg = nested_msg;
- FieldMaskUtil::FromString("child.child.payload", &mask);
- FieldMaskUtil::TrimMessage(mask, &trimmed_msg);
- EXPECT_EQ(0, trimmed_msg.child().payload().optional_int32());
- EXPECT_EQ(5678, trimmed_msg.child().child().payload().optional_int32());
- trimmed_msg = nested_msg;
- FieldMaskUtil::FromString("child", &mask);
- FieldMaskUtil::TrimMessage(mask, &trimmed_msg);
- EXPECT_EQ(1234, trimmed_msg.child().payload().optional_int32());
- EXPECT_EQ(5678, trimmed_msg.child().child().payload().optional_int32());
- trimmed_msg = nested_msg;
- FieldMaskUtil::FromString("child.child", &mask);
- FieldMaskUtil::TrimMessage(mask, &trimmed_msg);
- EXPECT_EQ(0, trimmed_msg.child().payload().optional_int32());
- EXPECT_EQ(5678, trimmed_msg.child().child().payload().optional_int32());
- // Verify than an empty FieldMask trims nothing
- TestAllTypes all_types_msg;
- TestUtil::SetAllFields(&all_types_msg);
- TestAllTypes trimmed_all_types(all_types_msg);
- FieldMask empty_mask;
- FieldMaskUtil::TrimMessage(empty_mask, &trimmed_all_types);
- EXPECT_EQ(trimmed_all_types.DebugString(), all_types_msg.DebugString());
- // Test trim required fields with keep_required_fields is set true.
- FieldMaskUtil::TrimOptions options;
- TestRequired required_msg_1;
- required_msg_1.set_a(1234);
- required_msg_1.set_b(3456);
- required_msg_1.set_c(5678);
- TestRequired trimmed_required_msg_1(required_msg_1);
- FieldMaskUtil::FromString("dummy2", &mask);
- options.set_keep_required_fields(true);
- FieldMaskUtil::TrimMessage(mask, &trimmed_required_msg_1, options);
- EXPECT_EQ(trimmed_required_msg_1.DebugString(), required_msg_1.DebugString());
- // Test trim required fields with keep_required_fields is set false.
- required_msg_1.clear_a();
- required_msg_1.clear_b();
- required_msg_1.clear_c();
- options.set_keep_required_fields(false);
- FieldMaskUtil::TrimMessage(mask, &trimmed_required_msg_1, options);
- EXPECT_EQ(trimmed_required_msg_1.DebugString(), required_msg_1.DebugString());
- // Test trim required message with keep_required_fields is set true.
- TestRequiredMessage required_msg_2;
- required_msg_2.mutable_optional_message()->set_a(1234);
- required_msg_2.mutable_optional_message()->set_b(3456);
- required_msg_2.mutable_optional_message()->set_c(5678);
- required_msg_2.mutable_required_message()->set_a(1234);
- required_msg_2.mutable_required_message()->set_b(3456);
- required_msg_2.mutable_required_message()->set_c(5678);
- required_msg_2.mutable_required_message()->set_dummy2(7890);
- TestRequired* repeated_msg = required_msg_2.add_repeated_message();
- repeated_msg->set_a(1234);
- repeated_msg->set_b(3456);
- repeated_msg->set_c(5678);
- TestRequiredMessage trimmed_required_msg_2(required_msg_2);
- FieldMaskUtil::FromString("optional_message.dummy2", &mask);
- options.set_keep_required_fields(true);
- required_msg_2.clear_repeated_message();
- required_msg_2.mutable_required_message()->clear_dummy2();
- FieldMaskUtil::TrimMessage(mask, &trimmed_required_msg_2, options);
- EXPECT_EQ(trimmed_required_msg_2.DebugString(),
- required_msg_2.DebugString());
- FieldMaskUtil::FromString("required_message", &mask);
- required_msg_2.mutable_required_message()->set_dummy2(7890);
- trimmed_required_msg_2.mutable_required_message()->set_dummy2(7890);
- required_msg_2.clear_optional_message();
- FieldMaskUtil::TrimMessage(mask, &trimmed_required_msg_2, options);
- EXPECT_EQ(trimmed_required_msg_2.DebugString(),
- required_msg_2.DebugString());
- // Test trim required message with keep_required_fields is set false.
- FieldMaskUtil::FromString("required_message.dummy2", &mask);
- required_msg_2.mutable_required_message()->clear_a();
- required_msg_2.mutable_required_message()->clear_b();
- required_msg_2.mutable_required_message()->clear_c();
- options.set_keep_required_fields(false);
- FieldMaskUtil::TrimMessage(mask, &trimmed_required_msg_2, options);
- EXPECT_EQ(trimmed_required_msg_2.DebugString(),
- required_msg_2.DebugString());
- // Verify that trimming an empty message has no effect. In particular, fields
- // mentioned in the field mask should not be created or changed.
- TestAllTypes empty_msg;
- FieldMaskUtil::FromString(
- "optional_int32,optional_bytes,optional_nested_message.bb", &mask);
- FieldMaskUtil::TrimMessage(mask, &empty_msg);
- EXPECT_FALSE(empty_msg.has_optional_int32());
- EXPECT_FALSE(empty_msg.has_optional_bytes());
- EXPECT_FALSE(empty_msg.has_optional_nested_message());
- // Verify trimming of oneof fields. This should work as expected even if
- // multiple elements of the same oneof are included in the FieldMask.
- TestAllTypes oneof_msg;
- oneof_msg.set_oneof_uint32(11);
- FieldMaskUtil::FromString("oneof_uint32,oneof_nested_message.bb", &mask);
- FieldMaskUtil::TrimMessage(mask, &oneof_msg);
- EXPECT_EQ(11, oneof_msg.oneof_uint32());
- }
- } // namespace
- } // namespace util
- } // namespace protobuf
- } // namespace google
|