diff options
author | aa <aa@chromium.org> | 2014-10-14 18:18:00 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-10-15 01:18:15 +0000 |
commit | 6b5d1a9be85123b55109f92268a6bf31157f2b88 (patch) | |
tree | 8cf52182dd2e4738216fcf9ff178dec4fae1ccdb /mojo | |
parent | 204bacbab4ef7aae299f673705e31e51478332fa (diff) | |
download | chromium_src-6b5d1a9be85123b55109f92268a6bf31157f2b88.zip chromium_src-6b5d1a9be85123b55109f92268a6bf31157f2b88.tar.gz chromium_src-6b5d1a9be85123b55109f92268a6bf31157f2b88.tar.bz2 |
Add Equals() to mojom structs and related types.
BUG=
Review URL: https://codereview.chromium.org/649633003
Cr-Commit-Position: refs/heads/master@{#299614}
Diffstat (limited to 'mojo')
-rw-r--r-- | mojo/edk/mojo_edk.gyp | 1 | ||||
-rw-r--r-- | mojo/public/cpp/bindings/array.h | 13 | ||||
-rw-r--r-- | mojo/public/cpp/bindings/lib/bindings_internal.h | 29 | ||||
-rw-r--r-- | mojo/public/cpp/bindings/lib/map_internal.h | 2 | ||||
-rw-r--r-- | mojo/public/cpp/bindings/lib/template_util.h | 9 | ||||
-rw-r--r-- | mojo/public/cpp/bindings/map.h | 18 | ||||
-rw-r--r-- | mojo/public/cpp/bindings/struct_ptr.h | 11 | ||||
-rw-r--r-- | mojo/public/cpp/bindings/tests/BUILD.gn | 1 | ||||
-rw-r--r-- | mojo/public/cpp/bindings/tests/equals_unittest.cc | 120 | ||||
-rw-r--r-- | mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl | 2 | ||||
-rw-r--r-- | mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl | 9 |
11 files changed, 214 insertions, 1 deletions
diff --git a/mojo/edk/mojo_edk.gyp b/mojo/edk/mojo_edk.gyp index 98c493b..58dae52 100644 --- a/mojo/edk/mojo_edk.gyp +++ b/mojo/edk/mojo_edk.gyp @@ -85,6 +85,7 @@ '../public/cpp/bindings/tests/buffer_unittest.cc', '../public/cpp/bindings/tests/connector_unittest.cc', '../public/cpp/bindings/tests/container_test_util.cc', + '../public/cpp/bindings/tests/equals_unittest.cc', '../public/cpp/bindings/tests/handle_passing_unittest.cc', '../public/cpp/bindings/tests/interface_ptr_unittest.cc', '../public/cpp/bindings/tests/map_unittest.cc', diff --git a/mojo/public/cpp/bindings/array.h b/mojo/public/cpp/bindings/array.h index 966cf31..2544abb 100644 --- a/mojo/public/cpp/bindings/array.h +++ b/mojo/public/cpp/bindings/array.h @@ -12,6 +12,7 @@ #include <vector> #include "mojo/public/cpp/bindings/lib/array_internal.h" +#include "mojo/public/cpp/bindings/lib/bindings_internal.h" #include "mojo/public/cpp/bindings/lib/template_util.h" #include "mojo/public/cpp/bindings/type_converter.h" @@ -107,6 +108,18 @@ class Array { return result.Pass(); } + bool Equals(const Array& other) const { + if (is_null() != other.is_null()) + return false; + if (size() != other.size()) + return false; + for (size_t i = 0; i < size(); ++i) { + if (!internal::ValueTraits<T>::Equals(at(i), other.at(i))) + return false; + } + return true; + } + private: typedef std::vector<StorageType> Array::*Testable; diff --git a/mojo/public/cpp/bindings/lib/bindings_internal.h b/mojo/public/cpp/bindings/lib/bindings_internal.h index df3c620..ec70d37 100644 --- a/mojo/public/cpp/bindings/lib/bindings_internal.h +++ b/mojo/public/cpp/bindings/lib/bindings_internal.h @@ -12,6 +12,12 @@ namespace mojo { class String; +template <typename T> +class Array; + +template <typename K, typename V> +class Map; + namespace internal { template <typename T> class Array_Data; @@ -94,6 +100,29 @@ struct WrapperTraits<S, true> { typedef typename S::Data_* DataType; }; +template <typename T, typename Enable = void> +struct ValueTraits { + static bool Equals(const T& a, const T& b) { return a == b; } +}; + +template <typename T> +struct ValueTraits< + T, + typename EnableIf<IsSpecializationOf<Array, T>::value || + IsSpecializationOf<Map, T>::value || + IsSpecializationOf<StructPtr, T>::value || + IsSpecializationOf<InlinedStructPtr, T>::value>::type> { + static bool Equals(const T& a, const T& b) { return a.Equals(b); } +}; + +template <typename T> +struct ValueTraits<ScopedHandleBase<T>> { + static bool Equals(const ScopedHandleBase<T>& a, + const ScopedHandleBase<T>& b) { + return a.get().value() == b.get().value(); + } +}; + } // namespace internal } // namespace mojo diff --git a/mojo/public/cpp/bindings/lib/map_internal.h b/mojo/public/cpp/bindings/lib/map_internal.h index ce6e9d6..aa0fe7e 100644 --- a/mojo/public/cpp/bindings/lib/map_internal.h +++ b/mojo/public/cpp/bindings/lib/map_internal.h @@ -8,7 +8,7 @@ #include <map> #include "mojo/public/cpp/bindings/array.h" -#include "mojo/public/cpp/bindings/lib/bindings_internal.h" +#include "mojo/public/cpp/bindings/lib/template_util.h" namespace mojo { namespace internal { diff --git a/mojo/public/cpp/bindings/lib/template_util.h b/mojo/public/cpp/bindings/lib/template_util.h index c4aeb43..6767acf 100644 --- a/mojo/public/cpp/bindings/lib/template_util.h +++ b/mojo/public/cpp/bindings/lib/template_util.h @@ -104,6 +104,15 @@ struct RemovePointer<T*> { typedef T type; }; +template <template <typename...> class Template, typename T> +struct IsSpecializationOf : FalseType {}; + +template <template <typename...> class Template, typename... Args> +struct IsSpecializationOf<Template, Template<Args...>> : TrueType {}; + +template <class A, class B> +struct LogicalOr : IntegralConstant<bool, A::value || B::value> {}; + } // namespace internal } // namespace mojo diff --git a/mojo/public/cpp/bindings/map.h b/mojo/public/cpp/bindings/map.h index 0ee66fb..f09937a 100644 --- a/mojo/public/cpp/bindings/map.h +++ b/mojo/public/cpp/bindings/map.h @@ -117,6 +117,24 @@ class Map { return result.Pass(); } + bool Equals(const Map& other) const { + if (is_null() != other.is_null()) + return false; + if (size() != other.size()) + return false; + auto i = begin(); + auto j = other.begin(); + while (i != end()) { + if (i.GetKey() != j.GetKey()) + return false; + if (!internal::ValueTraits<Value>::Equals(i.GetValue(), j.GetValue())) + return false; + ++i; + ++j; + } + return true; + } + class ConstMapIterator { public: ConstMapIterator( diff --git a/mojo/public/cpp/bindings/struct_ptr.h b/mojo/public/cpp/bindings/struct_ptr.h index 5d08364..efcf255 100644 --- a/mojo/public/cpp/bindings/struct_ptr.h +++ b/mojo/public/cpp/bindings/struct_ptr.h @@ -71,6 +71,12 @@ class StructPtr { // that it contains Mojo handles). StructPtr Clone() const { return is_null() ? StructPtr() : ptr_->Clone(); } + bool Equals(const StructPtr& other) const { + if (is_null() || other.is_null()) + return is_null() && other.is_null(); + return ptr_->Equals(*other.ptr_); + } + private: typedef Struct* StructPtr::*Testable; @@ -139,6 +145,11 @@ class InlinedStructPtr { InlinedStructPtr Clone() const { return is_null() ? InlinedStructPtr() : value_.Clone(); } + bool Equals(const InlinedStructPtr& other) const { + if (is_null() || other.is_null()) + return is_null() && other.is_null(); + return value_.Equals(other.value_); + } private: typedef Struct InlinedStructPtr::*Testable; diff --git a/mojo/public/cpp/bindings/tests/BUILD.gn b/mojo/public/cpp/bindings/tests/BUILD.gn index 918a3db..9e6deab 100644 --- a/mojo/public/cpp/bindings/tests/BUILD.gn +++ b/mojo/public/cpp/bindings/tests/BUILD.gn @@ -10,6 +10,7 @@ test("mojo_public_bindings_unittests") { "buffer_unittest.cc", "connector_unittest.cc", "container_test_util.cc", + "equals_unittest.cc", "handle_passing_unittest.cc", "interface_ptr_unittest.cc", "map_unittest.cc", diff --git a/mojo/public/cpp/bindings/tests/equals_unittest.cc b/mojo/public/cpp/bindings/tests/equals_unittest.cc new file mode 100644 index 0000000..38c78cb --- /dev/null +++ b/mojo/public/cpp/bindings/tests/equals_unittest.cc @@ -0,0 +1,120 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/public/cpp/environment/environment.h" +#include "mojo/public/interfaces/bindings/tests/test_structs.mojom.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo { +namespace test { + +namespace { + +RectPtr CreateRect() { + RectPtr r = Rect::New(); + r->x = 1; + r->y = 2; + r->width = 3; + r->height = 4; + return r.Pass(); +} + +class EqualsTest : public testing::Test { + public: + virtual ~EqualsTest() {} + + private: + Environment env_; +}; +} + +TEST_F(EqualsTest, Null) { + RectPtr r1; + RectPtr r2; + EXPECT_TRUE(r1.Equals(r2)); + EXPECT_TRUE(r2.Equals(r1)); + + r1 = CreateRect(); + EXPECT_FALSE(r1.Equals(r2)); + EXPECT_FALSE(r2.Equals(r1)); +} + +TEST_F(EqualsTest, EqualsStruct) { + RectPtr r1(CreateRect()); + RectPtr r2(r1.Clone()); + EXPECT_TRUE(r1.Equals(r2)); + r2->y = 1; + EXPECT_FALSE(r1.Equals(r2)); + r2.reset(); + EXPECT_FALSE(r1.Equals(r2)); +} + +TEST_F(EqualsTest, EqualsStructNested) { + RectPairPtr p1(RectPair::New()); + p1->first = CreateRect(); + p1->second = CreateRect(); + RectPairPtr p2(p1.Clone()); + EXPECT_TRUE(p1.Equals(p2)); + p2->second->width = 0; + EXPECT_FALSE(p1.Equals(p2)); + p2->second.reset(); + EXPECT_FALSE(p1.Equals(p2)); +} + +TEST_F(EqualsTest, EqualsArray) { + NamedRegionPtr n1(NamedRegion::New()); + n1->name = "n1"; + n1->rects.push_back(CreateRect()); + NamedRegionPtr n2(n1.Clone()); + EXPECT_TRUE(n1.Equals(n2)); + + n2->rects.reset(); + EXPECT_FALSE(n1.Equals(n2)); + n2->rects.resize(0); + EXPECT_FALSE(n1.Equals(n2)); + + n2->rects.push_back(CreateRect()); + n2->rects.push_back(CreateRect()); + EXPECT_FALSE(n1.Equals(n2)); + + n2->rects.resize(1); + n2->rects[0]->width = 0; + EXPECT_FALSE(n1.Equals(n2)); + + n2->rects[0] = CreateRect(); + EXPECT_TRUE(n1.Equals(n2)); +} + +TEST_F(EqualsTest, EqualsMap) { + auto n1(NamedRegion::New()); + n1->name = "foo"; + n1->rects.push_back(CreateRect()); + + Map<std::string, NamedRegionPtr> m1; + m1.insert("foo", n1.Pass()); + + decltype(m1) m2; + EXPECT_FALSE(m1.Equals(m2)); + + m2.insert("bar", m1.at("foo").Clone()); + EXPECT_FALSE(m1.Equals(m2)); + + m2 = m1.Clone(); + m2.at("foo")->name = "monkey"; + EXPECT_FALSE(m1.Equals(m2)); + + m2 = m1.Clone(); + m2.at("foo")->rects.push_back(Rect::New()); + EXPECT_FALSE(m1.Equals(m2)); + + m2.at("foo")->rects.resize(1); + m2.at("foo")->rects[0]->width = 1; + EXPECT_FALSE(m1.Equals(m2)); + + m2 = m1.Clone(); + EXPECT_TRUE(m1.Equals(m2)); +} + +} // test +} // mojo diff --git a/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl index 21f2968..f6bea2c 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl @@ -21,9 +21,11 @@ class {{struct.name}} { {{struct.name}}(); ~{{struct.name}}(); + {% if struct|is_cloneable_kind %} {{struct.name}}Ptr Clone() const; {%- endif %} + bool Equals(const {{struct.name}}& other) const; {#--- Getters #} {% for field in struct.fields %} diff --git a/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl index 1ba7235..cb5a5fa 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl @@ -13,6 +13,7 @@ {{struct.name}}::~{{struct.name}}() { } + {% if struct|is_cloneable_kind %} {{struct.name}}Ptr {{struct.name}}::Clone() const { {{struct.name}}Ptr rv(New()); @@ -26,3 +27,11 @@ return rv.Pass(); } {% endif %} + +bool {{struct.name}}::Equals(const {{struct.name}}& other) const { +{%- for field in struct.fields %} + if (!mojo::internal::ValueTraits<{{field.kind|cpp_wrapper_type}}>::Equals({{field.name}}, other.{{field.name}})) + return false; +{%- endfor %} + return true; +} |