Browse Source

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

Marcin Siodelski 11 years ago
parent
commit
ad0866f984

+ 9 - 73
src/lib/dhcp/tests/pkt_filter_inet_unittest.cc

@@ -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

+ 9 - 80
src/lib/dhcp/tests/pkt_filter_lpf_unittest.cc

@@ -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

+ 84 - 2
src/lib/dhcp/tests/pkt_filter_test_utils.cc

@@ -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
@@ -57,6 +91,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.
     ASSERT_GE(sock, 0);
@@ -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);

+ 23 - 2
src/lib/dhcp/tests/pkt_filter_test_utils.h

@@ -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.
     ///