Added new unit testcases

1. Added testcases to validate IP/PrefixLengnth/MACAddress.
2. Added test to rtnetlink.

Resolves openbmc/openbmc#2546

Change-Id: I61efbf69682a50f7479b68e32d9714e9c81a32d7
Signed-off-by: Nagaraju Goruganti <ngorugan@in.ibm.com>
diff --git a/network_manager.hpp b/network_manager.hpp
index 7685ba8..ed6dc5b 100644
--- a/network_manager.hpp
+++ b/network_manager.hpp
@@ -37,6 +37,7 @@
 } // namespace details
 
 class TestNetworkManager; //forward declaration
+class TestRtNetlink; //forward declaration
 
 /** @class Manager
  *  @brief OpenBMC network manager implementation.
@@ -129,6 +130,7 @@
         fs::path confDir;
 
         friend class TestNetworkManager;
+        friend class TestRtNetlink;
 
 };
 
diff --git a/test/Makefile.am b/test/Makefile.am
index 5a1e712..b32e210 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -9,6 +9,7 @@
 	mock_syscall.cpp \
 	test_network_manager.cpp \
 	test_ethernet_interface.cpp \
+	test_rtnetlink.cpp \
 	test_config_parser.cpp \
 	test_vlan_interface.cpp
 
@@ -49,6 +50,7 @@
 			$(top_builddir)/routing_table.o \
 			$(top_builddir)/util.o \
 			$(top_builddir)/timer.o \
+			$(top_builddir)/rtnetlink_server.o \
 			$(top_builddir)/system_configuration.o \
 			$(top_builddir)/dhcp_configuration.o \
 			$(top_builddir)/config_parser.o \
diff --git a/test/test_network_manager.cpp b/test/test_network_manager.cpp
index 8413c01..2776bcf 100644
--- a/test/test_network_manager.cpp
+++ b/test/test_network_manager.cpp
@@ -21,9 +21,6 @@
 namespace network
 {
 
-std::unique_ptr<phosphor::network::Timer> refreshObjectTimer = nullptr;
-std::unique_ptr<phosphor::network::Timer> restartTimer = nullptr;
-
 namespace fs = std::experimental::filesystem;
 
 class TestNetworkManager : public testing::Test
diff --git a/test/test_rtnetlink.cpp b/test/test_rtnetlink.cpp
new file mode 100644
index 0000000..52008ba
--- /dev/null
+++ b/test/test_rtnetlink.cpp
@@ -0,0 +1,148 @@
+#include "types.hpp"
+#include "rtnetlink_server.hpp"
+#include "network_manager.hpp"
+#include "mock_syscall.hpp"
+#include "timer.hpp"
+#include "types.hpp"
+
+
+#include <gtest/gtest.h>
+#include <sdbusplus/bus.hpp>
+
+#include <net/if.h>
+#include <linux/rtnetlink.h>
+
+namespace phosphor
+{
+
+namespace network
+{
+
+std::unique_ptr<Manager> manager = nullptr;
+std::unique_ptr<Timer> refreshObjectTimer = nullptr;
+std::unique_ptr<Timer> restartTimer = nullptr;
+EventPtr eventPtr = nullptr;
+
+/** @brief refresh the network objects. */
+void refreshObjects()
+{
+
+    if (manager)
+    {
+        manager->createChildObjects();
+    }
+}
+
+void initializeTimers()
+{
+    std::function<void()> refreshFunc(
+        std::bind(&refreshObjects));
+
+    refreshObjectTimer =
+        std::make_unique<Timer>(refreshFunc);
+
+}
+
+class TestRtNetlink : public testing::Test
+{
+
+    public:
+        std::string confDir;
+        phosphor::Descriptor smartSock;
+
+
+
+        TestRtNetlink()
+        {
+            sdbusplus::bus::bus bus(sdbusplus::bus::new_default());
+            manager =
+                std::make_unique<Manager>(bus,
+                        "/xyz/openbmc_test/bcd",
+                        "/tmp");
+            sd_event* events;
+            sd_event_default(&events);
+            eventPtr.reset(events);
+            events = nullptr;
+            setConfDir();
+            initializeTimers();
+            createNetLinkSocket();
+            bus.attach_event(eventPtr.get(), SD_EVENT_PRIORITY_NORMAL);
+            rtnetlink::Server svr(eventPtr, smartSock);
+        }
+
+        ~TestRtNetlink()
+        {
+            if (confDir.empty())
+            {
+                fs::remove_all(confDir);
+            }
+        }
+
+        void setConfDir()
+        {
+            confDir = "/tmp/NetworkManager.YYYY";
+            manager->setConfDir(confDir);
+        }
+
+        bool isInterfaceAdded(std::string intf)
+        {
+            return manager->interfaces.find(intf) != manager->interfaces.end()?
+                   true :
+                   false;
+        }
+
+        void createNetLinkSocket()
+        {
+            //RtnetLink socket
+            auto fd = socket(PF_NETLINK, SOCK_RAW | SOCK_NONBLOCK,
+                NETLINK_ROUTE);
+            smartSock.set(fd);
+        }
+};
+
+
+TEST_F(TestRtNetlink, WithSingleInterface)
+{
+    bool caughtException = false;
+    using namespace std::chrono;
+    try
+    {
+        // Adds the following ip in the getifaddrs list.
+        mock_addIP("igb5", "127.0.0.1", "255.255.255.128",
+                   IFF_UP | IFF_RUNNING);
+        constexpr auto BUFSIZE = 4096;
+        std::array<char, BUFSIZE> msgBuf = {0};
+
+        // point the header and the msg structure pointers into the buffer.
+        auto nlMsg = reinterpret_cast<nlmsghdr*>(msgBuf.data());
+        // Length of message
+        nlMsg->nlmsg_len = NLMSG_LENGTH(sizeof(rtmsg));
+        nlMsg->nlmsg_type = RTM_GETADDR;
+        nlMsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
+        nlMsg->nlmsg_seq = 0;
+        nlMsg->nlmsg_pid = getpid();
+
+        EXPECT_EQ(false, isInterfaceAdded("igb5"));
+        // Send the request
+        send(smartSock(), nlMsg, nlMsg->nlmsg_len, 0);
+
+        int i = 2;
+        while (i--)
+        {
+            //wait for timer to expire
+            std::this_thread::sleep_for(
+                std::chrono::milliseconds(refreshTimeout));
+            sd_event_run(eventPtr.get(), 10);
+        };
+
+        EXPECT_EQ(true, isInterfaceAdded("igb5"));
+    }
+    catch (std::exception& e)
+    {
+        caughtException = true;
+    }
+    EXPECT_EQ(false, caughtException);
+}
+
+}// namespce network
+}// namespace phosphor
diff --git a/test/test_util.cpp b/test/test_util.cpp
index 1c78b64..9596097 100644
--- a/test/test_util.cpp
+++ b/test/test_util.cpp
@@ -17,6 +17,89 @@
 
 };
 
