summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrancis Dupont <fdupont@isc.org>2024-08-07 19:54:07 +0200
committerFrancis Dupont <fdupont@isc.org>2024-08-21 15:12:38 +0200
commit7d1f9176509502efe4580072f654000b5bc1f652 (patch)
treea5b02da8381afa9c3a62d10236ad62c991fdb43c
parent[#3502] Checkpoint: add strict-* syntax (diff)
downloadkea-7d1f9176509502efe4580072f654000b5bc1f652.tar.xz
kea-7d1f9176509502efe4580072f654000b5bc1f652.zip
[#3502] Checkpoint: changed strict- by s
-rw-r--r--src/lib/eval/lexer.ll6
-rw-r--r--src/lib/eval/parser.yy16
-rw-r--r--src/lib/eval/tests/boolean_unittest.cc33
-rw-r--r--src/lib/eval/tests/context_unittest.cc132
4 files changed, 173 insertions, 14 deletions
diff --git a/src/lib/eval/lexer.ll b/src/lib/eval/lexer.ll
index 719d3ff131..b948271a25 100644
--- a/src/lib/eval/lexer.ll
+++ b/src/lib/eval/lexer.ll
@@ -221,7 +221,7 @@ addr6 [0-9a-fA-F]*\:[0-9a-fA-F]*\:[0-9a-fA-F:.]*
"all" return isc::eval::EvalParser::make_ALL(loc);
"concat" return isc::eval::EvalParser::make_CONCAT(loc);
"ifelse" return isc::eval::EvalParser::make_IFELSE(loc);
-"strict-ifelse" return isc::eval::EvalParser::make_STRICT_IFELSE(loc);
+"sifelse" return isc::eval::EvalParser::make_SIFELSE(loc);
"hexstring" return isc::eval::EvalParser::make_TOHEXSTRING(loc);
"addrtotext" return isc::eval::EvalParser::make_ADDRTOTEXT(loc);
"int8totext" return isc::eval::EvalParser::make_INT8TOTEXT(loc);
@@ -232,9 +232,9 @@ addr6 [0-9a-fA-F]*\:[0-9a-fA-F]*\:[0-9a-fA-F:.]*
"uint32totext" return isc::eval::EvalParser::make_UINT32TOTEXT(loc);
"not" return isc::eval::EvalParser::make_NOT(loc);
"and" return isc::eval::EvalParser::make_AND(loc);
-"strict-and" return isc::eval::EvalParser::make_STRICT_AND(loc);
+"sand" return isc::eval::EvalParser::make_SAND(loc);
"or" return isc::eval::EvalParser::make_OR(loc);
-"strict-or" return isc::eval::EvalParser::make_STRICT_OR(loc);
+"sor" return isc::eval::EvalParser::make_SOR(loc);
"member" return isc::eval::EvalParser::make_MEMBER(loc);
"match" return isc::eval::EvalParser::make_MATCH(loc);
"." return isc::eval::EvalParser::make_DOT(loc);
diff --git a/src/lib/eval/parser.yy b/src/lib/eval/parser.yy
index 65573e723c..59fdaa74b5 100644
--- a/src/lib/eval/parser.yy
+++ b/src/lib/eval/parser.yy
@@ -47,9 +47,9 @@ using namespace isc::eval;
RPAREN ")"
NOT "not"
AND "and"
- STRICT_AND "strict-and"
+ SAND "sand"
OR "or"
- STRICT_OR "strict-or"
+ SOR "sor"
EQUAL "=="
OPTION "option"
RELAY4 "relay4"
@@ -83,7 +83,7 @@ using namespace isc::eval;
CONCAT "concat"
PLUS "+"
IFELSE "ifelse"
- STRICT_IFELSE "strict-ifelse"
+ SIFELSE "sifelse"
TOHEXSTRING "hexstring"
ADDRTOTEXT "addrtotext"
INT8TOTEXT "int8totext"
@@ -126,9 +126,9 @@ using namespace isc::eval;
%type <TokenPkt6::FieldType> pkt6_field
%left PLUS
-%left STRICT_OR
+%left SOR
%left OR
-%left STRICT_AND
+%left SAND
%left AND
%precedence NOT
@@ -161,7 +161,7 @@ bool_expr : "(" bool_expr ")"
TokenPtr neg(new TokenAnd());
ctx.expression.push_back(neg);
}
- | bool_expr STRICT_AND bool_expr
+ | bool_expr SAND bool_expr
{
TokenPtr neg(new TokenAnd());
ctx.expression.push_back(neg);
@@ -171,7 +171,7 @@ bool_expr : "(" bool_expr ")"
TokenPtr neg(new TokenOr());
ctx.expression.push_back(neg);
}
- | bool_expr STRICT_OR bool_expr
+ | bool_expr SOR bool_expr
{
TokenPtr neg(new TokenOr());
ctx.expression.push_back(neg);
@@ -423,7 +423,7 @@ string_expr : STRING
TokenPtr cond(new TokenIfElse());
ctx.expression.push_back(cond);
}
- | STRICT_IFELSE "(" bool_expr "," string_expr "," string_expr ")"
+ | SIFELSE "(" bool_expr "," string_expr "," string_expr ")"
{
TokenPtr cond(new TokenIfElse());
ctx.expression.push_back(cond);
diff --git a/src/lib/eval/tests/boolean_unittest.cc b/src/lib/eval/tests/boolean_unittest.cc
index f620daeca4..8c883c155f 100644
--- a/src/lib/eval/tests/boolean_unittest.cc
+++ b/src/lib/eval/tests/boolean_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2016-2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2016-2024 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -34,7 +34,34 @@ public:
}
};
-// A group of tests
+// A group of tests (strict version)
+TEST_F(BooleanTest, strict) {
+ // true and (false or false)
+ check("('a' == 'a') sand (('a' == 'b') sor ('b' == 'a'))", false);
+ // (true and false) or false
+ check("(('a' == 'a') sand ('a' == 'b')) sor ('b' == 'a')", false);
+ // not true
+ check("not ('a' == 'a')", false);
+ // not false
+ check("not ('a' == 'b')", true);
+ // true and true and true and false
+ check("('a' == 'a') sand ('b' == 'b') sand ('c' == 'c') sand ('a' == 'c')",
+ false);
+ // false or false or false or true
+ check("('a' == 'b') sor ('a' == 'c') sor ('b' == 'c') sor ('b' == 'b')",
+ true);
+ // true or false or false or false
+ check("('a' == 'a') sor ('a' == 'b') sor ('a' == 'c') sor ('b' == 'c')",
+ true);
+ // not (true or false)
+ check("not (('a' == 'a') sor ('a' == 'b'))", false);
+ // not (true and false)
+ check("not (('a' == 'a') sand ('a' == 'b'))", true);
+ // (not true) and false
+ check("(not ('a' == 'a')) sand ('a' == 'b')",false);
+}
+
+// A group of tests (strict version)
TEST_F(BooleanTest, tests) {
// true and (false or false)
check("('a' == 'a') and (('a' == 'b') or ('b' == 'a'))", false);
@@ -61,4 +88,4 @@ TEST_F(BooleanTest, tests) {
check("(not ('a' == 'a')) and ('a' == 'b')",false);
}
-};
+}
diff --git a/src/lib/eval/tests/context_unittest.cc b/src/lib/eval/tests/context_unittest.cc
index ca2ce3da1e..0bea61b772 100644
--- a/src/lib/eval/tests/context_unittest.cc
+++ b/src/lib/eval/tests/context_unittest.cc
@@ -1333,6 +1333,31 @@ TEST_F(EvalContextTest, logicalOps) {
boost::dynamic_pointer_cast<TokenNot>(token);
EXPECT_TRUE(tnot);
+ // sand
+ EvalContext evala(Option::V4);
+ EXPECT_NO_THROW(parsed_ =
+ evala.parseString("option[123].exists sand option[123].exists"));
+ EXPECT_TRUE(parsed_);
+ ASSERT_EQ(3, evala.expression.size());
+ token = evala.expression.at(2);
+ ASSERT_TRUE(token);
+ boost::shared_ptr<TokenAnd> tand =
+ boost::dynamic_pointer_cast<TokenAnd>(token);
+ EXPECT_TRUE(tand);
+
+ // sor
+ EvalContext evalo(Option::V4);
+ EXPECT_NO_THROW(parsed_ =
+ evalo.parseString("option[123].exists sor option[123].exists"));
+ EXPECT_TRUE(parsed_);
+ ASSERT_EQ(3, evalo.expression.size());
+ token = evalo.expression.at(2);
+ ASSERT_TRUE(token);
+ boost::shared_ptr<TokenOr> tor =
+ boost::dynamic_pointer_cast<TokenOr>(token);
+ EXPECT_TRUE(tor);
+
+#if notyet
// and
EvalContext evala(Option::V4);
EXPECT_NO_THROW(parsed_ =
@@ -1356,6 +1381,7 @@ TEST_F(EvalContextTest, logicalOps) {
boost::shared_ptr<TokenOr> tor =
boost::dynamic_pointer_cast<TokenOr>(token);
EXPECT_TRUE(tor);
+#endif
}
// Test parsing of logical operators with precedence
@@ -1363,6 +1389,32 @@ TEST_F(EvalContextTest, logicalPrecedence) {
// not precedence > and precedence
EvalContext evalna(Option::V4);
EXPECT_NO_THROW(parsed_ =
+ evalna.parseString("not option[123].exists sand option[123].exists"));
+ EXPECT_TRUE(parsed_);
+ ASSERT_EQ(4, evalna.expression.size());
+ TokenPtr token = evalna.expression.at(3);
+ ASSERT_TRUE(token);
+ boost::shared_ptr<TokenAnd> tand =
+ boost::dynamic_pointer_cast<TokenAnd>(token);
+ EXPECT_TRUE(tand);
+
+ // and precedence > or precedence
+ EvalContext evaloa(Option::V4);
+ EXPECT_NO_THROW(parsed_ =
+ evaloa.parseString("option[123].exists sor option[123].exists "
+ "and option[123].exists"));
+ EXPECT_TRUE(parsed_);
+ ASSERT_EQ(5, evaloa.expression.size());
+ token = evaloa.expression.at(4);
+ ASSERT_TRUE(token);
+ boost::shared_ptr<TokenOr> tor =
+ boost::dynamic_pointer_cast<TokenOr>(token);
+ EXPECT_TRUE(tor);
+
+#if notyet
+ // not precedence > and precedence
+ EvalContext evalna(Option::V4);
+ EXPECT_NO_THROW(parsed_ =
evalna.parseString("not option[123].exists and option[123].exists"));
EXPECT_TRUE(parsed_);
ASSERT_EQ(4, evalna.expression.size());
@@ -1384,6 +1436,7 @@ TEST_F(EvalContextTest, logicalPrecedence) {
boost::shared_ptr<TokenOr> tor =
boost::dynamic_pointer_cast<TokenOr>(token);
EXPECT_TRUE(tor);
+#endif
}
// Test parsing of logical operators with parentheses (same than
@@ -1392,6 +1445,32 @@ TEST_F(EvalContextTest, logicalParentheses) {
// not precedence > and precedence
EvalContext evalna(Option::V4);
EXPECT_NO_THROW(parsed_ =
+ evalna.parseString("not (option[123].exists sand option[123].exists)"));
+ EXPECT_TRUE(parsed_);
+ ASSERT_EQ(4, evalna.expression.size());
+ TokenPtr token = evalna.expression.at(3);
+ ASSERT_TRUE(token);
+ boost::shared_ptr<TokenNot> tnot =
+ boost::dynamic_pointer_cast<TokenNot>(token);
+ EXPECT_TRUE(tnot);
+
+ // and precedence > or precedence
+ EvalContext evaloa(Option::V4);
+ EXPECT_NO_THROW(parsed_ =
+ evaloa.parseString("(option[123].exists sor option[123].exists) "
+ "sand option[123].exists"));
+ EXPECT_TRUE(parsed_);
+ ASSERT_EQ(5, evaloa.expression.size());
+ token = evaloa.expression.at(4);
+ ASSERT_TRUE(token);
+ boost::shared_ptr<TokenAnd> tand =
+ boost::dynamic_pointer_cast<TokenAnd>(token);
+ EXPECT_TRUE(tand);
+
+#if notyet
+ // not precedence > and precedence
+ EvalContext evalna(Option::V4);
+ EXPECT_NO_THROW(parsed_ =
evalna.parseString("not (option[123].exists and option[123].exists)"));
EXPECT_TRUE(parsed_);
ASSERT_EQ(4, evalna.expression.size());
@@ -1413,6 +1492,7 @@ TEST_F(EvalContextTest, logicalParentheses) {
boost::shared_ptr<TokenAnd> tand =
boost::dynamic_pointer_cast<TokenAnd>(token);
EXPECT_TRUE(tand);
+#endif
}
// Test the parsing of a substring expression
@@ -1519,7 +1599,28 @@ TEST_F(EvalContextTest, assocRightPlus) {
checkTokenConcat(tmp5);
}
+// Test the parsing of a sifelse expression
+TEST_F(EvalContextTest, strictIfElse) {
+ EvalContext eval(Option::V4);
+
+ EXPECT_NO_THROW(parsed_ =
+ eval.parseString("sifelse('foo' == 'bar', 'us', 'them') == 'you'"));
+
+ ASSERT_EQ(8, eval.expression.size());
+
+ TokenPtr tmp1 = eval.expression.at(2);
+ TokenPtr tmp2 = eval.expression.at(3);
+ TokenPtr tmp3 = eval.expression.at(4);
+ TokenPtr tmp4 = eval.expression.at(5);
+
+ checkTokenEq(tmp1);
+ checkTokenString(tmp2, "us");
+ checkTokenString(tmp3, "them");
+ checkTokenIfElse(tmp4);
+}
+
// Test the parsing of an ifelse expression
+#if notyet
TEST_F(EvalContextTest, ifElse) {
EvalContext eval(Option::V4);
@@ -1538,8 +1639,38 @@ TEST_F(EvalContextTest, ifElse) {
checkTokenString(tmp3, "them");
checkTokenIfElse(tmp4);
}
+#endif
+
+// Test the parsing of a plus operator and sifelse expression
+TEST_F(EvalContextTest, plusStrictIfElse) {
+ EvalContext eval(Option::V4);
+
+ EXPECT_NO_THROW(parsed_ =
+ eval.parseString("'foo' + sifelse('a' == 'a', 'bar', '') == 'foobar'"));
+
+ ASSERT_EQ(10, eval.expression.size());
+
+ TokenPtr tmp1 = eval.expression.at(0);
+ TokenPtr tmp2 = eval.expression.at(1);
+ TokenPtr tmp3 = eval.expression.at(2);
+ TokenPtr tmp4 = eval.expression.at(3);
+ TokenPtr tmp5 = eval.expression.at(4);
+ TokenPtr tmp6 = eval.expression.at(5);
+ TokenPtr tmp7 = eval.expression.at(6);
+ TokenPtr tmp8 = eval.expression.at(7);
+
+ checkTokenString(tmp1, "foo");
+ checkTokenString(tmp2, "a");
+ checkTokenString(tmp3, "a");
+ checkTokenEq(tmp4);
+ checkTokenString(tmp5, "bar");
+ checkTokenString(tmp6, "");
+ checkTokenIfElse(tmp7);
+ checkTokenConcat(tmp8);
+}
// Test the parsing of a plus operator and ifelse expression
+#if notyet
TEST_F(EvalContextTest, plusIfElse) {
EvalContext eval(Option::V4);
@@ -1566,6 +1697,7 @@ TEST_F(EvalContextTest, plusIfElse) {
checkTokenIfElse(tmp7);
checkTokenConcat(tmp8);
}
+#endif
// Test the parsing of a hexstring expression
TEST_F(EvalContextTest, toHexString) {