Browse Source

[4231] Addressed code comments

Francis Dupont 9 years ago
parent
commit
732af87d48

+ 2 - 9
src/lib/eval/evaluate.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2015-2016 Internet Systems Consortium, Inc. ("ISC")
 //
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
 // purpose with or without fee is hereby granted, provided that the above
@@ -27,14 +27,7 @@ bool evaluate(const Expression& expr, const Pkt& pkt) {
         isc_throw(EvalBadStack, "Incorrect stack order. Expected exactly "
         isc_throw(EvalBadStack, "Incorrect stack order. Expected exactly "
                   "1 value at the end of evaluatuion, got " << values.size());
                   "1 value at the end of evaluatuion, got " << values.size());
     }
     }
-    if (values.top() == "false") {
-        return (false);
-    } else if (values.top() == "true") {
-        return (true);
-    } else {
-        isc_throw(EvalTypeError, "Incorrect evaluation type. Expected "
-                  "\"false\" or \"true\", got \"" << values.top() << "\"");
-    }
+    return (Token::toBool(values.top()));
 }
 }
 
 
 }; // end of isc::dhcp namespace
 }; // end of isc::dhcp namespace

+ 1 - 1
src/lib/eval/lexer.cc

@@ -665,7 +665,7 @@ goto find_rule; \
 #define YY_RESTORE_YY_MORE_OFFSET
 #define YY_RESTORE_YY_MORE_OFFSET
 char *yytext;
 char *yytext;
 #line 1 "lexer.ll"
 #line 1 "lexer.ll"