+TEST_F(TestUtil, IpValidation)
+{
+    std::string ipaddress = "0.0.0.0";
+    EXPECT_EQ(true, isValidIP(AF_INET, ipaddress));
+
+    ipaddress = "9.3.185.83";
+    EXPECT_EQ(true, isValidIP(AF_INET, ipaddress));
+
+    ipaddress = "9.3.185.a";
+    EXPECT_EQ(false, isValidIP(AF_INET, ipaddress));
+
+    ipaddress = "9.3.a.83";
+    EXPECT_EQ(false, isValidIP(AF_INET, ipaddress));
+
+    ipaddress = "x.x.x.x";
+    EXPECT_EQ(false, isValidIP(AF_INET, ipaddress));
+
+    ipaddress = "0:0:0:0:0:0:0:0";
+    EXPECT_EQ(true, isValidIP(AF_INET6, ipaddress));
+
+    ipaddress = "1:0:0:0:0:0:0:8";
+    EXPECT_EQ(true, isValidIP(AF_INET6, ipaddress));
+
+    ipaddress = "1::8";
+    EXPECT_EQ(true, isValidIP(AF_INET6, ipaddress));
+
+    ipaddress = "0:0:0:0:0:FFFF:204.152.189.116";
+    EXPECT_EQ(true, isValidIP(AF_INET6, ipaddress));
+
+    ipaddress = "::ffff:204.152.189.116";
+    EXPECT_EQ(true, isValidIP(AF_INET6, ipaddress));
+
+    ipaddress = "a:0:0:0:0:FFFF:204.152.189.116";
+    EXPECT_EQ(true, isValidIP(AF_INET6, ipaddress));
+
+    ipaddress = "1::8";
+    EXPECT_EQ(true, isValidIP(AF_INET6, ipaddress));
+
+
+}
+
+TEST_F(TestUtil, PrefixValidation)
+{
+    uint8_t prefixLength = 1;
+    EXPECT_EQ(true, isValidPrefix(AF_INET, prefixLength));
+
+    prefixLength = 32;
+    EXPECT_EQ(true, isValidPrefix(AF_INET, prefixLength));
+
+    prefixLength = 0;
+    EXPECT_EQ(false, isValidPrefix(AF_INET, prefixLength));
+
+    prefixLength = 33;
+    EXPECT_EQ(false, isValidPrefix(AF_INET, prefixLength));
+
+    prefixLength = 33;
+    EXPECT_EQ(true, isValidPrefix(AF_INET6, prefixLength));
+
+    prefixLength = 65;
+    EXPECT_EQ(false, isValidPrefix(AF_INET, prefixLength));
+
+}
+
+
+TEST_F(TestUtil, MacValidation)
+{
+    std::string macaddress = "00:00:00:00:00:00";
+    EXPECT_EQ(false, phosphor::network::mac_address::validate(macaddress));
+
+    macaddress = "F6:C6:E6:6:B0:D3";
+    EXPECT_EQ(false, phosphor::network::mac_address::validate(macaddress));
+
+    macaddress = "F6:C6:E6:06:B0:D3";
+    EXPECT_EQ(true, phosphor::network::mac_address::validate(macaddress));
+
+    macaddress = "hh:HH:HH:hh:HH:yy";
+    EXPECT_EQ(false, phosphor::network::mac_address::validate(macaddress));
+
+    macaddress = "hhh:GGG:iii:jjj:kkk:lll";
+    EXPECT_EQ(false, phosphor::network::mac_address::validate(macaddress));
+
+}
+
 TEST_F(TestUtil, ConvertV4MasktoPrefix)
 {
     std::string mask = "255.255.255.0";