Parcourir la source

[trac878] Implemented gtest tests for recently added dhcpv6 classes:
Addr6, Pkt6, IfaceMgr, Dhcpv6Srv. Interface detection is still not
implemented, so some parts of the tests are stubbed.

Tomek Mrugalski il y a 14 ans
Parent
commit
0caae46ef0

+ 1 - 3
src/bin/auth/tests/Makefile.am

@@ -19,9 +19,7 @@ TESTS =
 if HAVE_GTEST
 if HAVE_GTEST
 
 
 TESTS += run_unittests
 TESTS += run_unittests
-run_unittests_SOURCES = $(top_srcdir)/src/lib/dns/tests/unittest_util.h
-run_unittests_SOURCES += $(top_srcdir)/src/lib/dns/tests/unittest_util.cc
-run_unittests_SOURCES += ../auth_srv.h ../auth_srv.cc
+run_unittests_SOURCES  = ../auth_srv.h ../auth_srv.cc
 run_unittests_SOURCES += ../auth_log.h ../auth_log.cc
 run_unittests_SOURCES += ../auth_log.h ../auth_log.cc
 run_unittests_SOURCES += ../query.h ../query.cc
 run_unittests_SOURCES += ../query.h ../query.cc
 run_unittests_SOURCES += ../change_user.h ../change_user.cc
 run_unittests_SOURCES += ../change_user.h ../change_user.cc

+ 4 - 0
src/bin/dhcp6/dhcp6_srv.cc

@@ -24,6 +24,10 @@ Dhcpv6Srv::Dhcpv6Srv() {
     cout << "Initialization" << endl;
     cout << "Initialization" << endl;
 }
 }
 
 
