text:
// 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.

// Defines classes for field comparison.

#ifndef GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__
#define GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__

#include <map>
#include <string>

#include <google/protobuf/stubs/common.h>

namespace google {
namespace protobuf {

class Message;
class EnumValueDescriptor;
class FieldDescriptor;

namespace util {

class FieldContext;

// Base class specifying the interface for comparing protocol buffer fields.
// Regular users should consider using or subclassing DefaultFieldComparator
// rather than this interface.
// Currently, this does not support comparing unknown fields.
class LIBPROTOBUF_EXPORT FieldComparator {
 public:
  FieldComparator();
  virtual ~FieldComparator();

  enum ComparisonResult {
    SAME,       // Compared fields are equal. In case of comparing submessages,
                // user should not recursively compare their contents.
    DIFFERENT,  // Compared fields are different. In case of comparing
                // submessages, user should not recursively compare their
                // contents.
    RECURSE,    // Compared submessages need to be compared recursively.
                // FieldComparator does not specify the semantics of recursive
                // comparison. This value should not be returned for simple
                // values.
  };

  // Compares the values of a field in two protocol buffer messages.
  // Returns SAME or DIFFERENT for simple values, and SAME, DIFFERENT or RECURSE
  // for submessages. Returning RECURSE for fields not being submessages is
  // illegal.
  // In case the given FieldDescriptor points to a repeated field, the indices
  // need to be valid. Otherwise they should be ignored.
  //
  // FieldContext contains information about the specific instances of the
  // fields being compared, versus FieldDescriptor which only contains general
  // type information about the fields.
  virtual ComparisonResult Compare(
      const google::protobuf::Message& message_1,
      const google::protobuf::Message& message_2,
      const google::protobuf::FieldDescriptor* field,
      int index_1, int index_2,
      const google::protobuf::util::FieldContext* field_context) = 0;

 private:
  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldComparator);
};

// Basic implementation of FieldComparator.  Supports three modes of floating
// point value comparison: exact, approximate using MathUtil::AlmostEqual
// method, and arbitrarily precise using MathUtil::WithinFractionOrMargin.
class LIBPROTOBUF_EXPORT DefaultFieldComparator : public FieldComparator {
 public:
  enum FloatComparison {
     EXACT,               // Floats and doubles are compared exactly.
     APPROXIMATE,         // Floats and doubles are compared using the
                          // MathUtil::AlmostEqual method or
                          // MathUtil::WithinFractionOrMargin method.
     // TODO(ksroka): Introduce third value to differenciate uses of AlmostEqual
     //               and WithinFractionOrMargin.
  };

  // Creates new comparator with float comparison set to EXACT.
  DefaultFieldComparator();

  virtual ~DefaultFieldComparator();

  virtual ComparisonResult Compare(
      const google::protobuf::Message& message_1,
      const google::protobuf::Message& message_2,
      const google::protobuf::FieldDescriptor* field,
      int index_1, int index_2,
      const google::protobuf::util::FieldContext* field_context);

  void set_float_comparison(FloatComparison float_comparison) {
    float_comparison_ = float_comparison;
  }

  FloatComparison float_comparison() const {
    return float_comparison_;
  }

  // Set whether the FieldComparator shall treat floats or doubles that are both
  // NaN as equal (treat_nan_as_equal = true) or as different
  // (treat_nan_as_equal = false). Default is treating NaNs always as different.
  void set_treat_nan_as_equal(bool treat_nan_as_equal) {
    treat_nan_as_equal_ = treat_nan_as_equal;
  }

  bool treat_nan_as_equal() const {
    return treat_nan_as_equal_;
  }

  // Sets the fraction and margin for the float comparison of a given field.
  // Uses MathUtil::WithinFractionOrMargin to compare the values.
  //
  // REQUIRES: field->cpp_type == FieldDescriptor::CPPTYPE_DOUBLE or
  //           field->cpp_type == FieldDescriptor::CPPTYPE_FLOAT
  // REQUIRES: float_comparison_ == APPROXIMATE
  void SetFractionAndMargin(const FieldDescriptor* field, double fraction,
                            double margin);

  // Sets the fraction and margin for the float comparison of all float and
  // double fields, unless a field has been given a specific setting via
  // SetFractionAndMargin() above.
  // Uses MathUtil::WithinFractionOrMargin to compare the values.
  //
  // REQUIRES: float_comparison_ == APPROXIMATE
  void SetDefaultFractionAndMargin(double fraction, double margin);

 private:
  // Defines the tolerance for floating point comparison (fraction and margin).
  struct Tolerance {
    double fraction;
    double margin;
    Tolerance()
        : fraction(0.0),
          margin(0.0) {}
    Tolerance(double f, double m)
        : fraction(f),
          margin(m) {}
  };

  // Defines the map to store the tolerances for floating point comparison.
  typedef std::map<const FieldDescriptor*, Tolerance> ToleranceMap;

  // The following methods get executed when CompareFields is called for the
  // basic types (instead of submessages). They return true on success. One
  // can use ResultFromBoolean() to convert that boolean to a ComparisonResult
  // value.
  bool CompareBool(const google::protobuf::FieldDescriptor& field,
                   bool value_1, bool value_2) {
    return value_1 == value_2;
  }

  // Uses CompareDoubleOrFloat, a helper function used by both CompareDouble and
  // CompareFloat.
  bool CompareDouble(const google::protobuf::FieldDescriptor& field,
                     double value_1, double value_2);

  bool CompareEnum(const google::protobuf::FieldDescriptor& field,
                   const EnumValueDescriptor* value_1,
                   const EnumValueDescriptor* value_2);

