/// @param test_start The postion to start when getting a substring
/// @param test_length The length of the substring to get
/// @param result_string The expected result of the eval
+ /// @param should_throw The eval will throw
void verifySubstringEval(const std::string& test_string,
const std::string& test_start,
const std::string& test_length,
- const std::string& result_string) {
+ const std::string& result_string,
+ bool should_throw = false) {
// create the token
ASSERT_NO_THROW(t_.reset(new TokenSubstring()));
values_.push(test_length);
// evaluate the token
- EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
-
- // verify results
- ASSERT_EQ(1, values_.size());
- EXPECT_EQ(result_string, values_.top());
-
- // remove result
- values_.pop();
+ if (should_throw) {
+ EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalTypeError);
+ ASSERT_EQ(0, values_.size());
+ } else {
+ EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_));
+
+ // verify results
+ ASSERT_EQ(1, values_.size());
+ EXPECT_EQ(result_string, values_.top());
+
+ // remove result
+ values_.pop();
+ }
}
/// @todo: Add more option types here
// Check what happens if we use strings that aren't numbers for start or length
// We should return the empty string
TEST_F(TokenTest, substringBadParams) {
- verifySubstringEval("foobar", "0ick", "all", "");
- verifySubstringEval("foobar", "ick0", "all", "");
- verifySubstringEval("foobar", "ick", "all", "");
- verifySubstringEval("foobar", "0", "ick", "");
- verifySubstringEval("foobar", "0", "0ick", "");
- verifySubstringEval("foobar", "0", "ick0", "");
- verifySubstringEval("foobar", "0", "allaboard", "");
+ verifySubstringEval("foobar", "0ick", "all", "", true);
+ verifySubstringEval("foobar", "ick0", "all", "", true);
+ verifySubstringEval("foobar", "ick", "all", "", true);
+ verifySubstringEval("foobar", "0", "ick", "", true);
+ verifySubstringEval("foobar", "0", "0ick", "", true);
+ verifySubstringEval("foobar", "0", "ick0", "", true);
+ verifySubstringEval("foobar", "0", "allaboard", "", true);
}
// lastly check that we don't get anything if the string is empty or
int length;
try {
start_pos = boost::lexical_cast<int>(start_str);
+ } catch (const boost::bad_lexical_cast&) {
+ isc_throw(EvalTypeError, "the parameter '" << start_str
+ << "' for the starting postion of the substring "
+ << "couldn't be converted to an integer.");
+ }
+ try {
if (len_str == "all") {
length = string_str.length();
} else {
length = boost::lexical_cast<int>(len_str);
}
} catch (const boost::bad_lexical_cast&) {
- LOG_DEBUG(eval_logger, EVAL_DBG_TRACE,
- EVAL_SUBSTRING_BAD_PARAM_CONVERSION)
- .arg(start_str)
- .arg(len_str);
-
- values.push("");
- return;
+ isc_throw(EvalTypeError, "the parameter '" << len_str
+ << "' for the length of the substring "
+ << "couldn't be converted to an integer.");
}
const int string_length = string_str.length();
/// Evaluated values are stored as a stack of strings
typedef std::stack<std::string> ValueStack;
-/// @brief EvalStackError is thrown when more or less parameters are on the
+/// @brief EvalBadStack is thrown when more or less parameters are on the
/// stack than expected.
class EvalBadStack : public Exception {
public:
isc::Exception(file, line, what) { };
};
+/// @brief EvalTypeError is thrown when a value on the stack has a content
+/// with an unexpected type.
+class EvalTypeError : public Exception {
+public:
+ EvalTypeError(const char* file, size_t line, const char* what) :
+ isc::Exception(file, line, what) { };
+};
+
/// @brief Base class for all tokens
///
/// It provides an interface for all tokens and storage for string representation
/// - -1, -4 => "ooba"
///
/// @throw EvalBadStack if there are less than 3 values on stack
+ /// @throw EvalTypeError if start is not a number or length a number or
+ /// the special value "all".
///
/// @param pkt (unused)
/// @param values - stack of values (3 arguments will be popped, 1 result