-/* Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
+/* Copyright (C) 2015-2016 Internet Systems Consortium, Inc. ("ISC")
 
 
    Permission to use, copy, modify, and/or distribute this software for any
    Permission to use, copy, modify, and/or distribute this software for any
    purpose with or without fee is hereby granted, provided that the above
    purpose with or without fee is hereby granted, provided that the above

+ 1 - 1
src/lib/eval/lexer.ll

@@ -1,4 +1,4 @@
-/* Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
+/* Copyright (C) 2015-2016 Internet Systems Consortium, Inc. ("ISC")
 
 
    Permission to use, copy, modify, and/or distribute this software for any
    Permission to use, copy, modify, and/or distribute this software for any
    purpose with or without fee is hereby granted, provided that the above
    purpose with or without fee is hereby granted, provided that the above

+ 1 - 1
src/lib/eval/parser.yy

@@ -1,4 +1,4 @@
-/* Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
+/* Copyright (C) 2015-2016 Internet Systems Consortium, Inc. ("ISC")
 
 
    Permission to use, copy, modify, and/or distribute this software for any
    Permission to use, copy, modify, and/or distribute this software for any
    purpose with or without fee is hereby granted, provided that the above
    purpose with or without fee is hereby granted, provided that the above

+ 2 - 1
src/lib/eval/tests/Makefile.am

@@ -26,7 +26,8 @@ if HAVE_GTEST
 
 
 TESTS += libeval_unittests
 TESTS += libeval_unittests
 
 
-libeval_unittests_SOURCES  = context_unittest.cc
+libeval_unittests_SOURCES  = boolean_unittest.cc
+libeval_unittests_SOURCES += context_unittest.cc
 libeval_unittests_SOURCES += evaluate_unittest.cc
 libeval_unittests_SOURCES += evaluate_unittest.cc
 libeval_unittests_SOURCES += token_unittest.cc
 libeval_unittests_SOURCES += token_unittest.cc
 libeval_unittests_SOURCES += run_unittests.cc
 libeval_unittests_SOURCES += run_unittests.cc

+ 72 - 0
src/lib/eval/tests/boolean_unittest.cc

@@ -0,0 +1,72 @@
+// Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <config.h>
+#include <eval/eval_context.h>
+#include <eval/evaluate.h>
+#include <eval/token.h>
+#include <dhcp/pkt4.h>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <gtest/gtest.h>
+
+using namespace std;
+using namespace isc::dhcp;
+
+namespace {
+
+/// @brief Test fixture for testing booleans.
+class BooleanTest : public ::testing::Test {
+public:
+    void check(const string& expr, bool expected) {
+        EvalContext eval(Option::V4);
+        ASSERT_TRUE(eval.parseString(expr));
+        Pkt4Ptr pkt4(new Pkt4(DHCPDISCOVER, 12345));
+        if (expected) {
+            EXPECT_TRUE(evaluate(eval.expression, *pkt4));
+        } else {
+            EXPECT_FALSE(evaluate(eval.expression, *pkt4));
+        }
+    }
+};
+
+// A group of tests
+TEST_F(BooleanTest, tests) {
+    // true and (false or false)
+    check("('a' == 'a') and (('a' == 'b') or ('b' == 'a'))", false);
+    // (true and false) or false
+    check("(('a' == 'a') and ('a' == 'b')) or ('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') and ('b' == 'b') and ('c' == 'c') and ('a' == 'c')",
+          false);
+    // false or false or false or true
+    check("('a' == 'b') or ('a' == 'c') or ('b' == 'c') or ('b' == 'b')",
+          true);
+    // true or false or false or false
+    check("('a' == 'a') or ('a' == 'b') or ('a' == 'c') or ('b' == 'c')",
+          true);
+    // not (true or false)
+    check("not (('a' == 'a') or ('a' == 'b'))", false);
+    // not (true and false)
+    check("not (('a' == 'a') and ('a' == 'b'))", true);
+    // (not true) and false
+    check("(not ('a' == 'a')) and ('a' == 'b')",false);
+}
+
+};

+ 1 - 1
src/lib/eval/tests/context_unittest.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2015-2016 Internet Systems Consortium, Inc. ("ISC")
 //
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
 // purpose with or without fee is hereby granted, provided that the above

+ 1 - 1
src/lib/eval/tests/evaluate_unittest.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2015-2016 Internet Systems Consortium, Inc. ("ISC")
 //
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
 // purpose with or without fee is hereby granted, provided that the above

+ 19 - 1
src/lib/eval/tests/token_unittest.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2015-2016 Internet Systems Consortium, Inc. ("ISC")
 //
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
 // purpose with or without fee is hereby granted, provided that the above
@@ -106,6 +106,24 @@ public:
     /// @todo: Add more option types here
     /// @todo: Add more option types here
 };
 };
 
 
+// This tests the toBool() conversions
+TEST_F(TokenTest, toBool) {
+
+    ASSERT_NO_THROW(Token::toBool("true"));
+    EXPECT_TRUE(Token::toBool("true"));
+    ASSERT_NO_THROW(Token::toBool("false"));
+    EXPECT_FALSE(Token::toBool("false"));
+
+    // Token::toBool() is case-sensitive
+    EXPECT_THROW(Token::toBool("True"), EvalTypeError);
+    EXPECT_THROW(Token::toBool("TRUE"), EvalTypeError);
+
+    // Proposed aliases
+    EXPECT_THROW(Token::toBool("1"), EvalTypeError);
+    EXPECT_THROW(Token::toBool("0"), EvalTypeError);
+    EXPECT_THROW(Token::toBool(""), EvalTypeError);
+}
+
 // This simple test checks that a TokenString, representing a constant string,
 // This simple test checks that a TokenString, representing a constant string,
 // can be used in Pkt4 evaluation. (The actual packet is not used)
 // can be used in Pkt4 evaluation. (The actual packet is not used)
 TEST_F(TokenTest, string4) {
 TEST_F(TokenTest, string4) {

+ 15 - 44
src/lib/eval/token.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2015-2016 Internet Systems Consortium, Inc. ("ISC")
 //
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
 // purpose with or without fee is hereby granted, provided that the above
@@ -190,14 +190,12 @@ TokenNot::evaluate(const Pkt& /*pkt*/, ValueStack& values) {
 
 
     string op = values.top();
     string op = values.top();
     values.pop();
     values.pop();
+    bool val = toBool(op);
 
 
-    if (op == "true") {
-        values.push("false");
-    } else if (op == "false") {
-        values.push("true");
+    if (val) {
+	values.push("false");
     } else {
     } else {
-        isc_throw(EvalTypeError, "Expected a logical value at top of stack. "
-                  << "Got '" << op << "'.");
+	values.push("true");
     }
     }
 }
 }
 
 