  // Uses CompareDoubleOrFloat, a helper function used by both CompareDouble and
  // CompareFloat.
  bool CompareFloat(const google::protobuf::FieldDescriptor& field,
                    float value_1, float value_2);

  bool CompareInt32(const google::protobuf::FieldDescriptor& field,
                    int32 value_1, int32 value_2) {
    return value_1 == value_2;
  }

  bool CompareInt64(const google::protobuf::FieldDescriptor& field,
                    int64 value_1, int64 value_2) {
    return value_1 == value_2;
  }

  bool CompareString(const google::protobuf::FieldDescriptor& field,
                     const string& value_1, const string& value_2) {
    return value_1 == value_2;
  }

  bool CompareUInt32(const google::protobuf::FieldDescriptor& field,
                     uint32 value_1, uint32 value_2) {
    return value_1 == value_2;
  }

  bool CompareUInt64(const google::protobuf::FieldDescriptor& field,
                     uint64 value_1, uint64 value_2) {
    return value_1 == value_2;
  }

  // This function is used by CompareDouble and CompareFloat to avoid code
  // duplication. There are no checks done against types of the values passed,
  // but it's likely to fail if passed non-numeric arguments.
  template<typename T>
  bool CompareDoubleOrFloat(const google::protobuf::FieldDescriptor& field,
                            T value_1, T value_2);

  // Returns FieldComparator::SAME if boolean_result is true and
  // FieldComparator::DIFFERENT otherwise.
  ComparisonResult ResultFromBoolean(bool boolean_result) const;

  FloatComparison float_comparison_;

  // If true, floats and doubles that are both NaN are considered to be
  // equal. Otherwise, two floats or doubles that are NaN are considered to be
  // different.
  bool treat_nan_as_equal_;

  // True iff default_tolerance_ has been explicitly set.
  //
  // If false, then the default tolerance for floats and doubles is that which
  // is used by MathUtil::AlmostEquals().
  bool has_default_tolerance_;

  // Default float/double tolerance. Only meaningful if
  // has_default_tolerance_ == true.
  Tolerance default_tolerance_;

  // Field-specific float/double tolerances, which override any default for
  // those particular fields.
  ToleranceMap map_tolerance_;

  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DefaultFieldComparator);
};

}  // namespace util
}  // namespace protobuf

}  // namespace google
#endif  // GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__

mime_type: text/plain


text:
// 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", NULL));
  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", NULL));
  // FieldMask cannot be used to specify sub-fields of a repeated message.
  EXPECT_FALSE(FieldMaskUtil::GetFieldDescriptors(
      TestAllTypes::descriptor(), "repeated_nested_message.bb", NULL));
}

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;
  FieldMaskUtil::GetFieldMaskForAllFields<TestAllTypes::NestedMessage>(&mask);
  EXPECT_EQ(1, mask.paths_size());
  EXPECT_TRUE(FieldMaskUtil::IsPathInFieldMask("bb", mask));

  FieldMaskUtil::GetFieldMaskForAllFields<TestAllTypes>(&mask);
  EXPECT_EQ(76, 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));
}

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


text:
// 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.

// Author: ksroka@google.com (Krzysztof Sroka)

#include <google/protobuf/util/field_comparator.h>

#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/stubs/mathutil.h>
// This gtest header is put after mathutil.h intentionally. We have to do
// this because mathutil.h includes mathlimits.h which requires cmath not
// being included to compile on some versions of gcc:
//   https://github.com/google/protobuf/blob/818c5eee08840355d70d2f3bdf1a2f17986a5e70/src/google/protobuf/stubs/mathlimits.h#L48
// and the opensource version gtest.h header includes cmath transitively
// somehow.
#include <gtest/gtest.h>
namespace google {
namespace protobuf {
namespace util {
namespace {

using protobuf_unittest::TestAllTypes;

class DefaultFieldComparatorTest : public ::testing::Test {
 protected:
  void SetUp() {
    descriptor_ = TestAllTypes::descriptor();
  }