+Dhcpv6Srv::~Dhcpv6Srv() {
+    cout << "DHCPv6 Srv shutdown." << endl;
+}
+
 bool Dhcpv6Srv::run() {
 bool Dhcpv6Srv::run() {
     while (true) {
     while (true) {
         Pkt6 * pkt;
         Pkt6 * pkt;

+ 7 - 7
src/bin/dhcp6/iface_mgr.h

@@ -45,10 +45,6 @@ namespace isc {
         };
         };
         typedef std::list<Iface> IfaceLst;
         typedef std::list<Iface> IfaceLst;
 
 
-    private:
-        IfaceMgr(); // don't create IfaceMgr directly, use instance() method
-        ~IfaceMgr();
-    public:
         static IfaceMgr& instance();
         static IfaceMgr& instance();
         static void instanceCreate();
         static void instanceCreate();
 
 
@@ -67,17 +63,21 @@ namespace isc {
         bool send(Pkt6 &pkt);
         bool send(Pkt6 &pkt);
         Pkt6 * receive();
         Pkt6 * receive();
 
 
+	// don't use private, we need derived classes in tests
     protected:
     protected:
+        IfaceMgr(); // don't create IfaceMgr directly, use instance() method
+        ~IfaceMgr();
+
         void detectIfaces();
         void detectIfaces();
 
 
         // XXX: having 2 maps (ifindex->iface and ifname->iface would)
         // XXX: having 2 maps (ifindex->iface and ifname->iface would)
         //      probably be better for performance reasons
         //      probably be better for performance reasons
         IfaceLst ifaces_;
         IfaceLst ifaces_;
-    private:
+
         static IfaceMgr * instance_;
         static IfaceMgr * instance_;
 
 
-        int recvsock_; // XXX: should be fd_set eventually, but we 2 sockets
-        int sendsock_; // will do for until next release
+        int recvsock_; // XXX: should be fd_set eventually, but we have only
+        int sendsock_; // 2 sockets for now. Will do for until next release
 
 
         char * control_buf_;
         char * control_buf_;
         int control_buf_len_;
         int control_buf_len_;

+ 15 - 7
src/bin/dhcp6/pkt6.cc

@@ -18,20 +18,28 @@
 
 
 namespace isc {
 namespace isc {
 
 
+    /**
+     * constructor.
+     *
+     * Note: Pkt6 will take ownership of any data passed
+     *
+     * @param data
+     * @param dataLen
+     */
     Pkt6::Pkt6(char * data, int dataLen) {
     Pkt6::Pkt6(char * data, int dataLen) {
-        data_ = data;
-        dataLen_ = dataLen;
+	data_ = data;
+	dataLen_ = dataLen;
     }
     }
 
 
     Pkt6::Pkt6(int dataLen) {
     Pkt6::Pkt6(int dataLen) {
-        data_ = new char[dataLen];
-        dataLen_ = dataLen;
+	data_ = new char[dataLen];
+	dataLen_ = dataLen;
     }
     }
 
 
     Pkt6::~Pkt6() {
     Pkt6::~Pkt6() {
-        if (data_) {
-            delete [] data_;
-        }
+	if (data_) {
+	    delete [] data_;
+	}
 
 
     }
     }
 
 

+ 21 - 18
src/bin/dhcp6/tests/Makefile.am

@@ -40,24 +40,27 @@ endif
 TESTS =
 TESTS =
 if HAVE_GTEST
 if HAVE_GTEST
 
 
-TESTS += run_unittests
-
-run_unittests_SOURCES  = ../addr6.h ../addr6.cc
-run_unittests_SOURCES += ../pkt6.h ../pkt6.cc
-run_unittests_SOURCES += ../iface_mgr.h ../iface_mgr.cc
-run_unittests_SOURCES += ../dhcp6_srv.h ../dhcp6_srv.cc
-run_unittests_SOURCES += addr6_unittest.cc
-run_unittests_SOURCES += run_unittests.cc
-
-run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
-run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
-run_unittests_LDADD = $(GTEST_LDADD)
-run_unittests_LDADD += $(SQLITE_LIBS)
-run_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
-run_unittests_LDADD += $(top_builddir)/src/lib/config/libcfgclient.la
-run_unittests_LDADD += $(top_builddir)/src/lib/cc/libcc.la
-run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
-run_unittests_LDADD += $(top_builddir)/src/lib/log/liblog.la
+TESTS += dhcp6_unittests
+
+dhcp6_unittests_SOURCES  = ../addr6.h ../addr6.cc
+dhcp6_unittests_SOURCES += ../pkt6.h ../pkt6.cc
+dhcp6_unittests_SOURCES += ../iface_mgr.h ../iface_mgr.cc
+dhcp6_unittests_SOURCES += ../dhcp6_srv.h ../dhcp6_srv.cc
+dhcp6_unittests_SOURCES += dhcp6_unittests.cc
+dhcp6_unittests_SOURCES += addr6_unittest.cc
+dhcp6_unittests_SOURCES += pkt6_unittest.cc
+dhcp6_unittests_SOURCES += iface_mgr_unittest.cc
+dhcp6_unittests_SOURCES += dhcp6_srv_unittest.cc
+
+dhcp6_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
+dhcp6_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
+dhcp6_unittests_LDADD = $(GTEST_LDADD)
+dhcp6_unittests_LDADD += $(SQLITE_LIBS)
+dhcp6_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
+dhcp6_unittests_LDADD += $(top_builddir)/src/lib/config/libcfgclient.la
+dhcp6_unittests_LDADD += $(top_builddir)/src/lib/cc/libcc.la
+dhcp6_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
+dhcp6_unittests_LDADD += $(top_builddir)/src/lib/log/liblog.la
 endif
 endif
 
 
 noinst_PROGRAMS = $(TESTS)
 noinst_PROGRAMS = $(TESTS)

+ 10 - 10
src/bin/dhcp6/tests/addr6_unittest.cc

@@ -25,13 +25,13 @@
 using namespace std;
 using namespace std;
 using namespace isc;
 using namespace isc;
 
 
+// empty class for now, but may be extended once Addr6 becomes bigger
 class Addr6Test : public ::testing::Test {
 class Addr6Test : public ::testing::Test {
 public:
 public:
     Addr6Test() {
     Addr6Test() {
     }
     }
 };
 };
 
 
-
 TEST_F(Addr6Test, constructor) {
 TEST_F(Addr6Test, constructor) {
 
 
     char buf[16];
     char buf[16];
@@ -56,14 +56,14 @@ TEST_F(Addr6Test, mcast_linklocal) {
     Addr6 global("2001:db8:1::dead:beef", true);
     Addr6 global("2001:db8:1::dead:beef", true);
     Addr6 local("fe80::face:b00c", true);
     Addr6 local("fe80::face:b00c", true);
 
 
-    EXPECT_EQ(mcast.multicast(), true);
-    EXPECT_EQ(mcast.linkLocal(), false);
+    EXPECT_TRUE(mcast.multicast());
+    EXPECT_FALSE(mcast.linkLocal());
 
 
-    EXPECT_EQ(global.multicast(), false);
-    EXPECT_EQ(global.linkLocal(), false);
+    EXPECT_FALSE(global.multicast());
+    EXPECT_FALSE(global.linkLocal());
 
 
-    EXPECT_EQ(local.multicast(), false);
-    EXPECT_EQ(local.linkLocal(), true);
+    EXPECT_FALSE(local.multicast());
+    EXPECT_TRUE(local.linkLocal());
 }
 }
 
 
 TEST_F(Addr6Test, equal) {
 TEST_F(Addr6Test, equal) {
@@ -72,8 +72,8 @@ TEST_F(Addr6Test, equal) {
     Addr6 two("2001:db8:1::abcd");
     Addr6 two("2001:db8:1::abcd");
     Addr6 three("2001:db8:1::4321");
     Addr6 three("2001:db8:1::4321");
 
 
-    EXPECT_EQ( (one==two), true);
-    EXPECT_EQ( (one==three), false);
+    EXPECT_TRUE( one==two );
+    EXPECT_FALSE( one==three );
 }
 }
 
 
 TEST_F(Addr6Test, stream) {
 TEST_F(Addr6Test, stream) {
@@ -84,5 +84,5 @@ TEST_F(Addr6Test, stream) {
     stringstream tmp;
     stringstream tmp;
     tmp << addr;
     tmp << addr;
 
 
-    EXPECT_EQ( tmp.str(), plain);
+    EXPECT_STREQ( tmp.str().c_str(), plain.c_str() );
 }
 }

+ 46 - 0
src/bin/dhcp6/tests/dhcp6_srv_unittest.cc

@@ -0,0 +1,46 @@
+// Copyright (C) 2011  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 <config.h>
+#include <iostream>
+#include <sstream>
+
+#include <arpa/inet.h>
+#include <gtest/gtest.h>
+
+
+#include "dhcp6/dhcp6_srv.h"
+
+using namespace std;
+using namespace isc;
+
+class Dhcpv6SrvTest : public ::testing::Test {
+public:
+    Dhcpv6SrvTest() {
+    }
+};
+
+TEST_F(Dhcpv6SrvTest, basic) {
+    // there's almost no code now. What's there provides echo capability 
+    // that is just a proof of concept and will be removed soon
+    // No need to thoroughly test it
+
+    EXPECT_NO_THROW( {
+        Dhcpv6Srv * srv = new Dhcpv6Srv();
+
+	delete srv;
+    });
+    
+}
+

src/bin/dhcp6/tests/run_unittests.cc → src/bin/dhcp6/tests/dhcp6_unittests.cc


+ 196 - 0
src/bin/dhcp6/tests/iface_mgr_unittest.cc

@@ -0,0 +1,196 @@
+// Copyright (C) 2011  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 <config.h>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+
+#include <arpa/inet.h>
+#include <gtest/gtest.h>
+
+#include "dhcp6/addr6.h"
+#include "dhcp6/pkt6.h"
+#include "dhcp6/iface_mgr.h"
+
+using namespace std;
+using namespace isc;
+
+class NakedIfaceMgr: public IfaceMgr {
+    // "naked" Interface Manager, exposes internal fields 
+public:
+    NakedIfaceMgr() { }
+    IfaceLst & getIfacesLst() { return ifaces_; }
+    void setSendSock(int sock) { sendsock_ = sock; }
+    void setRecvSock(int sock) { recvsock_ = sock; }
+};
+
+// dummy class for now, but this will be expanded when needed
+class IfaceMgrTest : public ::testing::Test {
+public:
+    IfaceMgrTest() {
+    }
+};
+
+TEST_F(IfaceMgrTest, basic) {
+    // checks that IfaceManager can be instantiated
+
+    IfaceMgr & ifacemgr = IfaceMgr::instance();
+    ASSERT_TRUE(&ifacemgr != 0);
+}
+
+TEST_F(IfaceMgrTest, ifaceClass) {
+    // basic tests for Iface inner class
+
+    IfaceMgr::Iface * iface = new IfaceMgr::Iface("eth5", 7);
+
+    EXPECT_STREQ("eth5/7", iface->getFullName().c_str());
+
+    delete iface;
+
+}
+
+TEST_F(IfaceMgrTest, getIface) {
+
+    cout << "Interface checks. Please ignore socket binding errors." << endl;
+    NakedIfaceMgr * ifacemgr = new NakedIfaceMgr();
+
+    // interface name, ifindex
+    IfaceMgr::Iface iface1("lo", 1);
+    IfaceMgr::Iface iface2("eth5", 2);
+    IfaceMgr::Iface iface3("en3", 5);
+    IfaceMgr::Iface iface4("e1000g0", 3);
+
+    ifacemgr->getIfacesLst().push_back(iface1);
+    ifacemgr->getIfacesLst().push_back(iface2);
+    ifacemgr->getIfacesLst().push_back(iface3);
+    ifacemgr->getIfacesLst().push_back(iface4);
+
+    // check that interface can be retrieved by ifindex
+    IfaceMgr::Iface * tmp = ifacemgr->getIface(5);
+    // ASSERT_NE(NULL, tmp); is not supported. hmmmm.
+    ASSERT_TRUE( tmp != NULL );
+
+    EXPECT_STREQ( "en3", tmp->name_.c_str() );
+    EXPECT_EQ(5, tmp->ifindex_);
+
+    // check that interface can be retrieved by name
+    tmp = ifacemgr->getIface("lo");
+    ASSERT_TRUE( tmp != NULL );
+
+    EXPECT_STREQ( "lo", tmp->name_.c_str() );
+    EXPECT_EQ(1, tmp->ifindex_);
+
+    // check that non-existing interfaces are not returned
+    EXPECT_EQ(0, ifacemgr->getIface("wifi0") );
+
+    delete ifacemgr;
+}
+
+TEST_F(IfaceMgrTest, detectIfaces) {
+
+    // test detects that interfaces can be detected 
+    // there is no code for that now, but interfaces are
+    // read from file
+    fstream fakeifaces("interfaces.txt", ios::out);
+    fakeifaces << "eth0 fe80::1234";
+    fakeifaces.close();
+    
+    // this is not usable on systems that don't have eth0
+    // interfaces. Nevertheless, this fake interface should
+    // be on list, but if_nametoindex() will fail.
+    
+    IfaceMgr & ifacemgr = IfaceMgr::instance();
+    
+    ASSERT_TRUE( ifacemgr.getIface("eth0") != NULL );
+    
+    IfaceMgr::Iface * eth0 = ifacemgr.getIface("eth0");
+    
+    // there should be one address
+    EXPECT_EQ(1, eth0->addrs_.size());
+    
+    Addr6 * addr = &(*eth0->addrs_.begin());
+    ASSERT_TRUE( addr != NULL );
+    
+    EXPECT_STREQ( "fe80::1234", addr->getPlain().c_str() );
+}
+
+TEST_F(IfaceMgrTest, sockets) {
+    // testing socket operation in a portable way is tricky
+    // without interface detection implemented
+
+    IfaceMgr & ifacemgr = IfaceMgr::instance();
+
+    Addr6 loAddr("::1", true);
+
+    // bind multicast socket to port 10547
+    int socket1 = ifacemgr.openSocket("lo", loAddr, 10547, true);
+    EXPECT_GT(socket1, 0); // socket > 0
+
+    // bind unicast socket to port 10548
+    int socket2 = ifacemgr.openSocket("lo", loAddr, 10548, false);
+    EXPECT_GT(socket2, 0);
+
+    // good to check that both sockets can be opened at once
+
+    close(socket1);
+    close(socket2);
+}
+
+TEST_F(IfaceMgrTest, sendReceive) {
+    // testing socket operation in a portable way is tricky
+    // without interface detection implemented
+
+    NakedIfaceMgr * ifacemgr = new NakedIfaceMgr();
+
+    // let's assume that every supported OS have lo interface
+    Addr6 loAddr("::1", true);
+    int socket1 = ifacemgr->openSocket("lo", loAddr, 10547, true);
+    int socket2 = ifacemgr->openSocket("lo", loAddr, 10546, false);
+
+    ifacemgr->setSendSock(socket2);
+    ifacemgr->setRecvSock(socket1);
+
+    Pkt6 sendPkt(128);
+
+    // prepare dummy payload
+    for (int i=0;i<128; i++) {
+	sendPkt.data_[i] = i;
+    }
+
+    sendPkt.remotePort = 10547;
+    sendPkt.remoteAddr = Addr6("::1", true);
+    sendPkt.ifindex = 1;
+    sendPkt.iface = "lo";
+    
+    Pkt6 * rcvPkt;
+
+    EXPECT_EQ(true, ifacemgr->send(sendPkt));
+
+    rcvPkt = ifacemgr->receive();
+
+    ASSERT_TRUE( rcvPkt != NULL ); // received our own packet
+
+    // let's check that we received what was sent
+    EXPECT_EQ(sendPkt.dataLen_, rcvPkt->dataLen_);
+    EXPECT_EQ(0, memcmp(sendPkt.data_, rcvPkt->data_, rcvPkt->dataLen_) );
+
+    EXPECT_EQ(sendPkt.remoteAddr, rcvPkt->remoteAddr);
+    EXPECT_EQ(rcvPkt->remotePort, 10546);
+
+    delete rcvPkt;
+
+    delete ifacemgr;
+}
+

+ 51 - 0
src/bin/dhcp6/tests/pkt6_unittest.cc

@@ -0,0 +1,51 @@
+// Copyright (C) 2011  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 <config.h>
+#include <iostream>
+#include <sstream>
+
+#include <arpa/inet.h>
+#include <gtest/gtest.h>
+
+
+#include "dhcp6/pkt6.h"
+
+using namespace std;
+using namespace isc;
+
+// empty class for now, but may be extended once Addr6 becomes bigger
+class Pkt6Test : public ::testing::Test {
+public:
+    Pkt6Test() {
+    }
+};
+
+TEST_F(Pkt6Test, constructor) {
+    Pkt6 * pkt1 = new Pkt6(17);
+    
+    ASSERT_EQ(pkt1->dataLen_, 17);
+
+    char * buf = new char[23];
+    // can't use char buf[23], as Pkt6 takes ownership of the data
+
+    Pkt6 * pkt2 = new Pkt6(buf, 23);
+
+    ASSERT_EQ(pkt2->dataLen_, 23);
+    ASSERT_EQ(pkt2->data_, buf);
+
+    delete pkt1;
+    delete pkt2;
+}
+