You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by as...@apache.org on 2020/08/20 19:23:49 UTC

[mesos] 04/07: Added basic tests for the `OfferConstraintsFilter`.

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 f0af7082f8bd1586c7f5de9eaa3a8ef83060d632
Author: Andrei Sekretenko <as...@apache.org>
AuthorDate: Mon Aug 3 17:16:11 2020 +0200

    Added basic tests for the `OfferConstraintsFilter`.
    
    Review: https://reviews.apache.org/r/72742
---
 src/Makefile.am                                    |   1 +
 src/tests/CMakeLists.txt                           |   1 +
 .../master/offer_constraints_filter_tests.cpp      | 265 +++++++++++++++++++++
 3 files changed, 267 insertions(+)

diff --git a/src/Makefile.am b/src/Makefile.am
index a91678e..8b95611 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -2693,6 +2693,7 @@ mesos_tests_SOURCES =						\
   tests/master_tests.cpp					\
   tests/master/mock_master_api_subscriber.cpp			\
   tests/master/mock_master_api_subscriber.hpp			\
+  tests/master/offer_constraints_filter_tests.cpp		\
   tests/master/update_framework_tests.cpp			\
   tests/master_validation_tests.cpp				\
   tests/mesos.cpp						\
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
index cf579f8..6b420d0 100644
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -111,6 +111,7 @@ set(MESOS_TESTS_SRC
   master_load_tests.cpp
   master_maintenance_tests.cpp
   master_slave_reconciliation_tests.cpp
+  master/offer_constraints_filter_tests.cpp
   master/update_framework_tests.cpp
   metrics_tests.cpp
   operation_reconciliation_tests.cpp
diff --git a/src/tests/master/offer_constraints_filter_tests.cpp b/src/tests/master/offer_constraints_filter_tests.cpp
new file mode 100644
index 0000000..f88e201
--- /dev/null
+++ b/src/tests/master/offer_constraints_filter_tests.cpp
@@ -0,0 +1,265 @@
+// 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 <string>
+
+#include <gtest/gtest.h>
+
+#include <stout/gtest.hpp>
+#include <stout/json.hpp>
+#include <stout/protobuf.hpp>
+#include <stout/try.hpp>
+
+#include <mesos/allocator/allocator.hpp>
+#include <mesos/attributes.hpp>
+
+using std::string;
+using std::unique_ptr;
+
+using ::mesos::Attributes;
+using ::mesos::SlaveInfo;
+
+using ::mesos::allocator::OfferConstraintsFilter;
+
+using ::mesos::scheduler::OfferConstraints;
+
+
+static Try<OfferConstraints> OfferConstraintsFromJSON(const string& json)
+{
+  Try<JSON::Object> jsonObject = JSON::parse<JSON::Object>(json);
+
+  if (jsonObject.isError()) {
+    return Error(jsonObject.error());
+  }
+
+  return protobuf::parse<OfferConstraints>(*jsonObject);
+}
+
+
+static SlaveInfo slaveInfoWithAttributes(const string& attributes)
+{
+  SlaveInfo info;
+  *info.mutable_attributes() = Attributes::parse(attributes);
+  return info;
+}
+
+
+// Tests a single Exists constraint on a named attribute.
+TEST(OfferConstraintsFilter, NamedAttributeExists)
+{
+  Try<OfferConstraints> constraints = OfferConstraintsFromJSON(R"~(
+    {
+      "role_constraints": {
+        "roleA": {
+          "groups": [{
+            "attribute_constraints": [{
+              "selector": {"attribute_name": "bar"},
+              "predicate": {"exists": {}}
+            }]
+          }]
+        }
+      }
+    })~");
+
+  ASSERT_SOME(constraints);
+
+  const Try<OfferConstraintsFilter> filter =
+    OfferConstraintsFilter::create(std::move(*constraints));
+
+  ASSERT_SOME(filter);
+
+  EXPECT_FALSE(
+      filter->isAgentExcluded("roleA", slaveInfoWithAttributes("bar:123")));
+
+  EXPECT_TRUE(
+      filter->isAgentExcluded("roleA", slaveInfoWithAttributes("foo:123")));
+
+  EXPECT_FALSE(filter->isAgentExcluded(
+      "roleA", slaveInfoWithAttributes("foo:123;bar:456")));
+}
+
+
+// Tests a single NotExists constraint on a named attribute.
+TEST(OfferConstraintsFilter, NamedAttributeNotExists)
+{
+  Try<OfferConstraints> constraints = OfferConstraintsFromJSON(R"~(
+    {
+      "role_constraints": {
+        "roleA": {
+          "groups": [{
+            "attribute_constraints": [{
+              "selector": {"attribute_name": "bar"},
+              "predicate": {"not_exists": {}}
+            }]
+          }]
+        }
+      }
+    })~");
+
+  ASSERT_SOME(constraints);
+
+  const Try<OfferConstraintsFilter> filter =
+    OfferConstraintsFilter::create(std::move(*constraints));
+
+  ASSERT_SOME(filter);
+
+  EXPECT_TRUE(
+      filter->isAgentExcluded("roleA", slaveInfoWithAttributes("bar:123")));
+
+  EXPECT_FALSE(
+      filter->isAgentExcluded("roleA", slaveInfoWithAttributes("foo:123")));
+
+  EXPECT_TRUE(filter->isAgentExcluded(
+      "roleA", slaveInfoWithAttributes("foo:123;bar:456")));
+}
+
+
+// Tests a single group of two constraints.
+TEST(OfferConstraintsFilter, TwoConstraintsInGroup)
+{
+  Try<OfferConstraints> constraints = OfferConstraintsFromJSON(R"~(
+    {
+      "role_constraints": {
+        "roleA": {
+          "groups": [{
+            "attribute_constraints": [
+              {
+                "selector": {"attribute_name": "foo"},
+                "predicate": {"exists": {}}
+              },
+              {
+                "selector": {"attribute_name": "bar"},
+                "predicate": {"not_exists": {}}
+              }
+            ]
+          }]
+        }
+      }
+    })~");
+
+  ASSERT_SOME(constraints);
+
+  const Try<OfferConstraintsFilter> filter =
+    OfferConstraintsFilter::create(std::move(*constraints));
+
+  ASSERT_SOME(filter);
+
+  EXPECT_TRUE(filter->isAgentExcluded("roleA", slaveInfoWithAttributes("")));
+
+  EXPECT_FALSE(
+      filter->isAgentExcluded("roleA", slaveInfoWithAttributes("foo:123")));
+
+  EXPECT_TRUE(
+      filter->isAgentExcluded("roleA", slaveInfoWithAttributes("bar:456")));
+
+  EXPECT_TRUE(filter->isAgentExcluded(
+      "roleA", slaveInfoWithAttributes("bar:123;foo:456")));
+
+  EXPECT_FALSE(filter->isAgentExcluded(
+      "roleA", slaveInfoWithAttributes("baz:123;foo:456")));
+}
+
+
+// Tests a constraint expression consisting of two groups.
+TEST(OfferConstraintsFilter, TwoGroups)
+{
+  Try<OfferConstraints> constraints = OfferConstraintsFromJSON(R"~(
+    {
+      "role_constraints": {
+        "roleA": {
+          "groups": [
+            {
+              "attribute_constraints": [{
+                "selector": {"attribute_name": "foo"},
+                "predicate": {"exists": {}}
+              }]
+            },
+            {
+              "attribute_constraints": [{
+                "selector": {"attribute_name": "bar"},
+                "predicate": {"not_exists": {}}
+              }]
+            }
+          ]
+        }
+      }
+    })~");
+
+  ASSERT_SOME(constraints);
+
+  const Try<OfferConstraintsFilter> filter =
+    OfferConstraintsFilter::create(std::move(*constraints));
+
+  ASSERT_SOME(filter);
+
+  EXPECT_FALSE(filter->isAgentExcluded("roleA", slaveInfoWithAttributes("")));
+
+  EXPECT_FALSE(
+      filter->isAgentExcluded("roleA", slaveInfoWithAttributes("baz:123")));
+
+  EXPECT_TRUE(
+      filter->isAgentExcluded("roleA", slaveInfoWithAttributes("bar:123")));
+
+  EXPECT_FALSE(filter->isAgentExcluded(
+      "roleA", slaveInfoWithAttributes("bar:123;foo:456")));
+}
+
+
+// Tests offer constraints for two roles.
+TEST(OfferConstraintsFilter, TwoRoles)
+{
+  Try<OfferConstraints> constraints = OfferConstraintsFromJSON(R"~(
+    {
+      "role_constraints": {
+        "roleA": {
+          "groups": [{
+            "attribute_constraints": [{
+              "selector": {"attribute_name": "foo"},
+              "predicate": {"exists": {}}
+            }]
+          }]
+        },
+        "roleB": {
+          "groups": [{
+            "attribute_constraints": [{
+              "selector": {"attribute_name": "bar"},
+              "predicate": {"exists": {}}
+            }]
+          }]
+        }
+      }
+    })~");
+
+  ASSERT_SOME(constraints);
+
+  const Try<OfferConstraintsFilter> filter =
+    OfferConstraintsFilter::create(std::move(*constraints));
+
+  ASSERT_SOME(filter);
+
+  EXPECT_TRUE(
+      filter->isAgentExcluded("roleA", slaveInfoWithAttributes("bar:123")));
+
+  EXPECT_FALSE(
+      filter->isAgentExcluded("roleA", slaveInfoWithAttributes("foo:123")));
+
+  EXPECT_FALSE(
+      filter->isAgentExcluded("roleB", slaveInfoWithAttributes("bar:123")));
+
+  EXPECT_TRUE(
+      filter->isAgentExcluded("roleB", slaveInfoWithAttributes("foo:123")));
+}