  const Descriptor* descriptor_;
  DefaultFieldComparator comparator_;
  TestAllTypes message_1_;
  TestAllTypes message_2_;
};

TEST_F(DefaultFieldComparatorTest, RecursesIntoGroup) {
  const FieldDescriptor* field =
      descriptor_->FindFieldByName("optionalgroup");
  EXPECT_EQ(FieldComparator::RECURSE,
            comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
}

TEST_F(DefaultFieldComparatorTest, RecursesIntoNestedMessage) {
  const FieldDescriptor* field =
      descriptor_->FindFieldByName("optional_nested_message");
  EXPECT_EQ(FieldComparator::RECURSE,
            comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
}

TEST_F(DefaultFieldComparatorTest, RecursesIntoForeignMessage) {
  const FieldDescriptor* field =
      descriptor_->FindFieldByName("optional_foreign_message");
  EXPECT_EQ(FieldComparator::RECURSE,
            comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
}

TEST_F(DefaultFieldComparatorTest, Int32Comparison) {
  const FieldDescriptor* field = descriptor_->FindFieldByName("optional_int32");
  message_1_.set_optional_int32(1);
  message_2_.set_optional_int32(1);

  EXPECT_EQ(FieldComparator::SAME,
            comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));

  message_2_.set_optional_int32(-1);
  EXPECT_EQ(FieldComparator::DIFFERENT,
            comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
}

TEST_F(DefaultFieldComparatorTest, Int64Comparison) {
  const FieldDescriptor* field = descriptor_->FindFieldByName("optional_int64");
  message_1_.set_optional_int64(1L);
  message_2_.set_optional_int64(1L);

  EXPECT_EQ(FieldComparator::SAME,
            comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));

  message_2_.set_optional_int64(-1L);
  EXPECT_EQ(FieldComparator::DIFFERENT,
            comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
}

TEST_F(DefaultFieldComparatorTest, UInt32Comparison) {
  const FieldDescriptor* field =
      descriptor_->FindFieldByName("optional_uint32");
  message_1_.set_optional_uint32(1);
  message_2_.set_optional_uint32(1);

  EXPECT_EQ(FieldComparator::SAME,
            comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));

  message_2_.set_optional_uint32(2);
  EXPECT_EQ(FieldComparator::DIFFERENT,
            comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
}

TEST_F(DefaultFieldComparatorTest, UInt64Comparison) {
  const FieldDescriptor* field =
      descriptor_->FindFieldByName("optional_uint64");
  message_1_.set_optional_uint64(1L);
  message_2_.set_optional_uint64(1L);

  EXPECT_EQ(FieldComparator::SAME,
            comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));

  message_2_.set_optional_uint64(2L);
  EXPECT_EQ(FieldComparator::DIFFERENT,
            comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
}

TEST_F(DefaultFieldComparatorTest, BooleanComparison) {
  const FieldDescriptor* field =
      descriptor_->FindFieldByName("optional_bool");
  message_1_.set_optional_bool(true);
  message_2_.set_optional_bool(true);

  EXPECT_EQ(FieldComparator::SAME,
            comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));

  message_2_.set_optional_bool(false);
  EXPECT_EQ(FieldComparator::DIFFERENT,
            comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
}

TEST_F(DefaultFieldComparatorTest, EnumComparison) {
  const FieldDescriptor* field =
      descriptor_->FindFieldByName("optional_nested_enum");
  message_1_.set_optional_nested_enum(TestAllTypes::BAR);
  message_2_.set_optional_nested_enum(TestAllTypes::BAR);

  EXPECT_EQ(FieldComparator::SAME,
            comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));

  message_2_.set_optional_nested_enum(TestAllTypes::BAZ);
  EXPECT_EQ(FieldComparator::DIFFERENT,
            comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
}

TEST_F(DefaultFieldComparatorTest, StringComparison) {
  const FieldDescriptor* field =
      descriptor_->FindFieldByName("optional_string");
  message_1_.set_optional_string("foo");
  message_2_.set_optional_string("foo");

  EXPECT_EQ(FieldComparator::SAME,
            comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));

  message_2_.set_optional_string("bar");
  EXPECT_EQ(FieldComparator::DIFFERENT,
            comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL));
}

TEST_F(DefaultFieldComparatorTest, FloatingPointComparisonExact) {
  const FieldDescriptor* field_float =
      descriptor_->FindFieldByName("optional_float");
  const FieldDescriptor* field_double =
      descriptor_->FindFieldByName("optional_double");

  message_1_.set_optional_float(0.1f);
  message_2_.set_optional_float(0.1f);
  message_1_.set_optional_double(0.1);
  message_2_.set_optional_double(0.1);

  EXPECT_EQ(FieldComparator::SAME,
            comparator_.Compare(message_1_, message_2_,
                                field_float, -1, -1, NULL));
  EXPECT_EQ(FieldComparator::SAME,
            comparator_.Compare(message_1_, message_2_,
                                field_double, -1, -1, NULL));

  message_2_.set_optional_float(0.2f);
  message_2_.set_optional_double(0.2);

  EXPECT_EQ(FieldComparator::DIFFERENT,
            comparator_.Compare(message_1_, message_2_,
                                field_float, -1, -1, NULL));
  EXPECT_EQ(FieldComparator::DIFFERENT,
            comparator_.Compare(message_1_, message_2_,
                                field_double, -1, -1, NULL));
}

TEST_F(DefaultFieldComparatorTest, FloatingPointComparisonApproximate) {
  const FieldDescriptor* field_float =
      descriptor_->FindFieldByName("optional_float");
  const FieldDescriptor* field_double =
      descriptor_->FindFieldByName("optional_double");

  message_1_.set_optional_float(2.300005f);
  message_2_.set_optional_float(2.300006f);
  message_1_.set_optional_double(2.3000000000000003);
  message_2_.set_optional_double(2.3000000000000007);

  // Approximate comparison depends on MathUtil, so we assert on MathUtil
  // results first to check if that's where the failure was introduced.
  ASSERT_NE(message_1_.optional_float(), message_2_.optional_float());
  ASSERT_NE(message_1_.optional_double(), message_2_.optional_double());
  ASSERT_TRUE(MathUtil::AlmostEquals(message_1_.optional_float(),
                                     message_2_.optional_float()));
  ASSERT_TRUE(MathUtil::AlmostEquals(message_1_.optional_double(),
                                     message_2_.optional_double()));

  // DefaultFieldComparator's default float comparison mode is EXACT.
  ASSERT_EQ(DefaultFieldComparator::EXACT, comparator_.float_comparison());
  EXPECT_EQ(FieldComparator::DIFFERENT,
            comparator_.Compare(message_1_, message_2_,
                                field_float, -1, -1, NULL));
  EXPECT_EQ(FieldComparator::DIFFERENT,
            comparator_.Compare(message_1_, message_2_,
                                field_double, -1, -1, NULL));

  comparator_.set_float_comparison(DefaultFieldComparator::APPROXIMATE);

  EXPECT_EQ(FieldComparator::SAME,
            comparator_.Compare(message_1_, message_2_,
                                field_float, -1, -1, NULL));
  EXPECT_EQ(FieldComparator::SAME,
            comparator_.Compare(message_1_, message_2_,
                                field_double, -1, -1, NULL));
}

TEST_F(DefaultFieldComparatorTest, FloatingPointComparisonTreatNaNsAsEqual) {
  const FieldDescriptor* field_float =
      descriptor_->FindFieldByName("optional_float");
  const FieldDescriptor* field_double =
      descriptor_->FindFieldByName("optional_double");

  message_1_.set_optional_float(MathLimits<float>::kNaN);
  message_2_.set_optional_float(MathLimits<float>::kNaN);
  message_1_.set_optional_double(MathLimits<double>::kNaN);
  message_2_.set_optional_double(MathLimits<double>::kNaN);

  // DefaultFieldComparator's default float comparison mode is EXACT with
  // treating NaNs as different.
  ASSERT_EQ(DefaultFieldComparator::EXACT, comparator_.float_comparison());
  ASSERT_EQ(false, comparator_.treat_nan_as_equal());
  EXPECT_EQ(FieldComparator::DIFFERENT,
            comparator_.Compare(message_1_, message_2_,
                                field_float, -1, -1, NULL));
  EXPECT_EQ(FieldComparator::DIFFERENT,
            comparator_.Compare(message_1_, message_2_,
                                field_double, -1, -1, NULL));
  comparator_.set_float_comparison(DefaultFieldComparator::APPROXIMATE);
  EXPECT_EQ(FieldComparator::DIFFERENT,
            comparator_.Compare(message_1_, message_2_,
                                field_float, -1, -1, NULL));
  EXPECT_EQ(FieldComparator::DIFFERENT,
            comparator_.Compare(message_1_, message_2_,
                                field_double, -1, -1, NULL));

  comparator_.set_treat_nan_as_equal(true);
  ASSERT_EQ(true, comparator_.treat_nan_as_equal());
  comparator_.set_float_comparison(DefaultFieldComparator::EXACT);
  EXPECT_EQ(FieldComparator::SAME,
            comparator_.Compare(message_1_, message_2_,
                                field_float, -1, -1, NULL));
  EXPECT_EQ(FieldComparator::SAME,
            comparator_.Compare(message_1_, message_2_,
                                field_double, -1, -1, NULL));
  comparator_.set_float_comparison(DefaultFieldComparator::APPROXIMATE);
  EXPECT_EQ(FieldComparator::SAME,
            comparator_.Compare(message_1_, message_2_,
                                field_float, -1, -1, NULL));
  EXPECT_EQ(FieldComparator::SAME,
            comparator_.Compare(message_1_, message_2_,
                                field_double, -1, -1, NULL));
}

TEST_F(DefaultFieldComparatorTest,
       FloatingPointComparisonWithinFractionOrMargin) {
  const FieldDescriptor* field_float =
      descriptor_->FindFieldByName("optional_float");
  const FieldDescriptor* field_double =
      descriptor_->FindFieldByName("optional_double");

  message_1_.set_optional_float(100.0f);
  message_2_.set_optional_float(109.9f);
  message_1_.set_optional_double(100.0);
  message_2_.set_optional_double(109.9);

  comparator_.set_float_comparison(DefaultFieldComparator::APPROXIMATE);
  EXPECT_EQ(FieldComparator::DIFFERENT,
            comparator_.Compare(message_1_, message_2_,
                                field_float, -1, -1, NULL));
  EXPECT_EQ(FieldComparator::DIFFERENT,
            comparator_.Compare(message_1_, message_2_,
                                field_double, -1, -1, NULL));

  // Should fail since the fraction is too low.
  comparator_.SetFractionAndMargin(field_float, 0.01, 0.0);
  comparator_.SetFractionAndMargin(field_double, 0.01, 0.0);

  EXPECT_EQ(FieldComparator::DIFFERENT,
            comparator_.Compare(message_1_, message_2_,
                                field_float, -1, -1, NULL));
  EXPECT_EQ(FieldComparator::DIFFERENT,
            comparator_.Compare(message_1_, message_2_,
                                field_double, -1, -1, NULL));

  // Should fail since the margin is too low.
  comparator_.SetFractionAndMargin(field_float, 0.0, 9.0);
  comparator_.SetFractionAndMargin(field_double, 0.0, 9.0);
  EXPECT_EQ(FieldComparator::DIFFERENT,
            comparator_.Compare(message_1_, message_2_,
                                field_float, -1, -1, NULL));
  EXPECT_EQ(FieldComparator::DIFFERENT,
            comparator_.Compare(message_1_, message_2_,
                                field_double, -1, -1, NULL));

  // Should succeed since the fraction is high enough.
  comparator_.SetFractionAndMargin(field_float, 0.2, 0.0);
  comparator_.SetFractionAndMargin(field_double, 0.2, 0.0);
  EXPECT_EQ(FieldComparator::SAME,
            comparator_.Compare(message_1_, message_2_,
                                field_float, -1, -1, NULL));
  EXPECT_EQ(FieldComparator::SAME,
            comparator_.Compare(message_1_, message_2_,
                                field_double, -1, -1, NULL));

  // Should succeed since the margin is high enough.
  comparator_.SetFractionAndMargin(field_float, 0.0, 10.0);
  comparator_.SetFractionAndMargin(field_double, 0.0, 10.0);
  EXPECT_EQ(FieldComparator::SAME,
            comparator_.Compare(message_1_, message_2_,
                                field_float, -1, -1, NULL));
  EXPECT_EQ(FieldComparator::SAME,
            comparator_.Compare(message_1_, message_2_,
                                field_double, -1, -1, NULL));

  // Setting values for one of the fields should not affect the other.
  comparator_.SetFractionAndMargin(field_double, 0.0, 0.0);
  EXPECT_EQ(FieldComparator::SAME,
            comparator_.Compare(message_1_, message_2_,
                                field_float, -1, -1, NULL));
  EXPECT_EQ(FieldComparator::DIFFERENT,
            comparator_.Compare(message_1_, message_2_,
                                field_double, -1, -1, NULL));

  // +inf should be equal even though they are not technically within margin or
  // fraction.
  message_1_.set_optional_float(std::numeric_limits<float>::infinity());
  message_2_.set_optional_float(std::numeric_limits<float>::infinity());
  message_1_.set_optional_double(std::numeric_limits<double>::infinity());
  message_2_.set_optional_double(std::numeric_limits<double>::infinity());
  comparator_.SetFractionAndMargin(field_float, 0.0, 0.0);
  comparator_.SetFractionAndMargin(field_double, 0.0, 0.0);
  EXPECT_EQ(FieldComparator::SAME,
            comparator_.Compare(message_1_, message_2_,
                                field_float, -1, -1, NULL));
  EXPECT_EQ(FieldComparator::SAME,
            comparator_.Compare(message_1_, message_2_,
                                field_double, -1, -1, NULL));

  // -inf should be equal even though they are not technically within margin or
  // fraction.
  message_1_.set_optional_float(-std::numeric_limits<float>::infinity());
  message_2_.set_optional_float(-std::numeric_limits<float>::infinity());
  message_1_.set_optional_double(-std::numeric_limits<double>::infinity());
  message_2_.set_optional_double(-std::numeric_limits<double>::infinity());
  comparator_.SetFractionAndMargin(field_float, 0.0, 0.0);
  comparator_.SetFractionAndMargin(field_double, 0.0, 0.0);
  EXPECT_EQ(FieldComparator::SAME,
            comparator_.Compare(message_1_, message_2_,
                                field_float, -1, -1, NULL));
  EXPECT_EQ(FieldComparator::SAME,
            comparator_.Compare(message_1_, message_2_,
                                field_double, -1, -1, NULL));
}

TEST_F(DefaultFieldComparatorTest,
       FloatingPointComparisonWithinDefaultFractionOrMargin) {
  const FieldDescriptor* field_float =
      descriptor_->FindFieldByName("optional_float");
  const FieldDescriptor* field_double =
      descriptor_->FindFieldByName("optional_double");

  message_1_.set_optional_float(100.0f);
  message_2_.set_optional_float(109.9f);
  message_1_.set_optional_double(100.0);
  message_2_.set_optional_double(109.9);

  comparator_.set_float_comparison(DefaultFieldComparator::APPROXIMATE);
  EXPECT_EQ(FieldComparator::DIFFERENT,
            comparator_.Compare(message_1_, message_2_,
                                field_float, -1, -1, NULL));
  EXPECT_EQ(FieldComparator::DIFFERENT,
            comparator_.Compare(message_1_, message_2_,
                                field_double, -1, -1, NULL));

  // Set default fraction and margin.
  comparator_.SetDefaultFractionAndMargin(0.01, 0.0);

  // Float comparisons should fail since the fraction is too low.
  EXPECT_EQ(FieldComparator::DIFFERENT,
            comparator_.Compare(message_1_, message_2_,
                                field_float, -1, -1, NULL));
  EXPECT_EQ(FieldComparator::DIFFERENT,
            comparator_.Compare(message_1_, message_2_,
                                field_double, -1, -1, NULL));

  // Set field-specific fraction and margin for one field (field_float) but not
  // the other (field_double)
  comparator_.SetFractionAndMargin(field_float, 0.2, 0.0);

  // The field with the override should succeed, since its field-specific
  // fraction is high enough.
  EXPECT_EQ(FieldComparator::SAME,
            comparator_.Compare(message_1_, message_2_,
                                field_float, -1, -1, NULL));
  // The field with no override should fail, since the default fraction is too
  // low
  EXPECT_EQ(FieldComparator::DIFFERENT,
            comparator_.Compare(message_1_, message_2_,
                                field_double, -1, -1, NULL));

  // Set the default fraction and margin high enough so that fields that use
  // the default should succeed
  comparator_.SetDefaultFractionAndMargin(0.2, 0.0);
  EXPECT_EQ(FieldComparator::SAME,
            comparator_.Compare(message_1_, message_2_,
                                field_double, -1, -1, NULL));

  // The field with an override should still be OK
  EXPECT_EQ(FieldComparator::SAME,
            comparator_.Compare(message_1_, message_2_,
                                field_float, -1, -1, NULL));

  // Set fraction and margin for the field with an override to be too low
  comparator_.SetFractionAndMargin(field_float, 0.01, 0.0);

  // Now our default is high enough but field_float's override is too low.
  EXPECT_EQ(FieldComparator::DIFFERENT,
            comparator_.Compare(message_1_, message_2_,
                                field_float, -1, -1, NULL));
  EXPECT_EQ(FieldComparator::SAME,
            comparator_.Compare(message_1_, message_2_,
                                field_double, -1, -1, NULL));
}

// Simple test checking whether we compare values at correct indices.
TEST_F(DefaultFieldComparatorTest, RepeatedFieldComparison) {
  const FieldDescriptor* field =
      descriptor_->FindFieldByName("repeated_string");

  message_1_.add_repeated_string("foo");
  message_1_.add_repeated_string("bar");
  message_2_.add_repeated_string("bar");
  message_2_.add_repeated_string("baz");

  EXPECT_EQ(FieldComparator::DIFFERENT,
            comparator_.Compare(message_1_, message_2_, field, 0, 0, NULL));
  EXPECT_EQ(FieldComparator::DIFFERENT,
            comparator_.Compare(message_1_, message_2_, field, 1, 1, NULL));
  EXPECT_EQ(FieldComparator::SAME,
            comparator_.Compare(message_1_, message_2_, field, 1, 0, NULL));
}

}  // namespace util
}  // namespace protobuf
}  // namespace
}  // namespace google


text:
// 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/json_util.h>

#include <list>
#include <string>

#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/descriptor_database.h>
#include <google/protobuf/dynamic_message.h>
#include <google/protobuf/util/internal/testdata/maps.pb.h>
#include <google/protobuf/util/json_format_proto3.pb.h>
#include <google/protobuf/util/type_resolver.h>
#include <google/protobuf/util/type_resolver_util.h>
#include <gtest/gtest.h>

namespace google {
namespace protobuf {
namespace util {
namespace {

using proto3::FOO;
using proto3::BAR;
using proto3::TestMessage;
using proto3::TestMap;
using proto3::TestOneof;
using google::protobuf::testing::MapIn;

static const char kTypeUrlPrefix[] = "type.googleapis.com";

// As functions defined in json_util.h are just thin wrappers around the
// JSON conversion code in //net/proto2/util/converter, in this test we
// only cover some very basic cases to make sure the wrappers have forwarded
// parameters to the underlying implementation correctly. More detailed
// tests are contained in the //net/proto2/util/converter directory.
class JsonUtilTest : public ::testing::Test {
 protected:
  JsonUtilTest() {
  }