@@ -211,28 +209,15 @@ TokenAnd::evaluate(const Pkt& /*pkt*/, ValueStack& values) {
 
 
     string op1 = values.top();
     string op1 = values.top();
     values.pop();
     values.pop();
+    bool val1 = toBool(op1);
     string op2 = values.top();
     string op2 = values.top();
     values.pop(); // Dammit, std::stack interface is awkward.
     values.pop(); // Dammit, std::stack interface is awkward.
+    bool val2 = toBool(op2);
 
 
-    if (op1 == "true") {
-        if (op2 == "true") {
-            values.push("true");
-        } else if (op2 == "false") {
-            values.push("false");
-        } else {
-            isc_throw(EvalTypeError, "Expected logical values at "
-                      << "top of stack. Got 'true' and '" << op2 << "'");
-        }
-    } else if (op1 == "false") {
-        if ((op2 == "true") || (op2 == "false")) {
-            values.push("false");
-        } else {
-            isc_throw(EvalTypeError, "Expected logical values at "
-                      << "top of stack. Got 'false' and '" << op2 << "'");
-        }
+    if (val1 && val2) {
+	values.push("true");
     } else {
     } else {
-        isc_throw(EvalTypeError, "Expected logical values at top of stack. "
-                  << "Got '" << op1 << "' and '" << op2 << "'");
+	values.push("false");
     }
     }
 }
 }
 
 
@@ -246,28 +231,14 @@ TokenOr::evaluate(const Pkt& /*pkt*/, ValueStack& values) {
 
 
     string op1 = values.top();
     string op1 = values.top();
     values.pop();
     values.pop();
+    bool val1 = toBool(op1);
     string op2 = values.top();
     string op2 = values.top();
     values.pop(); // Dammit, std::stack interface is awkward.
     values.pop(); // Dammit, std::stack interface is awkward.
+    bool val2 = toBool(op2);
 
 
-    if (op1 == "true") {
-        if ((op2 == "true") || (op2 == "false")) {
-            values.push("true");
-        } else {
-            isc_throw(EvalTypeError, "Expected logical values at "
-                      << "top of stack. Got 'true' and '" << op2 << "'");
-        }
-    } else if (op1 == "false") {
-        if (op2 == "true") {
-            values.push("true");
-        } else if (op2 == "false") {
-            values.push("false");
-        } else {
-            isc_throw(EvalTypeError, "Expected logical values at "
-                      << "top of stack. Got 'false' and '" << op2 << "'");
-        }
+    if (val1 || val2) {
+	values.push("true");
     } else {
     } else {
-        isc_throw(EvalTypeError, "Expected logical values at top of stack. "
-                  << "Got '" << op1 << "' and '" << op2 << "'");
+	values.push("false");
     }
     }
 }
 }
-

+ 19 - 1
src/lib/eval/token.h

@@ -1,4 +1,4 @@
-// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2015-2016 Internet Systems Consortium, Inc. ("ISC")
 //
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
 // purpose with or without fee is hereby granted, provided that the above
@@ -87,6 +87,24 @@ public:
 
 
     /// @brief Virtual destructor
     /// @brief Virtual destructor
     virtual ~Token() {}
     virtual ~Token() {}
+
+    /// @brief Coverts a (string) value to a boolean
+    ///
+    /// Only "true" and "false" are expected.
+    ///
+    /// @param the (string) value
+    /// @return the boolean represented by the value
+    /// @throw EvalTypeError when the value is not either "true" or "false".
+    static inline bool toBool(std::string value) {
+        if (value == "true") {
+            return (true);
+        } else if (value == "false") {
+            return (false);
+        } else {
+            isc_throw(EvalTypeError, "Incorrect boolean. Expected exactly "
+                      "\"false\" or \"true\", got \"" << value << "\"");
+        }
+    }
 };
 };
 
 
 /// @brief Token representing a constant string
 /// @brief Token representing a constant string