This is an automated email from the ASF dual-hosted git repository. asekretenko pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mesos.git
commit 9bb35fe23fed7756af9ceebccea74bf175fa6e47 Author: Andrei Sekretenko <asekrete...@mesosphere.com> AuthorDate: Mon Aug 31 18:34:00 2020 +0200 Extracted FrameworkInfo comparison logic from tests. This patch extracts the code that performs `FrameworkInfo` comparison via protobuf `MessageDifferencer` from the framework update tests into a set of general-purpose methods. Review: https://reviews.apache.org/r/72822 --- include/mesos/type_utils.hpp | 15 ++++++++ include/mesos/v1/mesos.hpp | 15 ++++++++ src/Makefile.am | 1 + src/common/type_utils.cpp | 29 ++++++++++++++++ src/common/type_utils_differencers.hpp | 53 ++++++++++++++++++++++++++++ src/tests/master/update_framework_tests.cpp | 54 ++++++++++------------------- src/v1/mesos.cpp | 30 ++++++++++++++++ 7 files changed, 161 insertions(+), 36 deletions(-) diff --git a/include/mesos/type_utils.hpp b/include/mesos/type_utils.hpp index da9fd96..2745ff0 100644 --- a/include/mesos/type_utils.hpp +++ b/include/mesos/type_utils.hpp @@ -30,6 +30,7 @@ #include <mesos/mesos.hpp> +#include <stout/option.hpp> #include <stout/stringify.hpp> #include <stout/strings.hpp> #include <stout/uuid.hpp> @@ -121,6 +122,20 @@ inline bool operator==(const FrameworkInfo& left, const FrameworkInfo& right) } +namespace typeutils { + +// Returns whether two `FrameworkInfo`s are equivalent for framework +// subscription purposes or not (i.e. whether subscribing a framework with the +// `left` should have the same effects as with the `right`). +bool equivalent(const FrameworkInfo& left, const FrameworkInfo& right); + +// Performs the same comparison as `equivalent()` and returns a human-readable +// diff if the `FrameworkInfo`s are not equivalnt. +Option<std::string> diff(const FrameworkInfo& left, const FrameworkInfo& right); + +} // namespace typeutils { + + inline bool operator==(const OfferID& left, const OfferID& right) { return left.value() == right.value(); diff --git a/include/mesos/v1/mesos.hpp b/include/mesos/v1/mesos.hpp index d8304f1..853330a 100644 --- a/include/mesos/v1/mesos.hpp +++ b/include/mesos/v1/mesos.hpp @@ -25,6 +25,7 @@ #include <mesos/v1/mesos.pb.h> // ONLY USEFUL AFTER RUNNING PROTOC. +#include <stout/option.hpp> #include <stout/strings.hpp> // This file includes definitions for operators on public protobuf @@ -105,6 +106,20 @@ inline bool operator==(const FrameworkInfo& left, const FrameworkInfo& right) } +namespace typeutils { + +// Returns whether two `FrameworkInfo`s are equivalent for framework +// subscription purposes or not (i.e. whether subscribing a framework with the +// `left` should have the same effects as with the `right`). +bool equivalent(const FrameworkInfo& left, const FrameworkInfo& right); + +// Performs the same comparison as `equivalent()` and returns a human-readable +// diff if the `FrameworkInfo`s are not equivalnt. +Option<std::string> diff(const FrameworkInfo& left, const FrameworkInfo& right); + +} // namespace typeutils { + + inline bool operator==(const OfferID& left, const OfferID& right) { return left.value() == right.value(); diff --git a/src/Makefile.am b/src/Makefile.am index 1043c7b..673ea6c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1091,6 +1091,7 @@ libmesos_no_3rdparty_la_SOURCES += \ common/resources_utils.hpp \ common/roles.cpp \ common/status_utils.hpp \ + common/type_utils_differencers.hpp \ common/type_utils.cpp \ common/validation.cpp \ common/validation.hpp \ diff --git a/src/common/type_utils.cpp b/src/common/type_utils.cpp index bb43784..899fd6d 100644 --- a/src/common/type_utils.cpp +++ b/src/common/type_utils.cpp @@ -26,10 +26,14 @@ #include <stout/protobuf.hpp> #include "messages/messages.hpp" +#include "common/type_utils_differencers.hpp" using std::ostream; using std::string; using std::vector; +using std::unique_ptr; + +using ::mesos::typeutils::internal::createFrameworkInfoDifferencer; namespace mesos { @@ -678,6 +682,31 @@ bool operator!=(const CheckStatusInfo& left, const CheckStatusInfo& right) } +namespace typeutils { + +bool equivalent(const FrameworkInfo& left, const FrameworkInfo& right) +{ + return createFrameworkInfoDifferencer<FrameworkInfo>()->Compare(left, right); +} + + +Option<string> diff(const FrameworkInfo& left, const FrameworkInfo& right) +{ + unique_ptr<::google::protobuf::util::MessageDifferencer> differencer{ + createFrameworkInfoDifferencer<FrameworkInfo>()}; + + string result; + differencer->ReportDifferencesToString(&result); + if (differencer->Compare(left, right)) { + return None(); + } + + return result; +} + +} // namespace typeutils { + + ostream& operator<<(ostream& stream, const CapabilityInfo& capabilityInfo) { return stream << JSON::protobuf(capabilityInfo); diff --git a/src/common/type_utils_differencers.hpp b/src/common/type_utils_differencers.hpp new file mode 100644 index 0000000..b106014 --- /dev/null +++ b/src/common/type_utils_differencers.hpp @@ -0,0 +1,53 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include <memory> + +#include <google/protobuf/descriptor.h> +#include <google/protobuf/util/message_differencer.h> + +namespace mesos { +namespace typeutils { +namespace internal { + +// Creates a protobuf `MessageDifferencer` specifically configured for +// comparing `FrameworkInfo`s (either V0 or V1 ones). +// +// TODO(asekretenko): Remove the `unique_ptr` wrapper if `MessageDifferencer` +// becomes move-constructible in future versions of protobuf. +template <class TFrameworkInfo> +std::unique_ptr<::google::protobuf::util::MessageDifferencer> +createFrameworkInfoDifferencer() +{ + static const ::google::protobuf::Descriptor* descriptor = + TFrameworkInfo::descriptor(); + + CHECK_EQ(13, descriptor->field_count()) + << "After adding a field to FrameworkInfo, please make sure " + << "that FrameworkInfoDifferencer handles this field properly;" + << "after that, adjust the expected fields count in this check."; + + std::unique_ptr<::google::protobuf::util::MessageDifferencer> differencer{ + new ::google::protobuf::util::MessageDifferencer()}; + + differencer->TreatAsSet(descriptor->FindFieldByName("capabilities")); + differencer->TreatAsSet(descriptor->FindFieldByName("roles")); + return differencer; +} + +} // namespace internal { +} // namespace typeutils { +} // namespace mesos { diff --git a/src/tests/master/update_framework_tests.cpp b/src/tests/master/update_framework_tests.cpp index d2a63b6..34e5a70 100644 --- a/src/tests/master/update_framework_tests.cpp +++ b/src/tests/master/update_framework_tests.cpp @@ -19,8 +19,6 @@ #include <gmock/gmock.h> -#include <google/protobuf/util/message_differencer.h> - #include <mesos/executor.hpp> #include <mesos/v1/mesos.hpp> @@ -119,28 +117,6 @@ static TFrameworkInfo changeAllMutableFields(const TFrameworkInfo& oldInfo) return newInfo; } - -template <class TFrameworkInfo> -static Option<std::string> diff( - const TFrameworkInfo& lhs, const TFrameworkInfo& rhs) -{ - const google::protobuf::Descriptor* descriptor = TFrameworkInfo::descriptor(); - google::protobuf::util::MessageDifferencer differencer; - - differencer.TreatAsSet(descriptor->FindFieldByName("capabilities")); - differencer.TreatAsSet(descriptor->FindFieldByName("roles")); - - string result; - differencer.ReportDifferencesToString(&result); - - if (differencer.Compare(lhs, rhs)) { - return None(); - } - - return result; -} - - namespace v1 { @@ -257,10 +233,11 @@ TEST_F(UpdateFrameworkTest, UserChangeFails) FrameworkInfo expected = DEFAULT_FRAMEWORK_INFO; *expected.mutable_id() = subscribed->framework_id(); - EXPECT_NONE(diff(frameworks->frameworks(0).framework_info(), expected)); + EXPECT_NONE(::mesos::v1::typeutils::diff( + frameworks->frameworks(0).framework_info(), expected)); // Sanity check for diff() - EXPECT_SOME(diff(update, expected)); + EXPECT_SOME(::mesos::v1::typeutils::diff(update, expected)); } @@ -307,10 +284,11 @@ TEST_F(UpdateFrameworkTest, PrincipalChangeFails) FrameworkInfo expected = DEFAULT_FRAMEWORK_INFO; *expected.mutable_id() = subscribed->framework_id(); - EXPECT_NONE(diff(frameworks->frameworks(0).framework_info(), expected)); + EXPECT_NONE(::mesos::v1::typeutils::diff( + frameworks->frameworks(0).framework_info(), expected)); // Sanity check for diff() - EXPECT_SOME(diff(update, expected)); + EXPECT_SOME(::mesos::v1::typeutils::diff(update, expected)); } @@ -358,10 +336,11 @@ TEST_F(UpdateFrameworkTest, CheckpointingChangeFails) FrameworkInfo expected = DEFAULT_FRAMEWORK_INFO; *expected.mutable_id() = subscribed->framework_id(); - EXPECT_NONE(diff(frameworks->frameworks(0).framework_info(), expected)); + EXPECT_NONE(::mesos::v1::typeutils::diff( + frameworks->frameworks(0).framework_info(), expected)); // Sanity check for diff() - EXPECT_SOME(diff(update, expected)); + EXPECT_SOME(::mesos::v1::typeutils::diff(update, expected)); } @@ -446,13 +425,15 @@ TEST_F(UpdateFrameworkTest, MutableFieldsUpdateSuccessfully) const FrameworkInfo& frameworkInfo = frameworks->frameworks(0).framework_info(); - EXPECT_NONE(diff(frameworkInfo, update)); + EXPECT_NONE(::mesos::v1::typeutils::diff(frameworkInfo, update)); AWAIT_READY(updateFrameworkMessage); - EXPECT_NONE(diff(evolve(updateFrameworkMessage->framework_info()), update)); + EXPECT_NONE(::mesos::v1::typeutils::diff( + evolve(updateFrameworkMessage->framework_info()), update)); AWAIT_READY(frameworkUpdated); - EXPECT_NONE(diff(frameworkUpdated->framework().framework_info(), update)); + EXPECT_NONE(::mesos::v1::typeutils::diff( + frameworkUpdated->framework().framework_info(), update)); }; @@ -995,10 +976,11 @@ TEST_F(UpdateFrameworkV0Test, MutableFieldsUpdateSuccessfully) AWAIT_READY(updateFrameworkMessage); - EXPECT_NONE(diff(updateFrameworkMessage->framework_info(), update)); + EXPECT_NONE(::mesos::typeutils::diff( + updateFrameworkMessage->framework_info(), update)); AWAIT_READY(frameworkUpdated); - EXPECT_NONE(diff( + EXPECT_NONE(::mesos::typeutils::diff( devolve(frameworkUpdated->framework().framework_info()), update)); Future<v1::master::Response::GetFrameworks> frameworks = @@ -1008,7 +990,7 @@ TEST_F(UpdateFrameworkV0Test, MutableFieldsUpdateSuccessfully) const FrameworkInfo& reportedFrameworkInfo = devolve(frameworks->frameworks(0).framework_info()); - EXPECT_NONE(diff(reportedFrameworkInfo, update)); + EXPECT_NONE(::mesos::typeutils::diff(reportedFrameworkInfo, update)); driver.stop(); driver.join(); diff --git a/src/v1/mesos.cpp b/src/v1/mesos.cpp index c2fb528..6e412e0 100644 --- a/src/v1/mesos.cpp +++ b/src/v1/mesos.cpp @@ -25,9 +25,14 @@ #include <mesos/v1/mesos.hpp> #include <mesos/v1/resources.hpp> +#include "common/type_utils_differencers.hpp" + using std::ostream; using std::string; using std::vector; +using std::unique_ptr; + +using ::mesos::typeutils::internal::createFrameworkInfoDifferencer; namespace mesos { namespace v1 { @@ -506,6 +511,31 @@ bool operator!=(const TaskStatus& left, const TaskStatus& right) } +namespace typeutils { + +bool equivalent(const FrameworkInfo& left, const FrameworkInfo& right) +{ + return createFrameworkInfoDifferencer<FrameworkInfo>()->Compare(left, right); +} + + +Option<string> diff(const FrameworkInfo& left, const FrameworkInfo& right) +{ + unique_ptr<::google::protobuf::util::MessageDifferencer> differencer{ + createFrameworkInfoDifferencer<FrameworkInfo>()}; + + string result; + differencer->ReportDifferencesToString(&result); + if (differencer->Compare(left, right)) { + return None(); + } + + return result; +} + +} // namespace typeutils { + + ostream& operator<<(ostream& stream, const CapabilityInfo& capabilityInfo) { return stream << JSON::protobuf(capabilityInfo);