  string ToJson(const Message& message, const JsonPrintOptions& options) {
    string result;
    GOOGLE_CHECK_OK(MessageToJsonString(message, &result, options));
    return result;
  }

  bool FromJson(const string& json, Message* message,
                const JsonParseOptions& options) {
    return JsonStringToMessage(json, message, options).ok();
  }

  bool FromJson(const string& json, Message* message) {
    return FromJson(json, message, JsonParseOptions());
  }

  google::protobuf::scoped_ptr<TypeResolver> resolver_;
};

TEST_F(JsonUtilTest, TestWhitespaces) {
  TestMessage m;
  m.mutable_message_value();

  JsonPrintOptions options;
  EXPECT_EQ("{\"messageValue\":{}}", ToJson(m, options));
  options.add_whitespace = true;
  EXPECT_EQ(
      "{\n"
      " \"messageValue\": {}\n"
      "}\n",
      ToJson(m, options));
}

TEST_F(JsonUtilTest, TestDefaultValues) {
  TestMessage m;
  JsonPrintOptions options;
  EXPECT_EQ("{}", ToJson(m, options));
  options.always_print_primitive_fields = true;
  EXPECT_EQ(
      "{\"boolValue\":false,"
      "\"int32Value\":0,"
      "\"int64Value\":\"0\","
      "\"uint32Value\":0,"
      "\"uint64Value\":\"0\","
      "\"floatValue\":0,"
      "\"doubleValue\":0,"
      "\"stringValue\":\"\","
      "\"bytesValue\":\"\","
      "\"enumValue\":\"FOO\","
      "\"repeatedBoolValue\":[],"
      "\"repeatedInt32Value\":[],"
      "\"repeatedInt64Value\":[],"
      "\"repeatedUint32Value\":[],"
      "\"repeatedUint64Value\":[],"
      "\"repeatedFloatValue\":[],"
      "\"repeatedDoubleValue\":[],"
      "\"repeatedStringValue\":[],"
      "\"repeatedBytesValue\":[],"
      "\"repeatedEnumValue\":[],"
      "\"repeatedMessageValue\":[]"
      "}",
      ToJson(m, options));

  options.always_print_primitive_fields = true;
  m.set_string_value("i am a test string value");
  m.set_bytes_value("i am a test bytes value");
  EXPECT_EQ(
      "{\"boolValue\":false,"
      "\"int32Value\":0,"
      "\"int64Value\":\"0\","
      "\"uint32Value\":0,"
      "\"uint64Value\":\"0\","
      "\"floatValue\":0,"
      "\"doubleValue\":0,"
      "\"stringValue\":\"i am a test string value\","
      "\"bytesValue\":\"aSBhbSBhIHRlc3QgYnl0ZXMgdmFsdWU=\","
      "\"enumValue\":\"FOO\","
      "\"repeatedBoolValue\":[],"
      "\"repeatedInt32Value\":[],"
      "\"repeatedInt64Value\":[],"
      "\"repeatedUint32Value\":[],"
      "\"repeatedUint64Value\":[],"
      "\"repeatedFloatValue\":[],"
      "\"repeatedDoubleValue\":[],"
      "\"repeatedStringValue\":[],"
      "\"repeatedBytesValue\":[],"
      "\"repeatedEnumValue\":[],"
      "\"repeatedMessageValue\":[]"
      "}",
      ToJson(m, options));

  options.preserve_proto_field_names = true;
  m.set_string_value("i am a test string value");
  m.set_bytes_value("i am a test bytes value");
  EXPECT_EQ(
      "{\"bool_value\":false,"
      "\"int32_value\":0,"
      "\"int64_value\":\"0\","
      "\"uint32_value\":0,"
      "\"uint64_value\":\"0\","
      "\"float_value\":0,"
      "\"double_value\":0,"
      "\"string_value\":\"i am a test string value\","
      "\"bytes_value\":\"aSBhbSBhIHRlc3QgYnl0ZXMgdmFsdWU=\","
      "\"enum_value\":\"FOO\","
      "\"repeated_bool_value\":[],"
      "\"repeated_int32_value\":[],"
      "\"repeated_int64_value\":[],"
      "\"repeated_uint32_value\":[],"
      "\"repeated_uint64_value\":[],"
      "\"repeated_float_value\":[],"
      "\"repeated_double_value\":[],"
      "\"repeated_string_value\":[],"
      "\"repeated_bytes_value\":[],"
      "\"repeated_enum_value\":[],"
      "\"repeated_message_value\":[]"
      "}",
      ToJson(m, options));
}

TEST_F(JsonUtilTest, TestPreserveProtoFieldNames) {
  TestMessage m;
  m.mutable_message_value();

  JsonPrintOptions options;
  options.preserve_proto_field_names = true;
  EXPECT_EQ("{\"message_value\":{}}", ToJson(m, options));
}

TEST_F(JsonUtilTest, TestAlwaysPrintEnumsAsInts) {
  TestMessage orig;
  orig.set_enum_value(proto3::BAR);
  orig.add_repeated_enum_value(proto3::FOO);
  orig.add_repeated_enum_value(proto3::BAR);

  JsonPrintOptions print_options;
  print_options.always_print_enums_as_ints = true;

  string expected_json = "{\"enumValue\":1,\"repeatedEnumValue\":[0,1]}";
  EXPECT_EQ(expected_json, ToJson(orig, print_options));

  TestMessage parsed;
  JsonParseOptions parse_options;
  ASSERT_TRUE(FromJson(expected_json, &parsed, parse_options));

  EXPECT_EQ(proto3::BAR, parsed.enum_value());
  EXPECT_EQ(2, parsed.repeated_enum_value_size());
  EXPECT_EQ(proto3::FOO, parsed.repeated_enum_value(0));
  EXPECT_EQ(proto3::BAR, parsed.repeated_enum_value(1));
}

TEST_F(JsonUtilTest, ParseMessage) {
  // Some random message but good enough to verify that the parsing warpper
  // functions are working properly.
  string input =
      "{\n"
      "  \"int32Value\": 1024,\n"
      "  \"repeatedInt32Value\": [1, 2],\n"
      "  \"messageValue\": {\n"
      "    \"value\": 2048\n"
      "  },\n"
      "  \"repeatedMessageValue\": [\n"
      "    {\"value\": 40}, {\"value\": 96}\n"
      "  ]\n"
      "}\n";
  JsonParseOptions options;
  TestMessage m;
  ASSERT_TRUE(FromJson(input, &m, options));
  EXPECT_EQ(1024, m.int32_value());
  ASSERT_EQ(2, m.repeated_int32_value_size());
  EXPECT_EQ(1, m.repeated_int32_value(0));
  EXPECT_EQ(2, m.repeated_int32_value(1));
  EXPECT_EQ(2048, m.message_value().value());
  ASSERT_EQ(2, m.repeated_message_value_size());
  EXPECT_EQ(40, m.repeated_message_value(0).value());
  EXPECT_EQ(96, m.repeated_message_value(1).value());
}

TEST_F(JsonUtilTest, ParseMap) {
  TestMap message;
  (*message.mutable_string_map())["hello"] = 1234;
  JsonPrintOptions print_options;
  JsonParseOptions parse_options;
  EXPECT_EQ("{\"stringMap\":{\"hello\":1234}}", ToJson(message, print_options));
  TestMap other;
  ASSERT_TRUE(FromJson(ToJson(message, print_options), &other, parse_options));
  EXPECT_EQ(message.DebugString(), other.DebugString());
}

TEST_F(JsonUtilTest, ParsePrimitiveMapIn) {
  MapIn message;
  JsonPrintOptions print_options;
  print_options.always_print_primitive_fields = true;
  JsonParseOptions parse_options;
  EXPECT_EQ("{\"other\":\"\",\"things\":[],\"mapInput\":{}}",
            ToJson(message, print_options));
  MapIn other;
  ASSERT_TRUE(FromJson(ToJson(message, print_options), &other, parse_options));
  EXPECT_EQ(message.DebugString(), other.DebugString());
}

TEST_F(JsonUtilTest, PrintPrimitiveOneof) {
  TestOneof message;
  JsonPrintOptions options;
  options.always_print_primitive_fields = true;
  message.mutable_oneof_message_value();
  EXPECT_EQ("{\"oneofMessageValue\":{\"value\":0}}", ToJson(message, options));

  message.set_oneof_int32_value(1);
  EXPECT_EQ("{\"oneofInt32Value\":1}", ToJson(message, options));
}

TEST_F(JsonUtilTest, TestParseIgnoreUnknownFields) {
  TestMessage m;
  JsonParseOptions options;
  options.ignore_unknown_fields = true;
  EXPECT_TRUE(FromJson("{\"unknownName\":0}", &m, options));
}

TEST_F(JsonUtilTest, TestParseErrors) {
  TestMessage m;
  JsonParseOptions options;
  // Parsing should fail if the field name can not be recognized.
  EXPECT_FALSE(FromJson("{\"unknownName\":0}", &m, options));
  // Parsing should fail if the value is invalid.
  EXPECT_FALSE(FromJson("{\"int32Value\":2147483648}", &m, options));
}

TEST_F(JsonUtilTest, TestDynamicMessage) {
  // Some random message but good enough to test the wrapper functions.
  string input =
      "{\n"
      "  \"int32Value\": 1024,\n"
      "  \"repeatedInt32Value\": [1, 2],\n"
      "  \"messageValue\": {\n"
      "    \"value\": 2048\n"
      "  },\n"
      "  \"repeatedMessageValue\": [\n"
      "    {\"value\": 40}, {\"value\": 96}\n"
      "  ]\n"
      "}\n";

  // Create a new DescriptorPool with the same protos as the generated one.
  DescriptorPoolDatabase database(*DescriptorPool::generated_pool());
  DescriptorPool pool(&database);
  // A dynamic version of the test proto.
  DynamicMessageFactory factory;
  google::protobuf::scoped_ptr<Message> message(factory.GetPrototype(
      pool.FindMessageTypeByName("proto3.TestMessage"))->New());
  EXPECT_TRUE(FromJson(input, message.get()));

  // Convert to generated message for easy inspection.
  TestMessage generated;
  EXPECT_TRUE(generated.ParseFromString(message->SerializeAsString()));
  EXPECT_EQ(1024, generated.int32_value());
  ASSERT_EQ(2, generated.repeated_int32_value_size());
  EXPECT_EQ(1, generated.repeated_int32_value(0));
  EXPECT_EQ(2, generated.repeated_int32_value(1));
  EXPECT_EQ(2048, generated.message_value().value());
  ASSERT_EQ(2, generated.repeated_message_value_size());
  EXPECT_EQ(40, generated.repeated_message_value(0).value());
  EXPECT_EQ(96, generated.repeated_message_value(1).value());

  JsonOptions options;
  EXPECT_EQ(ToJson(generated, options), ToJson(*message, options));
}

typedef std::pair<char*, int> Segment;
// A ZeroCopyOutputStream that writes to multiple buffers.
class SegmentedZeroCopyOutputStream : public io::ZeroCopyOutputStream {
 public:
  explicit SegmentedZeroCopyOutputStream(std::list<Segment> segments)
      : segments_(segments), last_segment_(static_cast<char*>(NULL), 0), byte_count_(0) {}

