Commit ad0866f9 authored by Marcin Siodelski's avatar Marcin Siodelski
Browse files

[2765] Implemented common utility functions for the PktFilter tests.

parent 18369354
......@@ -75,27 +75,6 @@ TEST_F(PktFilterInetTest, openSocket) {
// This test verifies that the packet is correctly sent over the INET
// datagram socket.
TEST_F(PktFilterInetTest, send) {
// Let's create a DHCPv4 packet.
Pkt4Ptr pkt(new Pkt4(DHCPOFFER, 0));
ASSERT_TRUE(pkt);
// Set required fields.
pkt->setLocalAddr(IOAddress("127.0.0.1"));
pkt->setRemoteAddr(IOAddress("127.0.0.1"));
pkt->setRemotePort(PORT);
pkt->setLocalPort(PORT + 1);
pkt->setIndex(ifindex_);
pkt->setIface(ifname_);
pkt->setHops(6);
pkt->setSecs(42);
pkt->setCiaddr(IOAddress("192.0.2.1"));
pkt->setSiaddr(IOAddress("192.0.2.2"));
pkt->setYiaddr(IOAddress("192.0.2.3"));
pkt->setGiaddr(IOAddress("192.0.2.4"));
// Create the on-wire data.
ASSERT_NO_THROW(pkt->pack());
// Packet will be sent over loopback interface.
Iface iface(ifname_, ifindex_);
IOAddress addr("127.0.0.1");
......@@ -109,7 +88,7 @@ TEST_F(PktFilterInetTest, send) {
ASSERT_GE(sock_info_.sockfd_, 0);
// Send the packet over the socket.
ASSERT_NO_THROW(pkt_filter.send(iface, sock_info_.sockfd_, pkt));
ASSERT_NO_THROW(pkt_filter.send(iface, sock_info_.sockfd_, test_message_));
// Read the data from socket.
fd_set readfds;
......@@ -135,47 +114,16 @@ TEST_F(PktFilterInetTest, send) {
// Parse the packet.
ASSERT_NO_THROW(rcvd_pkt->unpack());
// Verify that the received packet matches sent packet.
EXPECT_EQ(pkt->getHops(), rcvd_pkt->getHops());
EXPECT_EQ(pkt->getOp(), rcvd_pkt->getOp());
EXPECT_EQ(pkt->getSecs(), rcvd_pkt->getSecs());
EXPECT_EQ(pkt->getFlags(), rcvd_pkt->getFlags());
EXPECT_EQ(pkt->getCiaddr(), rcvd_pkt->getCiaddr());
EXPECT_EQ(pkt->getSiaddr(), rcvd_pkt->getSiaddr());
EXPECT_EQ(pkt->getYiaddr(), rcvd_pkt->getYiaddr());
EXPECT_EQ(pkt->getGiaddr(), rcvd_pkt->getGiaddr());
EXPECT_EQ(pkt->getTransid(), rcvd_pkt->getTransid());
EXPECT_TRUE(pkt->getSname() == rcvd_pkt->getSname());
EXPECT_TRUE(pkt->getFile() == rcvd_pkt->getFile());
EXPECT_EQ(pkt->getHtype(), rcvd_pkt->getHtype());
EXPECT_EQ(pkt->getHlen(), rcvd_pkt->getHlen());
// Check if the received message is correct.
testRcvdMessage(rcvd_pkt);
}
// This test verifies that the DHCPv4 packet is correctly received via
// INET datagram socket and that it matches sent packet.
TEST_F(PktFilterInetTest, receive) {
// Let's create a DHCPv4 packet.
Pkt4Ptr pkt(new Pkt4(DHCPOFFER, 0));
ASSERT_TRUE(pkt);
// Set required fields.
pkt->setLocalAddr(IOAddress("127.0.0.1"));
pkt->setRemoteAddr(IOAddress("127.0.0.1"));
pkt->setRemotePort(PORT);
pkt->setLocalPort(PORT + 1);
pkt->setIndex(ifindex_);
pkt->setIface(ifname_);
pkt->setHops(6);
pkt->setSecs(42);
pkt->setCiaddr(IOAddress("192.0.2.1"));
pkt->setSiaddr(IOAddress("192.0.2.2"));
pkt->setYiaddr(IOAddress("192.0.2.3"));
pkt->setGiaddr(IOAddress("192.0.2.4"));
// Create the on-wire data.
ASSERT_NO_THROW(pkt->pack());
// Packet will be sent over loopback interface.
// Packet will be received over loopback interface.
Iface iface(ifname_, ifindex_);
IOAddress addr("127.0.0.1");
......@@ -187,8 +135,8 @@ TEST_F(PktFilterInetTest, receive) {
sock_info_ = pkt_filter.openSocket(iface, addr, PORT, false, false);
ASSERT_GE(sock_info_.sockfd_, 0);
// Send the packet over the socket.
ASSERT_NO_THROW(pkt_filter.send(iface, sock_info_.sockfd_, pkt));
// Send a DHCPv4 message to the local loopback address and server's port.
sendMessage();
// Receive the packet.
Pkt4Ptr rcvd_pkt = pkt_filter.receive(iface, sock_info_);
......@@ -198,20 +146,8 @@ TEST_F(PktFilterInetTest, receive) {
// Parse the packet.
ASSERT_NO_THROW(rcvd_pkt->unpack());
// Verify that the received packet matches sent packet.
EXPECT_EQ(pkt->getHops(), rcvd_pkt->getHops());
EXPECT_EQ(pkt->getOp(), rcvd_pkt->getOp());
EXPECT_EQ(pkt->getSecs(), rcvd_pkt->getSecs());
EXPECT_EQ(pkt->getFlags(), rcvd_pkt->getFlags());
EXPECT_EQ(pkt->getCiaddr(), rcvd_pkt->getCiaddr());
EXPECT_EQ(pkt->getSiaddr(), rcvd_pkt->getSiaddr());
EXPECT_EQ(pkt->getYiaddr(), rcvd_pkt->getYiaddr());
EXPECT_EQ(pkt->getGiaddr(), rcvd_pkt->getGiaddr());
EXPECT_EQ(pkt->getTransid(), rcvd_pkt->getTransid());
EXPECT_TRUE(pkt->getSname() == rcvd_pkt->getSname());
EXPECT_TRUE(pkt->getFile() == rcvd_pkt->getFile());
EXPECT_EQ(pkt->getHtype(), rcvd_pkt->getHtype());
EXPECT_EQ(pkt->getHlen(), rcvd_pkt->getHlen());
// Check if the received message is correct.
testRcvdMessage(rcvd_pkt);
}
} // anonymous namespace
......@@ -103,32 +103,6 @@ TEST_F(PktFilterLPFTest, DISABLED_openSocket) {
// This test verifies correctness of sending DHCP packet through the raw
// socket, whereby all IP stack headers are hand-crafted.
TEST_F(PktFilterLPFTest, DISABLED_send) {
// Let's create a DHCPv4 packet.
Pkt4Ptr pkt(new Pkt4(DHCPOFFER, 0));
ASSERT_TRUE(pkt);
// Set required fields.
// By setting the local address to broadcast we simulate the
// typical scenario when client's request was send to broadcast
// address and server by default used it as a source address
// in its response. The send() function should be able to detect
// it and correct the source address.
pkt->setLocalAddr(IOAddress("255.255.255.255"));
pkt->setRemoteAddr(IOAddress("127.0.0.1"));
pkt->setRemotePort(PORT);
pkt->setLocalPort(PORT + 1);
pkt->setIndex(ifindex_);
pkt->setIface(ifname_);
pkt->setHops(6);
pkt->setSecs(42);
pkt->setCiaddr(IOAddress("192.0.2.1"));
pkt->setSiaddr(IOAddress("192.0.2.2"));
pkt->setYiaddr(IOAddress("192.0.2.3"));
pkt->setGiaddr(IOAddress("192.0.2.4"));
// Create the on-wire data.
ASSERT_NO_THROW(pkt->pack());
// Packet will be sent over loopback interface.
Iface iface(ifname_, ifindex_);
IOAddress addr("127.0.0.1");
......@@ -144,7 +118,7 @@ TEST_F(PktFilterLPFTest, DISABLED_send) {
ASSERT_GE(sock_info_.sockfd_, 0);
// Send the packet over the socket.
ASSERT_NO_THROW(pkt_filter.send(iface, sock_info_.sockfd_, pkt));
ASSERT_NO_THROW(pkt_filter.send(iface, sock_info_.sockfd_, test_message_));
// Read the data from socket.
fd_set readfds;
......@@ -180,48 +154,15 @@ TEST_F(PktFilterLPFTest, DISABLED_send) {
// Parse the packet.
ASSERT_NO_THROW(rcvd_pkt->unpack());
// Verify that the received packet matches sent packet.
EXPECT_EQ(pkt->getHops(), rcvd_pkt->getHops());
EXPECT_EQ(pkt->getOp(), rcvd_pkt->getOp());
EXPECT_EQ(pkt->getSecs(), rcvd_pkt->getSecs());
EXPECT_EQ(pkt->getFlags(), rcvd_pkt->getFlags());
EXPECT_EQ(pkt->getCiaddr(), rcvd_pkt->getCiaddr());
EXPECT_EQ(pkt->getSiaddr(), rcvd_pkt->getSiaddr());
EXPECT_EQ(pkt->getYiaddr(), rcvd_pkt->getYiaddr());
EXPECT_EQ(pkt->getGiaddr(), rcvd_pkt->getGiaddr());
EXPECT_EQ(pkt->getTransid(), rcvd_pkt->getTransid());
EXPECT_TRUE(pkt->getSname() == rcvd_pkt->getSname());
EXPECT_TRUE(pkt->getFile() == rcvd_pkt->getFile());
EXPECT_EQ(pkt->getHtype(), rcvd_pkt->getHtype());
EXPECT_EQ(pkt->getHlen(), rcvd_pkt->getHlen());
// Check if the received message is correct.
testRcvdMessage(rcvd_pkt);
}
// This test verifies correctness of reception of the DHCP packet over
// raw socket, whereby all IP stack headers are hand-crafted.
TEST_F(PktFilterLPFTest, DISABLED_receive) {
// Let's create a DHCPv4 packet.
Pkt4Ptr pkt(new Pkt4(DHCPOFFER, 0));
ASSERT_TRUE(pkt);
// Set required fields.
pkt->setLocalAddr(IOAddress("127.0.0.1"));
pkt->setRemoteAddr(IOAddress("127.0.0.1"));
pkt->setRemotePort(PORT);
pkt->setLocalPort(PORT + 1);
pkt->setIndex(ifindex_);
pkt->setIface(ifname_);
pkt->setHops(6);
pkt->setSecs(42);
pkt->setCiaddr(IOAddress("192.0.2.1"));
pkt->setSiaddr(IOAddress("192.0.2.2"));
pkt->setYiaddr(IOAddress("192.0.2.3"));
pkt->setGiaddr(IOAddress("192.0.2.4"));
// Create the on-wire data.
ASSERT_NO_THROW(pkt->pack());
// Packet will be sent over loopback interface.
// Packet will be received over loopback interface.
Iface iface(ifname_, ifindex_);
IOAddress addr("127.0.0.1");
......@@ -233,10 +174,10 @@ TEST_F(PktFilterLPFTest, DISABLED_receive) {
sock_info_ = pkt_filter.openSocket(iface, addr, PORT, false, false);
ASSERT_GE(sock_info_.sockfd_, 0);
// Send the packet over the socket.
ASSERT_NO_THROW(pkt_filter.send(iface, sock_info_.sockfd_, pkt));
// Send DHCPv4 message to the local loopback address and server's port.
sendMessage();
// Receive the packet.
// Receive the packet using LPF packet filter.
Pkt4Ptr rcvd_pkt = pkt_filter.receive(iface, sock_info_);
// Check that the packet has been correctly received.
ASSERT_TRUE(rcvd_pkt);
......@@ -244,20 +185,8 @@ TEST_F(PktFilterLPFTest, DISABLED_receive) {
// Parse the packet.
ASSERT_NO_THROW(rcvd_pkt->unpack());
// Verify that the received packet matches sent packet.
EXPECT_EQ(pkt->getHops(), rcvd_pkt->getHops());
EXPECT_EQ(pkt->getOp(), rcvd_pkt->getOp());
EXPECT_EQ(pkt->getSecs(), rcvd_pkt->getSecs());
EXPECT_EQ(pkt->getFlags(), rcvd_pkt->getFlags());
EXPECT_EQ(pkt->getCiaddr(), rcvd_pkt->getCiaddr());
EXPECT_EQ(pkt->getSiaddr(), rcvd_pkt->getSiaddr());
EXPECT_EQ(pkt->getYiaddr(), rcvd_pkt->getYiaddr());
EXPECT_EQ(pkt->getGiaddr(), rcvd_pkt->getGiaddr());
EXPECT_EQ(pkt->getTransid(), rcvd_pkt->getTransid());
EXPECT_TRUE(pkt->getSname() == rcvd_pkt->getSname());
EXPECT_TRUE(pkt->getFile() == rcvd_pkt->getFile());
EXPECT_EQ(pkt->getHtype(), rcvd_pkt->getHtype());
EXPECT_EQ(pkt->getHlen(), rcvd_pkt->getHlen());
// Check if the received message is correct.
testRcvdMessage(rcvd_pkt);
}
} // anonymous namespace
......@@ -12,19 +12,24 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <asiolink/io_address.h>
#include <dhcp/pkt4.h>
#include <dhcp/tests/pkt_filter_test_utils.h>
using namespace isc::asiolink;
namespace isc {
namespace dhcp {
namespace test {
PktFilterTest::PktFilterTest(const uint16_t port)
: port_(port),
sock_info_(isc::asiolink::IOAddress("127.0.0.1"), port, -1, -1) {
sock_info_(isc::asiolink::IOAddress("127.0.0.1"), port, -1, -1),
send_msg_sock_(-1) {
// Initialize ifname_ and ifindex_.
loInit();
// Initialize test_message_.
initTestMessage();
}
PktFilterTest::~PktFilterTest() {
......@@ -36,6 +41,35 @@ PktFilterTest::~PktFilterTest() {
if (sock_info_.fallbackfd_ >=0) {
close(sock_info_.fallbackfd_);
}
if (send_msg_sock_ >= 0) {
close(send_msg_sock_);
}
}
void
PktFilterTest::initTestMessage() {
// Let's create a DHCPv4 message instance.
test_message_.reset(new Pkt4(DHCPOFFER, 0));
// Set required fields.
test_message_->setLocalAddr(IOAddress("127.0.0.1"));
test_message_->setRemoteAddr(IOAddress("127.0.0.1"));
test_message_->setRemotePort(port_);
test_message_->setLocalPort(port_ + 1);
test_message_->setIndex(ifindex_);
test_message_->setIface(ifname_);
test_message_->setHops(6);
test_message_->setSecs(42);
test_message_->setCiaddr(IOAddress("192.0.2.1"));
test_message_->setSiaddr(IOAddress("192.0.2.2"));
test_message_->setYiaddr(IOAddress("192.0.2.3"));
test_message_->setGiaddr(IOAddress("192.0.2.4"));
try {
test_message_->pack();
} catch (const isc::Exception& ex) {
ADD_FAILURE() << "failed to create test message for PktFilterTest";
}
}
void
......@@ -56,6 +90,37 @@ PktFilterTest::loInit() {
}
}
void
PktFilterTest::sendMessage() {
// Packet will be sent over loopback interface.
Iface iface(ifname_, ifindex_);
IOAddress addr("127.0.0.1");
struct sockaddr_in addr4;
memset(&addr4, 0, sizeof(sockaddr));
addr4.sin_family = AF_INET;
addr4.sin_port = htons(port_ + 1);
send_msg_sock_ = socket(AF_INET, SOCK_DGRAM, 0);
ASSERT_GE(send_msg_sock_, 0);
ASSERT_GE(bind(send_msg_sock_, (struct sockaddr *)&addr4,
sizeof(addr4)), 0);
struct sockaddr_in dest_addr4;
memset(&dest_addr4, 0, sizeof(sockaddr));
dest_addr4.sin_family = AF_INET;
dest_addr4.sin_port = htons(port_);
ASSERT_EQ(sendto(send_msg_sock_, test_message_->getBuffer().getData(),
test_message_->getBuffer().getLength(), 0,
reinterpret_cast<struct sockaddr*>(&dest_addr4),
sizeof(sockaddr)), test_message_->getBuffer().getLength());
close(send_msg_sock_);
send_msg_sock_ = -1;
}
void
PktFilterTest::testDgramSocket(const int sock) const {
// Check that socket has been opened.
......@@ -84,6 +149,23 @@ PktFilterTest::testDgramSocket(const int sock) const {
EXPECT_EQ(SOCK_DGRAM, sock_type);
}
void
PktFilterTest::testRcvdMessage(const Pkt4Ptr& rcvd_msg) const {
EXPECT_EQ(test_message_->getHops(), rcvd_msg->getHops());
EXPECT_EQ(test_message_->getOp(), rcvd_msg->getOp());
EXPECT_EQ(test_message_->getSecs(), rcvd_msg->getSecs());
EXPECT_EQ(test_message_->getFlags(), rcvd_msg->getFlags());
EXPECT_EQ(test_message_->getCiaddr(), rcvd_msg->getCiaddr());
EXPECT_EQ(test_message_->getSiaddr(), rcvd_msg->getSiaddr());
EXPECT_EQ(test_message_->getYiaddr(), rcvd_msg->getYiaddr());
EXPECT_EQ(test_message_->getGiaddr(), rcvd_msg->getGiaddr());
EXPECT_EQ(test_message_->getTransid(), rcvd_msg->getTransid());
EXPECT_TRUE(test_message_->getSname() == rcvd_msg->getSname());
EXPECT_TRUE(test_message_->getFile() == rcvd_msg->getFile());
EXPECT_EQ(test_message_->getHtype(), rcvd_msg->getHtype());
EXPECT_EQ(test_message_->getHlen(), rcvd_msg->getHlen());
}
bool
PktFilterStub::isDirectResponseSupported() const {
return (true);
......
......@@ -50,12 +50,25 @@ public:
/// Closes open sockets (if any).
virtual ~PktFilterTest();
/// @brief Initializes DHCPv4 message used by tests.
void initTestMessage();
/// @brief Detect loopback interface.
///
/// @todo this function will be removed once cross-OS interface
/// detection is implemented
void loInit();
/// @brief Sends a single DHCPv4 message to the loopback address.
///
/// This function opens a datagram socket and binds it to the local loopback
/// address and client port. The client's port is assumed to be port_ + 1.
/// The send_msg_sock_ member holds the socket descriptor so as the socket
/// is closed automatically in the destructor. If the function succeeds to
/// send a DHCPv4 message, the socket is closed so as the function can be
/// called again within the same test.
void sendMessage();
/// @brief Test that the datagram socket is opened correctly.
///
/// This function is used by multiple tests.
......@@ -63,10 +76,18 @@ public:
/// @param sock A descriptor of the open socket.
void testDgramSocket(const int sock) const;
/// @brief Checks if the received message matches the test_message_.
///
/// @param rcvd_msg An instance of the message to be tested.
void testRcvdMessage(const Pkt4Ptr& rcvd_msg) const;
std::string ifname_; ///< Loopback interface name
uint16_t ifindex_; ///< Loopback interface index.
uint16_t port_; ///< A port number used for the test.
isc::dhcp::SocketInfo sock_info_; ///< A structure holding socket information.
isc::dhcp::SocketInfo sock_info_; ///< A structure holding socket info.
int send_msg_sock_; ///< Holds a descriptor of the socket used by
///< sendMessage function.
Pkt4Ptr test_message_; ///< A DHCPv4 message used by tests.
};
......@@ -90,7 +111,7 @@ public:
/// @brief Simulate opening of the socket.
///
/// This function simulates openinga primary socket. In reality, it doesn't
/// This function simulates opening a primary socket. In reality, it doesn't
/// open a socket but the socket descriptor returned in the SocketInfo
/// structure is always set to 0.
///
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment