-// 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
// purpose with or without fee is hereby granted, provided that the above
isc_throw(EvalBadStack, "Incorrect stack order. Expected exactly "
"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
#define YY_RESTORE_YY_MORE_OFFSET
char *yytext;
#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
purpose with or without fee is hereby granted, provided that the above
-/* 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
purpose with or without fee is hereby granted, provided that the above
-/* 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
purpose with or without fee is hereby granted, provided that the above
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 += token_unittest.cc
libeval_unittests_SOURCES += run_unittests.cc
--- /dev/null
+// 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);
+}
+
+};
-// 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
// purpose with or without fee is hereby granted, provided that the above
-// 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
// purpose with or without fee is hereby granted, provided that the above
-// 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
// purpose with or without fee is hereby granted, provided that the above
/// @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,
// can be used in Pkt4 evaluation. (The actual packet is not used)
TEST_F(TokenTest, string4) {
-// 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
// purpose with or without fee is hereby granted, provided that the above
string op = values.top();
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 {
- isc_throw(EvalTypeError, "Expected a logical value at top of stack. "
- << "Got '" << op << "'.");
+ values.push("true");
}
}
string op1 = values.top();
values.pop();
+ bool val1 = toBool(op1);
string op2 = values.top();
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 {
- isc_throw(EvalTypeError, "Expected logical values at top of stack. "
- << "Got '" << op1 << "' and '" << op2 << "'");
+ values.push("false");
}
}
string op1 = values.top();
values.pop();
+ bool val1 = toBool(op1);
string op2 = values.top();
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 {
- isc_throw(EvalTypeError, "Expected logical values at top of stack. "
- << "Got '" << op1 << "' and '" << op2 << "'");
+ values.push("false");
}
}
-
-// 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
// purpose with or without fee is hereby granted, provided that the above
/// @brief Virtual destructor
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