  virtual bool Next(void** buffer, int* length) {
    if (segments_.empty()) {
      return false;
    }
    last_segment_ = segments_.front();
    segments_.pop_front();
    *buffer = last_segment_.first;
    *length = last_segment_.second;
    byte_count_ += *length;
    return true;
  }

  virtual void BackUp(int length) {
    GOOGLE_CHECK(length <= last_segment_.second);
    segments_.push_front(
        Segment(last_segment_.first + last_segment_.second - length, length));
    last_segment_ = Segment(last_segment_.first, last_segment_.second - length);
    byte_count_ -= length;
  }

  virtual int64 ByteCount() const { return byte_count_; }

 private:
  std::list<Segment> segments_;
  Segment last_segment_;
  int64 byte_count_;
};

// This test splits the output buffer and also the input data into multiple
// segments and checks that the implementation of ZeroCopyStreamByteSink
// handles all possible cases correctly.
TEST(ZeroCopyStreamByteSinkTest, TestAllInputOutputPatterns) {
  static const int kOutputBufferLength = 10;
  // An exhaustive test takes too long, skip some combinations to make the test
  // run faster.
  static const int kSkippedPatternCount = 7;

  char buffer[kOutputBufferLength];
  for (int split_pattern = 0; split_pattern < (1 << (kOutputBufferLength - 1));
       split_pattern += kSkippedPatternCount) {
    // Split the buffer into small segments according to the split_pattern.
    std::list<Segment> segments;
    int segment_start = 0;
    for (int i = 0; i < kOutputBufferLength - 1; ++i) {
      if (split_pattern & (1 << i)) {
        segments.push_back(
            Segment(buffer + segment_start, i - segment_start + 1));
        segment_start = i + 1;
      }
    }
    segments.push_back(
        Segment(buffer + segment_start, kOutputBufferLength - segment_start));

    // Write exactly 10 bytes through the ByteSink.
    string input_data = "0123456789";
    for (int input_pattern = 0; input_pattern < (1 << (input_data.size() - 1));
         input_pattern += kSkippedPatternCount) {
      memset(buffer, 0, sizeof(buffer));
      {
        SegmentedZeroCopyOutputStream output_stream(segments);
        internal::ZeroCopyStreamByteSink byte_sink(&output_stream);
        int start = 0;
        for (int j = 0; j < input_data.length() - 1; ++j) {
          if (input_pattern & (1 << j)) {
            byte_sink.Append(&input_data[start], j - start + 1);
            start = j + 1;
          }
        }
        byte_sink.Append(&input_data[start], input_data.length() - start);
      }
      EXPECT_EQ(input_data, string(buffer, input_data.length()));
    }

    // Write only 9 bytes through the ByteSink.
    input_data = "012345678";
    for (int input_pattern = 0; input_pattern < (1 << (input_data.size() - 1));
         input_pattern += kSkippedPatternCount) {
      memset(buffer, 0, sizeof(buffer));
      {
        SegmentedZeroCopyOutputStream output_stream(segments);
        internal::ZeroCopyStreamByteSink byte_sink(&output_stream);
        int start = 0;
        for (int j = 0; j < input_data.length() - 1; ++j) {
          if (input_pattern & (1 << j)) {
            byte_sink.Append(&input_data[start], j - start + 1);
            start = j + 1;
          }
        }
        byte_sink.Append(&input_data[start], input_data.length() - start);
      }
      EXPECT_EQ(input_data, string(buffer, input_data.length()));
      EXPECT_EQ(0, buffer[input_data.length()]);
    }

    // Write 11 bytes through the ByteSink. The extra byte will just
    // be ignored.
    input_data = "0123456789A";
    for (int input_pattern = 0; input_pattern < (1 << (input_data.size() - 1));
         input_pattern += kSkippedPatternCount) {
      memset(buffer, 0, sizeof(buffer));
      {
        SegmentedZeroCopyOutputStream output_stream(segments);
        internal::ZeroCopyStreamByteSink byte_sink(&output_stream);
        int start = 0;
        for (int j = 0; j < input_data.length() - 1; ++j) {
          if (input_pattern & (1 << j)) {
            byte_sink.Append(&input_data[start], j - start + 1);
            start = j + 1;
          }
        }
        byte_sink.Append(&input_data[start], input_data.length() - start);
      }
      EXPECT_EQ(input_data.substr(0, kOutputBufferLength),
                string(buffer, kOutputBufferLength));
    }
  }
}

}  // namespace
}  // namespace util
}  // namespace protobuf
}  // namespace google