// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <config.h>
+#include <fstream>
#include <eval/token.h>
#include <dhcp/pkt4.h>
#include <dhcp/pkt6.h>
#include <dhcp/dhcp4.h>
#include <dhcp/dhcp6.h>
#include <dhcp/option_string.h>
+#include <log/logger_manager.h>
+#include <log/logger_name.h>
+#include <log/logger_support.h>
#include <boost/shared_ptr.hpp>
#include <boost/scoped_ptr.hpp>
using namespace std;
using namespace isc::dhcp;
using namespace isc::asiolink;
+using namespace isc::log;
namespace {
///
/// This class provides several convenience objects to be used during testing
/// of the Token family of classes.
+
class TokenTest : public ::testing::Test {
public:
pkt4_->addOption(option_str4_);
pkt6_->addOption(option_str6_);
+
+ // Set up the logger for use in checking the debug statements.
+ // We send the debug statements to a file which we can
+ // check after the evaluations have completed. We also
+ // set the log severity and debug levels so that the log
+ // statements are executed.
+ LoggerSpecification spec(getRootLoggerName(),
+ keaLoggerSeverity(isc::log::DEBUG),
+ keaLoggerDbglevel(isc::log::MAX_DEBUG_LEVEL));
+ OutputOption option;
+ option.destination = OutputOption::DEST_FILE;
+ option.filename = string(TokenTest::LOG_FILE);
+ spec.addOutputOption(option);
+ LoggerManager manager;
+ manager.process(spec);
+ }
+
+ /// @brief check that the requested strings are in the
+ /// test log file in the requested order.
+ ///
+ /// @param exp_strings vector of strings to match
+ /// @return true if all of the strings match
+ bool checkFile(const vector<string>& exp_strings) {
+ ifstream file(LOG_FILE);
+ EXPECT_TRUE(file.is_open());
+ string line, exp_line;
+ int i = 0;
+ bool found = true;
+
+ while (getline(file, line) && (i != exp_strings.size())) {
+ exp_line = exp_strings[i];
+ i++;
+ if (string::npos == line.find(exp_line)) {
+ found = false;
+ }
+ }
+
+ file.close();
+
+ if ((i != exp_strings.size()) || (found == false))
+ return (false);
+
+ return (true);
+ }
+
+ /// @brief remove the test log file
+ void remFile() {
+ static_cast<void>(remove(LOG_FILE));
}
/// @brief Inserts RAI option with several suboptions
}
/// @todo: Add more option types here
+
+ /// Name of the log file used during tests
+ static const char * LOG_FILE;
};
+// Set up the name of the LOG_FILE for use in checking
+// the debug statements
+const char *TokenTest::LOG_FILE = "test.log";
+
// This tests the toBool() conversions
TEST_F(TokenTest, toBool) {
// Check that the evaluation put its value on the values stack.
ASSERT_EQ(1, values_.size());
EXPECT_EQ("foo", values_.top());
+
+ // Check that the debug output was correct, we create a vector
+ // of all the strings we expect (in this case only 1) and send
+ // it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_STRING Pushing text string \"foo\"");
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
}
// This simple test checks that a TokenString, representing a constant string,
// Check that the evaluation put its value on the values stack.
ASSERT_EQ(1, values_.size());
EXPECT_EQ("foo", values_.top());
+
+ // Check that the debug output was correct, we create a vector
+ // of all the strings we expect (in this case only 1) and send
+ // it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_STRING Pushing text string \"foo\"");
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
}
// This simple test checks that a TokenHexString, representing a constant
// Store constant hexstring "0x63825363" (DHCP_OPTIONS_COOKIE).
ASSERT_NO_THROW(cookie.reset(new TokenHexString("0x63825363")));
- // Make sure that tokens can be evaluated without exceptions.
+ // Make sure that tokens can be evaluated without exceptions,
+ // and verify the debug output
ASSERT_NO_THROW(empty->evaluate(*pkt4_, values_));
ASSERT_NO_THROW(bad->evaluate(*pkt4_, values_));
ASSERT_NO_THROW(nodigit->evaluate(*pkt4_, values_));
EXPECT_EQ("", values_.top());
values_.pop();
EXPECT_EQ("", values_.top());
+
+ // Check that the debug output was correct, we create a vector of all
+ // the strings we expect and send it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_HEXSTRING Pushing hex string 0x");
+ exp_strings.push_back("EVAL_DEBUG_HEXSTRING Pushing hex string 0x");
+ exp_strings.push_back("EVAL_DEBUG_HEXSTRING Pushing hex string 0x");
+ exp_strings.push_back("EVAL_DEBUG_HEXSTRING Pushing hex string 0x");
+ exp_strings.push_back("EVAL_DEBUG_HEXSTRING Pushing hex string 0x07");
+ exp_strings.push_back("EVAL_DEBUG_HEXSTRING Pushing hex string 0x666F6F");
+ exp_strings.push_back("EVAL_DEBUG_HEXSTRING Pushing hex string 0x63825363");
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
}
// This simple test checks that a TokenHexString, representing a constant
EXPECT_EQ("", values_.top());
values_.pop();
EXPECT_EQ("", values_.top());
+
+ // Check that the debug output was correct, we create a vector of all
+ // the strings we expect and send it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_HEXSTRING Pushing hex string 0x");
+ exp_strings.push_back("EVAL_DEBUG_HEXSTRING Pushing hex string 0x");
+ exp_strings.push_back("EVAL_DEBUG_HEXSTRING Pushing hex string 0x");
+ exp_strings.push_back("EVAL_DEBUG_HEXSTRING Pushing hex string 0x");
+ exp_strings.push_back("EVAL_DEBUG_HEXSTRING Pushing hex string 0x07");
+ exp_strings.push_back("EVAL_DEBUG_HEXSTRING Pushing hex string 0x666F6F");
+ exp_strings.push_back("EVAL_DEBUG_HEXSTRING Pushing hex string 0x63825363");
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
}
// This test checks that a TokenIpAddress, representing an IP address as
uint8_t expected4[] = { 10, 0, 0, 1 };
EXPECT_EQ(4, values_.top().size());
EXPECT_EQ(0, memcmp(expected4, &values_.top()[0], 4));
+
+ // Check that the debug output was correct, we create a vector of all
+ // the strings we expect and send it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_IPADDRESS Pushing IPAddress 0x0A000001");
+ exp_strings.push_back("EVAL_DEBUG_IPADDRESS Pushing IPAddress "
+ "0x20010DB8000000000000000000000001");
+ exp_strings.push_back("EVAL_DEBUG_IPADDRESS Pushing IPAddress 0x");
+ exp_strings.push_back("EVAL_DEBUG_IPADDRESS Pushing IPAddress 0x");
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
}
// This test checks if a token representing an option value is able to extract
// Then the content of the option 100.
EXPECT_EQ("hundred4", values_.top());
+
+ // Check that the debug output was correct, we create a vector of all
+ // the strings we expect and send it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_OPTION Pushing option 100 with value \"hundred4\"");
+ exp_strings.push_back("EVAL_DEBUG_OPTION Pushing option 101 with value \"\"");
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
}
// This test checks if a token representing option value is able to extract
// Then the content of the option 100.
EXPECT_EQ("hundred4", values_.top());
+
+ // Check that the debug output was correct, we create a vector of all
+ // the strings we expect and send it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_OPTION Pushing option 100 with value "
+ "0x68756E6472656434");
+ exp_strings.push_back("EVAL_DEBUG_OPTION Pushing option 101 with value 0x");
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
}
// This test checks if a token representing an option value is able to check
EXPECT_EQ("false", values_.top());
values_.pop();
EXPECT_EQ("true", values_.top());
+
+ // Check that the debug output was correct, we create a vector of all
+ // the strings we expect and send it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_OPTION Pushing option 100 with value \"true\"");
+ exp_strings.push_back("EVAL_DEBUG_OPTION Pushing option 101 with value \"false\"");
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
}
// This test checks if a token representing an option value is able to extract
// Then the content of the option 100.
EXPECT_EQ("hundred6", values_.top());
+
+ // Check that the debug output was correct, we create a vector of all
+ // the strings we expect and send it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_OPTION Pushing option 100 with value \"hundred6\"");
+ exp_strings.push_back("EVAL_DEBUG_OPTION Pushing option 101 with value \"\"");
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
}
// This test checks if a token representing an option value is able to extract
// Then the content of the option 100.
EXPECT_EQ("hundred6", values_.top());
+
+ // Check that the debug output was correct, we create a vector of all
+ // the strings we expect and send it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_OPTION Pushing option 100 with value "
+ "0x68756E6472656436");
+ exp_strings.push_back("EVAL_DEBUG_OPTION Pushing option 101 with value 0x");
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
}
// This test checks if a token representing an option value is able to check
EXPECT_EQ("false", values_.top());
values_.pop();
EXPECT_EQ("true", values_.top());
+
+ // Check that the debug output was correct, we create a vector of all
+ // the strings we expect and send it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_OPTION Pushing option 100 with value \"true\"");
+ exp_strings.push_back("EVAL_DEBUG_OPTION Pushing option 101 with value \"false\"");
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
}
// This test checks that the existing relay4 option can be found.
// The option should be found and relay4[13] should evaluate to the
// content of that sub-option, i.e. "thirteen"
EXPECT_EQ("thirteen", values_.top());
+
+ // Check that the debug output was correct, we create a vector of all
+ // the strings we expect and send it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_OPTION Pushing option 13 with value \"thirteen\"");
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
}
// This test checks that the code properly handles cases when
// The option should NOT be found (there is no sub-option 15),
// so the expression should evaluate to ""
EXPECT_EQ("", values_.top());
+
+ // Check that the debug output was correct, we create a vector of all
+ // the strings we expect and send it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_OPTION Pushing option 15 with value \"\"");
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
}
// This test checks that the code properly handles cases when
// The option should NOT be found (there is no sub-option 13),
// so the expression should evaluate to ""
EXPECT_EQ("", values_.top());
+
+ // Check that the debug output was correct, we create a vector of all
+ // the strings we expect and send it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_OPTION Pushing option 13 with value \"\"");
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
}
// This test checks that only the RAI is searched for the requested
EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
ASSERT_EQ(1, values_.size());
EXPECT_EQ("false", values_.top());
+
+ // Check that the debug output was correct, we create a vector of all
+ // the strings we expect and send it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_OPTION Pushing option 13 with value \"thirteen\"");
+ exp_strings.push_back("EVAL_DEBUG_OPTION Pushing option 1 with value \"one\"");
+ exp_strings.push_back("EVAL_DEBUG_OPTION Pushing option 70 with value \"\"");
+ exp_strings.push_back("EVAL_DEBUG_OPTION Pushing option 1 with value \"true\"");
+ exp_strings.push_back("EVAL_DEBUG_OPTION Pushing option 70 with value \"false\"");
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
}
// Verifies if the DHCPv4 packet fields can be extracted.
clearStack();
ASSERT_NO_THROW(t_.reset(new TokenPkt4(TokenPkt4::HLEN)));
EXPECT_THROW(t_->evaluate(*pkt6_, values_), EvalTypeError);
+
+ // Check that the debug output was correct, we create a vector of all
+ // the strings we expect and send it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_PKT4 Pushing PKT4 field mac "
+ "with value 0x01020304050607");
+ exp_strings.push_back("EVAL_DEBUG_PKT4 Pushing PKT4 field hlen "
+ "with value 0x00000007");
+ exp_strings.push_back("EVAL_DEBUG_PKT4 Pushing PKT4 field htype "
+ "with value 0x0000007B");
+ exp_strings.push_back("EVAL_DEBUG_PKT4 Pushing PKT4 field giaddr "
+ "with value 0xC0000201");
+ exp_strings.push_back("EVAL_DEBUG_PKT4 Pushing PKT4 field ciaddr "
+ "with value 0xC0000202");
+ exp_strings.push_back("EVAL_DEBUG_PKT4 Pushing PKT4 field yiaddr "
+ "with value 0xC0000203");
+ exp_strings.push_back("EVAL_DEBUG_PKT4 Pushing PKT4 field siaddr "
+ "with value 0xC0000204");
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
}
// This test checks if a token representing an == operator is able to
// result of "foo" == "bar" comparision.
ASSERT_EQ(1, values_.size());
EXPECT_EQ("false", values_.top());
+
+ // Check that the debug output was correct, we create a vector of all
+ // the strings we expect and send it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_EQUAL Popping 0x626172 and 0x666F6F "
+ "pushing result \"false\"");
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
}
// This test checks if a token representing an == operator is able to
// result of "foo" == "foo" comparision.
ASSERT_EQ(1, values_.size());
EXPECT_EQ("true", values_.top());
+
+ // Check that the debug output was correct, we create a vector of all
+ // the strings we expect and send it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_EQUAL Popping 0x666F6F and 0x666F6F "
+ "pushing result \"true\"");
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
}
// This test checks if a token representing a not is able to
EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
ASSERT_EQ(1, values_.size());
EXPECT_EQ("true", values_.top());
+
+ // Check that the debug output was correct, we create a vector of all
+ // the strings we expect and send it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_NOT Popping \"true\" pushing \"false\"");
+ exp_strings.push_back("EVAL_DEBUG_NOT Popping \"false\" pushing \"true\"");
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
}
// This test checks if a token representing an and is able to
ASSERT_EQ(1, values_.size());
EXPECT_EQ("false", values_.top());
- // After true and false, checks false and true
+ // After true and false, check false and true
values_.push("true");
EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
ASSERT_EQ(1, values_.size());
EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
ASSERT_EQ(1, values_.size());
EXPECT_EQ("false", values_.top());
+
+ // Check that the debug output was correct, we create a vector of all
+ // the strings we expect and send it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_AND Popping \"false\" and \"true\" pushing \"false\"");
+ exp_strings.push_back("EVAL_DEBUG_AND Popping \"true\" and \"false\" pushing \"false\"");
+ exp_strings.push_back("EVAL_DEBUG_AND Popping \"false\" and \"false\" pushing \"false\"");
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
}
// This test checks if a token representing an and is able to
// After evaluation there should be a single "true" value
ASSERT_EQ(1, values_.size());
EXPECT_EQ("true", values_.top());
+
+ // Check that the debug output was correct, we create a vector of all
+ // the strings we expect and send it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_AND Popping \"true\" and \"true\" pushing \"true\"");
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
}
// This test checks if a token representing an or is able to
// After evaluation there should be a single "false" value
ASSERT_EQ(1, values_.size());
EXPECT_EQ("false", values_.top());
+
+ // Check that the debug output was correct, we create a vector of all
+ // the strings we expect and send it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_OR Popping \"false\" and \"false\" pushing \"false\"");
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
}
// This test checks if a token representing an == operator is able to
EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
ASSERT_EQ(1, values_.size());
EXPECT_EQ("true", values_.top());
-}
-};
+ // Check that the debug output was correct, we create a vector of all
+ // the strings we expect and send it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_OR Popping \"true\" and \"false\" pushing \"true\"");
+ exp_strings.push_back("EVAL_DEBUG_OR Popping \"false\" and \"true\" pushing \"true\"");
+ exp_strings.push_back("EVAL_DEBUG_OR Popping \"true\" and \"true\" pushing \"true\"");
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
+}
// This test checks if a token representing a substring request
// throws an exception if there aren't enough values on the stack.
// one after the evaluate
ASSERT_EQ(1, values_.size());
EXPECT_EQ("", values_.top());
+
+ // Check that the debug output was correct, we create a vector of all
+ // the strings we expect and send it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING_EMPTY Popping length 0, start 0, "
+ "string 0x pushing result 0x");
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
}
// Test getting the whole string in different ways
// Get the whole string counting from the back
verifySubstringEval("foobar", "-6", "all", "foobar");
+
+ // Check that the debug output was correct, we create a vector of all
+ // the strings we expect and send it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING Popping length 6, start 0, "
+ "string 0x666F6F626172 pushing result 0x666F6F626172");
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING Popping length all, start 0, "
+ "string 0x666F6F626172 pushing result 0x666F6F626172");
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING Popping length 123456, start 0, "
+ "string 0x666F6F626172 pushing result 0x666F6F626172");
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING Popping length all, start -6, "
+ "string 0x666F6F626172 pushing result 0x666F6F626172");
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
}
// Test getting a suffix, in this case the last 3 characters
verifySubstringEval("foobar", "3", "all", "bar");
verifySubstringEval("foobar", "-3", "all", "bar");
verifySubstringEval("foobar", "-3", "123", "bar");
+
+ // Check that the debug output was correct, we create a vector of all
+ // the strings we expect and send it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING Popping length 3, start 3, "
+ "string 0x666F6F626172 pushing result 0x626172");
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING Popping length all, start 3, "
+ "string 0x666F6F626172 pushing result 0x626172");
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING Popping length all, start -3, "
+ "string 0x666F6F626172 pushing result 0x626172");
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING Popping length 123, start -3, "
+ "string 0x666F6F626172 pushing result 0x626172");
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
}
// Test getting the middle of the string in different ways
verifySubstringEval("foobar", "-5", "4", "ooba");
verifySubstringEval("foobar", "-1", "-4", "ooba");
verifySubstringEval("foobar", "5", "-4", "ooba");
+
+ // Check that the debug output was correct, we create a vector of all
+ // the strings we expect and send it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING Popping length 4, start 1, "
+ "string 0x666F6F626172 pushing result 0x6F6F6261");
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING Popping length 4, start -5, "
+ "string 0x666F6F626172 pushing result 0x6F6F6261");
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING Popping length -4, start -1, "
+ "string 0x666F6F626172 pushing result 0x6F6F6261");
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING Popping length -4, start 5, "
+ "string 0x666F6F626172 pushing result 0x6F6F6261");
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
}
// Test getting the last letter in different ways
verifySubstringEval("foobar", "-1", "all", "r");
verifySubstringEval("foobar", "-1", "1", "r");
verifySubstringEval("foobar", "-1", "5", "r");
+
+ // Check that the debug output was correct, we create a vector of all
+ // the strings we expect and send it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING Popping length all, start 5, "
+ "string 0x666F6F626172 pushing result 0x72");
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING Popping length 1, start 5, "
+ "string 0x666F6F626172 pushing result 0x72");
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING Popping length 5, start 5, "
+ "string 0x666F6F626172 pushing result 0x72");
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING Popping length all, start -1, "
+ "string 0x666F6F626172 pushing result 0x72");
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING Popping length 1, start -1, "
+ "string 0x666F6F626172 pushing result 0x72");
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING Popping length 5, start -1, "
+ "string 0x666F6F626172 pushing result 0x72");
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
}
// Test we get only what is available if we ask for a longer string
verifySubstringEval("foobar", "4", "4", "ar");
verifySubstringEval("foobar", "5", "4", "r");
verifySubstringEval("foobar", "6", "4", "");
+
+ // Check that the debug output was correct, we create a vector of all
+ // the strings we expect and send it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING Popping length -4, start 0, "
+ "string 0x666F6F626172 pushing result 0x");
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING Popping length -4, start 1, "
+ "string 0x666F6F626172 pushing result 0x66");
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING Popping length -4, start 2, "
+ "string 0x666F6F626172 pushing result 0x666F");
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING Popping length -4, start 3, "
+ "string 0x666F6F626172 pushing result 0x666F6F");
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING Popping length 4, start 3, "
+ "string 0x666F6F626172 pushing result 0x626172");
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING Popping length 4, start 4, "
+ "string 0x666F6F626172 pushing result 0x6172");
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING Popping length 4, start 5, "
+ "string 0x666F6F626172 pushing result 0x72");
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING_RANGE Popping length 4, start 6, "
+ "string 0x666F6F626172 pushing result 0x");
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
}
// Test that we get nothing if the starting postion is out of the string
verifySubstringEval("foobar", "6", "1", "");
verifySubstringEval("foobar", "6", "-11", "");
verifySubstringEval("foobar", "6", "all", "");
+
+ // Check that the debug output was correct, we create a vector of all
+ // the strings we expect and send it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING_RANGE Popping length 1, start -7, "
+ "string 0x666F6F626172 pushing result 0x");
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING_RANGE Popping length -11, start -7, "
+ "string 0x666F6F626172 pushing result 0x");
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING_RANGE Popping length all, start -7, "
+ "string 0x666F6F626172 pushing result 0x");
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING_RANGE Popping length 1, start 6, "
+ "string 0x666F6F626172 pushing result 0x");
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING_RANGE Popping length -11, start 6, "
+ "string 0x666F6F626172 pushing result 0x");
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING_RANGE Popping length all, start 6, "
+ "string 0x666F6F626172 pushing result 0x");
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
}
// Check what happens if we use strings that aren't numbers for start or length
verifySubstringEval("foobar", "0", "0ick", "", true);
verifySubstringEval("foobar", "0", "ick0", "", true);
verifySubstringEval("foobar", "0", "allaboard", "", true);
+
+ // These should result in a throw which should generate it's own
+ // log entry
+ remFile();
}
// lastly check that we don't get anything if the string is empty or
TEST_F(TokenTest, substringReturnEmpty) {
verifySubstringEval("", "0", "all", "");
verifySubstringEval("foobar", "0", "0", "");
+
+ // Check that the debug output was correct, we create a vector of all
+ // the strings we expect and send it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING_EMPTY Popping length all, start 0, "
+ "string 0x pushing result 0x");
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING Popping length 0, start 0, "
+ "string 0x666F6F626172 pushing result 0x");
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
}
// Check if we can use the substring and equal tokens together
values_.push("ooba");
// The substring values
- // Subsring requires three values on the stack, try
- // with 0, 1 and 2 all should throw an exception
values_.push("foobar");
values_.push("1");
values_.push("4");
values_.push("foob");
// The substring values
- // Subsring requires three values on the stack, try
- // with 0, 1 and 2 all should throw an exception
values_.push("foobar");
values_.push("1");
values_.push("4");
ASSERT_EQ(1, values_.size());
EXPECT_EQ("false", values_.top());
+ // Check that the debug output was correct, we create a vector of all
+ // the strings we expect and send it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING Popping length 4, start 1, "
+ "string 0x666F6F626172 pushing result 0x6F6F6261");
+ exp_strings.push_back("EVAL_DEBUG_EQUAL Popping 0x6F6F6261 and 0x6F6F6261 "
+ "pushing result \"true\"");
+ exp_strings.push_back("EVAL_DEBUG_SUBSTRING Popping length 4, start 1, "
+ "string 0x666F6F626172 pushing result 0x6F6F6261");
+ exp_strings.push_back("EVAL_DEBUG_EQUAL Popping 0x6F6F6261 and 0x666F6F62 "
+ "pushing result \"false\"");
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
}
// This test checks if a token representing a concat request
// Check the result
ASSERT_EQ(1, values_.size());
EXPECT_EQ("foobar", values_.top());
+
+ // Check that the debug output was correct, we create a vector of all
+ // the strings we expect and send it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_CONCAT Popping 0x626172 and 0x666F6F "
+ "pushing 0x666F6F626172");
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
}
// This test checks if we can properly extract the link and peer
// be tidy
clearStack();
+
+ // Check that the debug output was correct, we create a vector of all
+ // the strings we expect and send it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_RELAY6 Pushing PKT6 relay field linkaddr nest 0 "
+ "with value 0x00000000000000000000000000000000");
+ exp_strings.push_back("EVAL_DEBUG_RELAY6 Pushing PKT6 relay field peeraddr nest 0 "
+ "with value 0x00000000000000000000000000000000");
+ exp_strings.push_back("EVAL_DEBUG_RELAY6 Pushing PKT6 relay field linkaddr nest 1 "
+ "with value 0x00010000000000000000000000000001");
+ exp_strings.push_back("EVAL_DEBUG_RELAY6 Pushing PKT6 relay field peeraddr nest 1 "
+ "with value 0x00010000000000000000000000000002");
+ exp_strings.push_back("EVAL_DEBUG_RELAY6_RANGE Pushing PKT6 relay field linkaddr nest 2 "
+ "with value 0x");
+
+ exp_strings.push_back("EVAL_DEBUG_RELAY6 Pushing PKT6 relay field linkaddr nest 1 "
+ "with value 0x00010000000000000000000000000001");
+ exp_strings.push_back("EVAL_DEBUG_IPADDRESS Pushing IPAddress "
+ "0x00010000000000000000000000000001");
+ exp_strings.push_back("EVAL_DEBUG_EQUAL Popping 0x00010000000000000000000000000001 "
+ "and 0x00010000000000000000000000000001 pushing result \"true\"");
+
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
}
// This test checks if we can properly extract an option
// Level 2, no encapsulation so no options
verifyRelay6Option(2, 100, TokenOption::TEXTUAL, "");
+
+ // Check that the debug output was correct, we create a vector of all
+ // the strings we expect and send it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_OPTION Pushing option 100 with value \"hundred.zero\"");
+ exp_strings.push_back("EVAL_DEBUG_OPTION Pushing option 100 with value \"true\"");
+ exp_strings.push_back("EVAL_DEBUG_OPTION Pushing option 101 with value \"hundredone.zero\"");
+ exp_strings.push_back("EVAL_DEBUG_OPTION Pushing option 102 with value \"\"");
+ exp_strings.push_back("EVAL_DEBUG_OPTION Pushing option 102 with value \"false\"");
+
+ exp_strings.push_back("EVAL_DEBUG_OPTION Pushing option 100 with value \"hundred.one\"");
+ exp_strings.push_back("EVAL_DEBUG_OPTION Pushing option 101 with value \"\"");
+ exp_strings.push_back("EVAL_DEBUG_OPTION Pushing option 102 with value \"hundredtwo.one\"");
+
+ exp_strings.push_back("EVAL_DEBUG_OPTION Pushing option 100 with value \"\"");
+
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
}
// Verifies if the DHCPv6 packet fields can be extracted.
clearStack();
ASSERT_NO_THROW(t_.reset(new TokenPkt6(TokenPkt6::TRANSID)));
EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalTypeError);
+
+ // Check that the debug output was correct, we create a vector of all
+ // the strings we expect and send it to checkFile for comparison.
+ vector<string> exp_strings;
+ exp_strings.push_back("EVAL_DEBUG_PKT6 Pushing PKT6 field msgtype "
+ "with value 0x00000001");
+ exp_strings.push_back("EVAL_DEBUG_PKT6 Pushing PKT6 field transid "
+ "with value 0x00003039");
+
+ EXPECT_TRUE(checkFile(exp_strings));
+ remFile();
}
+};
TokenString::evaluate(const Pkt& /*pkt*/, ValueStack& values) {
// Literals only push, nothing to pop
values.push(value_);
+
+ // Log what we pushed
+ LOG_DEBUG(eval_logger, EVAL_DBG_EXTENDED_CALLS, EVAL_DEBUG_STRING)
+ .arg('"' + value_ + '"');
}
TokenHexString::TokenHexString(const string& str) : value_("") {
TokenHexString::evaluate(const Pkt& /*pkt*/, ValueStack& values) {
// Literals only push, nothing to pop
values.push(value_);
+
+ // Log what we pushed
+ LOG_DEBUG(eval_logger, EVAL_DBG_EXTENDED_CALLS, EVAL_DEBUG_HEXSTRING)
+ .arg("0x" + util::encode::encodeHex(std::vector<uint8_t>(value_.begin(),
+ value_.end())));
}
TokenIpAddress::TokenIpAddress(const string& addr) : value_("") {
TokenIpAddress::evaluate(const Pkt& /*pkt*/, ValueStack& values) {
// Literals only push, nothing to pop
values.push(value_);
+
+ // Log what we pushed
+ LOG_DEBUG(eval_logger, EVAL_DBG_EXTENDED_CALLS, EVAL_DEBUG_IPADDRESS)
+ .arg("0x" + util::encode::encodeHex(std::vector<uint8_t>(value_.begin(),
+ value_.end())));
}
OptionPtr
// Push value of the option or empty string if there was no such option
// in the packet.
values.push(opt_str);
+
+ // Log what we pushed, both exists and textual are simple text
+ // and can be output directly. We also include the code number
+ // of the requested option.
+ if (representation_type_ == HEXADECIMAL) {
+ LOG_DEBUG(eval_logger, EVAL_DBG_EXTENDED_CALLS, EVAL_DEBUG_OPTION)
+ .arg(option_code_)
+ .arg("0x" + util::encode::encodeHex(std::vector<uint8_t>(opt_str.begin(),
+ opt_str.end())));
+ } else {
+ LOG_DEBUG(eval_logger, EVAL_DBG_EXTENDED_CALLS, EVAL_DEBUG_OPTION)
+ .arg(option_code_)
+ .arg('"' + opt_str + '"');
+ }
}
TokenRelay4Option::TokenRelay4Option(const uint16_t option_code,
TokenPkt4::evaluate(const Pkt& pkt, ValueStack& values) {
vector<uint8_t> binary;
+ string type_str;
try {
// Check if it's a Pkt4. If it's not, the dynamic_cast will throw
// std::bad_cast (failed dynamic_cast returns NULL for pointers and
"Packet does not have hardware address");
}
binary = hwaddr->hwaddr_;
+ type_str = "mac";
break;
}
case GIADDR:
binary = pkt4.getGiaddr().toBytes();
+ type_str = "giaddr";
break;
case CIADDR:
binary = pkt4.getCiaddr().toBytes();
+ type_str = "ciaddr";
break;
case YIADDR:
binary = pkt4.getYiaddr().toBytes();
+ type_str = "yiaddr";
break;
case SIADDR:
binary = pkt4.getSiaddr().toBytes();
+ type_str = "siaddr";
break;
case HLEN:
binary.push_back(0);
binary.push_back(0);
binary.push_back(pkt4.getHlen());
+ type_str = "hlen";
break;
case HTYPE:
binary.push_back(0);
binary.push_back(0);
binary.push_back(pkt4.getHtype());
+ type_str = "htype";
break;
default:
memmove(&value[0], &binary[0], binary.size());
}
values.push(value);
+
+ // Log what we pushed
+ LOG_DEBUG(eval_logger, EVAL_DBG_EXTENDED_CALLS, EVAL_DEBUG_PKT4)
+ .arg(type_str)
+ .arg("0x" + util::encode::encodeHex(std::vector<uint8_t>(value.begin(),
+ value.end())));
}
void
string op2 = values.top();
values.pop(); // Dammit, std::stack interface is awkward.
+ string result;
if (op1 == op2)
- values.push("true");
+ result = "true";
else
- values.push("false");
+ result = "false";
+
+ values.push(result);
+
+ // Log what we popped and pushed
+ LOG_DEBUG(eval_logger, EVAL_DBG_EXTENDED_CALLS, EVAL_DEBUG_EQUAL)
+ .arg("0x" + util::encode::encodeHex(std::vector<uint8_t>(op1.begin(),
+ op1.end())))
+ .arg("0x" + util::encode::encodeHex(std::vector<uint8_t>(op2.begin(),
+ op2.end())))
+ .arg('"' + result + '"');
}
void
// If we have no string to start with we push an empty string and leave
if (string_str.empty()) {
values.push("");
+
+ // Log what we popped and pushed
+ LOG_DEBUG(eval_logger, EVAL_DBG_EXTENDED_CALLS, EVAL_DEBUG_SUBSTRING_EMPTY)
+ .arg(len_str)
+ .arg(start_str)
+ .arg("0x")
+ .arg("0x");
return;
}
// empty string and leave
if ((start_pos < -string_length) || (start_pos >= string_length)) {
values.push("");
+
+ // Log what we popped and pushed
+ LOG_DEBUG(eval_logger, EVAL_DBG_EXTENDED_CALLS, EVAL_DEBUG_SUBSTRING_RANGE)
+ .arg(len_str)
+ .arg(start_str)
+ .arg("0x" + util::encode::encodeHex(std::vector<uint8_t>(string_str.begin(),
+ string_str.end())))
+ .arg("0x");
return;
}
}
}
+
// and finally get the substring
- values.push(string_str.substr(start_pos, length));
+ string result = string_str.substr(start_pos, length);
+ values.push(result);
+
+ // Log what we popped and pushed
+ LOG_DEBUG(eval_logger, EVAL_DBG_EXTENDED_CALLS, EVAL_DEBUG_SUBSTRING)
+ .arg(len_str)
+ .arg(start_str)
+ .arg("0x" + util::encode::encodeHex(std::vector<uint8_t>(string_str.begin(),
+ string_str.end())))
+ .arg("0x" + util::encode::encodeHex(std::vector<uint8_t>(result.begin(),
+ result.end())));
}
void
values.pop(); // Dammit, std::stack interface is awkward.
// The top of the stack was evaluated last so this is the right order
- values.push(op2 + op1);
+ string result = op2 + op1;
+ values.push(result);
+
+ // Log what we popped and pushed
+ LOG_DEBUG(eval_logger, EVAL_DBG_EXTENDED_CALLS, EVAL_DEBUG_CONCAT)
+ .arg("0x" + util::encode::encodeHex(std::vector<uint8_t>(op1.begin(),
+ op1.end())))
+ .arg("0x" + util::encode::encodeHex(std::vector<uint8_t>(op2.begin(),
+ op2.end())))
+ .arg("0x" + util::encode::encodeHex(std::vector<uint8_t>(result.begin(),
+ result.end())));
}
void
values.pop();
bool val = toBool(op);
+ string result;
if (!val) {
- values.push("true");
+ result = "true";
} else {
- values.push("false");
+ result = "false";
}
+ values.push(result);
+
+ // Log what we popped and pushed
+ LOG_DEBUG(eval_logger, EVAL_DBG_EXTENDED_CALLS, EVAL_DEBUG_NOT)
+ .arg('"' + op + '"')
+ .arg('"' + result + '"');
}
void
values.pop(); // Dammit, std::stack interface is awkward.
bool val2 = toBool(op2);
+ string result;
if (val1 && val2) {
- values.push("true");
+ result = "true";
} else {
- values.push("false");
+ result = "false";
}
+ values.push(result);
+
+ // Log what we popped and pushed
+ LOG_DEBUG(eval_logger, EVAL_DBG_EXTENDED_CALLS, EVAL_DEBUG_AND)
+ .arg('"' + op1 + '"')
+ .arg("\"" + op2 + "\"")
+ .arg("\"" + result + "\"");
}
void
values.pop(); // Dammit, std::stack interface is awkward.
bool val2 = toBool(op2);
+ string result;
if (val1 || val2) {
- values.push("true");
+ result = "true";
} else {
- values.push("false");
+ result = "false";
}
+ values.push(result);
+
+ // Log what we popped and pushed
+ LOG_DEBUG(eval_logger, EVAL_DBG_EXTENDED_CALLS, EVAL_DEBUG_OR)
+ .arg('"' + op1 + '"')
+ .arg('"' + op2 + '"')
+ .arg('"' + result + '"');
}
OptionPtr TokenRelay6Option::getOption(const Pkt& pkt) {
TokenRelay6Field::evaluate(const Pkt& pkt, ValueStack& values) {
vector<uint8_t> binary;
+ string type_str;
try {
// Check if it's a Pkt6. If it's not the dynamic_cast will
// throw std::bad_cast.
// Now that we have the right type of packet we can
// get the option and return it.
case LINKADDR:
+ type_str = "linkaddr";
binary = pkt6.getRelay6LinkAddress(nest_level_).toBytes();
break;
case PEERADDR:
+ type_str = "peeraddr";
binary = pkt6.getRelay6PeerAddress(nest_level_).toBytes();
break;
}
// The only exception we expect is OutOfRange if the nest
// level is invalid. We push "" in that case.
values.push("");
+ // Log what we pushed
+ LOG_DEBUG(eval_logger, EVAL_DBG_EXTENDED_CALLS, EVAL_DEBUG_RELAY6_RANGE)
+ .arg(type_str)
+ .arg(unsigned(nest_level_))
+ .arg("0x");
return;
}
} catch (const std::bad_cast&) {
memmove(&value[0], &binary[0], binary.size());
}
values.push(value);
+
+ // Log what we pushed
+ LOG_DEBUG(eval_logger, EVAL_DBG_EXTENDED_CALLS, EVAL_DEBUG_RELAY6)
+ .arg(type_str)
+ .arg(unsigned(nest_level_))
+ .arg("0x" + util::encode::encodeHex(std::vector<uint8_t>(value.begin(),
+ value.end())));
}
void
TokenPkt6::evaluate(const Pkt& pkt, ValueStack& values) {
vector<uint8_t> binary;
+ string type_str;
try {
// Check if it's a Pkt6. If it's not the dynamic_cast will throw
// std::bad_cast (failed dynamic_cast returns NULL for pointers and
binary.push_back(0);
binary.push_back(0);
binary.push_back(pkt6.getType());
+ type_str = "msgtype";
break;
}
case TRANSID: {
binary.push_back((transid >> 16) & 0xFF);
binary.push_back((transid >> 8) & 0xFF);
binary.push_back(transid & 0xFF);
+ type_str = "transid";
break;
}
default:
value.resize(binary.size());
memmove(&value[0], &binary[0], binary.size());
values.push(value);
+
+ // Log what we pushed
+ LOG_DEBUG(eval_logger, EVAL_DBG_EXTENDED_CALLS, EVAL_DEBUG_PKT6)
+ .arg(type_str)
+ .arg("0x" + util::encode::encodeHex(std::vector<uint8_t>(value.begin(),
+ value.end())));
}