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/28 12:47:13 UTC
[mesos] 05/05: Added basic tests for regexp-based constraints.
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 355b971ead7079e3fabcb46aa0a8b9e31c9fb79e
Author: Andrei Sekretenko <as...@apache.org>
AuthorDate: Mon Aug 17 20:57:43 2020 +0200
Added basic tests for regexp-based constraints.
Review: https://reviews.apache.org/r/72787
---
.../master/offer_constraints_filter_tests.cpp | 186 +++++++++++++++++++++
1 file changed, 186 insertions(+)
diff --git a/src/tests/master/offer_constraints_filter_tests.cpp b/src/tests/master/offer_constraints_filter_tests.cpp
index db1976c..f80d56c 100644
--- a/src/tests/master/offer_constraints_filter_tests.cpp
+++ b/src/tests/master/offer_constraints_filter_tests.cpp
@@ -263,6 +263,192 @@ TEST(OfferConstraintsFilter, TwoAttributesWithTheSameName)
}
+// Tests a single TextMatches constraint on a named attribute.
+TEST(OfferConstraintsFilter, NamedAttributeTextMatches)
+{
+ Try<OfferConstraints> constraints = OfferConstraintsFromJSON(R"~(
+ {
+ "role_constraints": {
+ "roleA": {
+ "groups": [{
+ "attribute_constraints": [{
+ "selector": {"attribute_name": "bar"},
+ "predicate": {"text_matches": {"regex": "[a-d]+"}}
+ }]
+ }]
+ }
+ }
+ })~");
+
+ ASSERT_SOME(constraints);
+
+ const Try<OfferConstraintsFilter> filter = createFilter(*constraints);
+
+ ASSERT_SOME(filter);
+
+ // Attribute exists, is a text and matches the regex.
+ EXPECT_FALSE(
+ filter->isAgentExcluded("roleA", slaveInfoWithAttributes("bar:abcd")));
+
+ // If an attribute is not a text, the constraint is a pass-through.
+ EXPECT_FALSE(
+ filter->isAgentExcluded("roleA", slaveInfoWithAttributes("bar:123")));
+
+ EXPECT_FALSE(
+ filter->isAgentExcluded("roleA", slaveInfoWithAttributes("bar:[1-17]")));
+
+ // Attribute is a text which does not match.
+ EXPECT_TRUE(
+ filter->isAgentExcluded("roleA", slaveInfoWithAttributes("bar:bcde")));
+
+ // Attribute does not exist.
+ EXPECT_TRUE(
+ filter->isAgentExcluded("roleA", slaveInfoWithAttributes("foo:abcd")));
+}
+
+
+// Tests a single TextNotMatches constraint on a named attribute.
+TEST(OfferConstraintsFilter, NamedAttributeTextNotMatches)
+{
+ Try<OfferConstraints> constraints = OfferConstraintsFromJSON(R"~(
+ {
+ "role_constraints": {
+ "roleA": {
+ "groups": [{
+ "attribute_constraints": [{
+ "selector": {"attribute_name": "bar"},
+ "predicate": {"text_not_matches": {"regex": "[a-d]+"}}
+ }]
+ }]
+ }
+ }
+ })~");
+
+ ASSERT_SOME(constraints);
+
+ const Try<OfferConstraintsFilter> filter = createFilter(*constraints);
+
+ ASSERT_SOME(filter);
+
+ // Attribute exists, is a text and matches the regex.
+ EXPECT_TRUE(
+ filter->isAgentExcluded("roleA", slaveInfoWithAttributes("bar:abcd")));
+
+ // If an attribute is not a text, the constraint is a pass-through.
+ EXPECT_FALSE(
+ filter->isAgentExcluded("roleA", slaveInfoWithAttributes("bar:123")));
+
+ EXPECT_FALSE(
+ filter->isAgentExcluded("roleA", slaveInfoWithAttributes("bar:[1-17]")));
+
+ // Attribute is a text which does not match.
+ EXPECT_FALSE(
+ filter->isAgentExcluded("roleA", slaveInfoWithAttributes("bar:bcde")));
+
+ // Attribute does not exist.
+ EXPECT_FALSE(
+ filter->isAgentExcluded("roleA", slaveInfoWithAttributes("foo:abcd")));
+}
+
+
+// Tests an invalid TextMatches constraint.
+TEST(OfferConstraintsFilter, InvalidTextMatches)
+{
+ Try<OfferConstraints> constraints = OfferConstraintsFromJSON(R"~(
+ {
+ "role_constraints": {
+ "roleA": {
+ "groups": [{
+ "attribute_constraints": [{
+ "selector": {"attribute_name": "bar"},
+ "predicate": {"text_matches": {"regex": "[a-d"}}
+ }]
+ }]
+ }
+ }
+ })~");
+
+ ASSERT_SOME(constraints);
+
+ ASSERT_ERROR(createFilter(*constraints));
+}
+
+
+// Tests an invalid TextNotMatches constraint.
+TEST(OfferConstraintsFilter, InvalidTextNotMatches)
+{
+ Try<OfferConstraints> constraints = OfferConstraintsFromJSON(R"~(
+ {
+ "role_constraints": {
+ "roleA": {
+ "groups": [{
+ "attribute_constraints": [{
+ "selector": {"attribute_name": "bar"},
+ "predicate": {"text_not_matches": {"regex": "[a-d"}}
+ }]
+ }]
+ }
+ }
+ })~");
+
+ ASSERT_SOME(constraints);
+
+ ASSERT_ERROR(createFilter(*constraints));
+}
+
+
+// Tests that the constraints cannot specify a regex which will result in a too
+// complex RE2 regex program.
+TEST(OfferConstraintsFilter, RegexTooComplex)
+{
+ auto regexConstraints = [](const string& regex) {
+ return OfferConstraintsFromJSON(
+ R"~(
+ {
+ "role_constraints": {
+ "roleA": {
+ "groups": [{
+ "attribute_constraints": [{
+ "selector": {"attribute_name": "bar"},
+ "predicate": {"text_not_matches": {"regex": ")~" +
+ regex + R"~("}}
+ }]
+ }]
+ }
+ }
+ })~");
+ };
+
+ {
+ Try<OfferConstraints> good = regexConstraints("(a+){10}");
+ ASSERT_SOME(good);
+ ASSERT_SOME(createFilter(*good));
+ }
+
+ {
+ // This regexp can be compiled (fits into a memory limit) but results in
+ // a too large program.
+ Try<OfferConstraints> tooComplex = regexConstraints("(a+){50}");
+ ASSERT_SOME(tooComplex);
+
+ Try<OfferConstraintsFilter> filter = createFilter(*tooComplex);
+ ASSERT_ERROR(filter);
+ ASSERT_TRUE(strings::contains(filter.error(), "too complex"));
+ }
+
+ {
+ // This regexp does not even fit into a memory limit.
+ Try<OfferConstraints> tooLarge = regexConstraints("(a+){500}");
+ ASSERT_SOME(tooLarge);
+
+ Try<OfferConstraintsFilter> filter = createFilter(*tooLarge);
+ ASSERT_ERROR(filter);
+ ASSERT_TRUE(strings::contains(
+ filter.error(), "pattern too large - compile failed"));
+ }
+}
+
+
// Tests a single group of two constraints.
TEST(OfferConstraintsFilter, TwoConstraintsInGroup)
{