// Copyright (C) 2015 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 #include #include #include #include #include #include #include #include #include using namespace std; using namespace isc::dhcp; namespace { /// @brief Test fixture for testing Tokens. /// /// This class provides several convenience objects to be used during testing /// of the Token family of classes. class TokenTest : public ::testing::Test { public: /// @brief Initializes Pkt4,Pkt6 and options that can be useful for /// evaluation tests. TokenTest() { pkt4_.reset(new Pkt4(DHCPDISCOVER, 12345)); pkt6_.reset(new Pkt6(DHCPV6_SOLICIT, 12345)); // Add options with easily identifiable strings in them option_str4_.reset(new OptionString(Option::V4, 100, "hundred4")); option_str6_.reset(new OptionString(Option::V6, 100, "hundred6")); pkt4_->addOption(option_str4_); pkt6_->addOption(option_str6_); } TokenPtr t_; ///< Just a convenience pointer ValueStack values_; ///< evaluated values will be stored here Pkt4Ptr pkt4_; ///< A stub DHCPv4 packet Pkt6Ptr pkt6_; ///< A stub DHCPv6 packet OptionPtr option_str4_; ///< A string option for DHCPv4 OptionPtr option_str6_; ///< A string option for DHCPv6 /// @todo: Add more option types here }; // 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) { // Store constant string "foo" in the TokenString object. ASSERT_NO_THROW(t_.reset(new TokenString("foo"))); // Make sure that the token can be evaluated without exceptions. ASSERT_NO_THROW(t_->evaluate(*pkt4_, values_)); // Check that the evaluation put its value on the values stack. ASSERT_EQ(1, values_.size()); EXPECT_EQ("foo", values_.top()); } // This simple test checks that a TokenString, representing a constant string, // can be used in Pkt6 evaluation. (The actual packet is not used) TEST_F(TokenTest, string6) { // Store constant string "foo" in the TokenString object. ASSERT_NO_THROW(t_.reset(new TokenString("foo"))); // Make sure that the token can be evaluated without exceptions. ASSERT_NO_THROW(t_->evaluate(*pkt6_, values_)); // Check that the evaluation put its value on the values stack. ASSERT_EQ(1, values_.size()); EXPECT_EQ("foo", values_.top()); } // This test checks if a token representing an option value is able to extract // the option from a packet and properly store the option's value. TEST_F(TokenTest, optionString) { TokenPtr found; TokenPtr not_found; // The packets we use have option 100 with a string in them. ASSERT_NO_THROW(found.reset(new TokenOption(100))); ASSERT_NO_THROW(not_found.reset(new TokenOption(101))); // This should evaluate to the content of the option 100 (i.e. "hundred4") ASSERT_NO_THROW(found->evaluate(*pkt4_, values_)); // This should evaluate to "" as there is no option 101. ASSERT_NO_THROW(not_found->evaluate(*pkt4_, values_)); // There should be 2 values evaluated. ASSERT_EQ(2, values_.size()); // This is a stack, so the pop order is inversed. We should get the empty // string first. EXPECT_EQ("", values_.top()); values_.pop(); // Then the content of the option 100. EXPECT_EQ("hundred4", values_.top()); } // This test checks if a token representing an == operator is able to // compare two values (with incorrectly built stack). TEST_F(TokenTest, optionEqualInvalid) { ASSERT_NO_THROW(t_.reset(new TokenEqual())); // CASE 1: There's not enough values on the stack. == is an operator that // takes two parameters. There are 0 on the stack. EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalBadStack); // CASE 2: One value is still not enough. values_.push("foo"); EXPECT_THROW(t_->evaluate(*pkt4_, values_), EvalBadStack); } // This test checks if a token representing an == operator is able to // compare two different values. TEST_F(TokenTest, optionEqualFalse) { ASSERT_NO_THROW(t_.reset(new TokenEqual())); values_.push("foo"); values_.push("bar"); EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_)); // After evaluation there should be a single value that represents // result of "foo" == "bar" comparision. ASSERT_EQ(1, values_.size()); EXPECT_EQ("false", values_.top()); } // This test checks if a token representing an == operator is able to // compare two identical values. TEST_F(TokenTest, optionEqualTrue) { ASSERT_NO_THROW(t_.reset(new TokenEqual())); values_.push("foo"); values_.push("foo"); EXPECT_NO_THROW(t_->evaluate(*pkt4_, values_)); // After evaluation there should be a single value that represents // result of "foo" == "foo" comparision. ASSERT_EQ(1, values_.size()); EXPECT_EQ("true", values_.top()); } };