test: Mock out interface lookups

This will make it possible to do interface lookups inside of our classes
during testing without depending on real interfaces existing.

Change-Id: I4c273d6961fa4229401fb25a0e5eb06af5b59ca4
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/test/mock_syscall.cpp b/test/mock_syscall.cpp
index 28ebed2..d6338c5 100644
--- a/test/mock_syscall.cpp
+++ b/test/mock_syscall.cpp
@@ -5,6 +5,11 @@
 #include <sys/socket.h>
 #include <sys/types.h>
 
+#include <cstring>
+#include <map>
+#include <stdexcept>
+#include <string>
+
 #define MAX_IFADDRS 5
 
 int debugging = false;
@@ -28,6 +33,20 @@
     return;
 }
 
+std::map<std::string, int> mock_if_nametoindex;
+std::map<int, std::string> mock_if_indextoname;
+
+void mock_addIF(const std::string& name, int idx)
+{
+    if (idx == 0)
+    {
+        throw std::invalid_argument("Bad interface index");
+    }
+
+    mock_if_nametoindex[name] = idx;
+    mock_if_indextoname[idx] = name;
+}
+
 void mock_addIP(const char* name, const char* addr, const char* mask,
                 unsigned int flags)
 {
@@ -66,3 +85,30 @@
         return -1;
     return (0);
 }
+
+unsigned if_nametoindex(const char* ifname)
+{
+    auto it = mock_if_nametoindex.find(ifname);
+    if (it == mock_if_nametoindex.end())
+    {
+        errno = ENXIO;
+        return 0;
+    }
+    return it->second;
+}
+
+char* if_indextoname(unsigned ifindex, char* ifname)
+{
+    if (ifindex == 0)
+    {
+        errno = ENXIO;
+        return NULL;
+    }
+    auto it = mock_if_indextoname.find(ifindex);
+    if (it == mock_if_indextoname.end())
+    {
+        // TODO: Return ENXIO once other code is mocked out
+        return std::strcpy(ifname, "invalid");
+    }
+    return std::strcpy(ifname, it->second.c_str());
+}
diff --git a/test/mock_syscall.hpp b/test/mock_syscall.hpp
index d219999..f14bd96 100644
--- a/test/mock_syscall.hpp
+++ b/test/mock_syscall.hpp
@@ -1,4 +1,5 @@
 #pragma once
+#include <string>
 
 /** @brief Adds the given interface and addr info
  *         into the ifaddr list.
@@ -10,3 +11,10 @@
 
 void mock_addIP(const char* name, const char* addr, const char* mask,
                 unsigned int flags);
+
+/** @brief Adds an address string to index mapping
+ *
+ *  @param[in] name - Interface name
+ *  @param[in] idx  - Interface index
+ */
+void mock_addIF(const std::string& name, int idx);
diff --git a/test/test_ethernet_interface.cpp b/test/test_ethernet_interface.cpp
index 9e611a6..a075423 100644
--- a/test/test_ethernet_interface.cpp
+++ b/test/test_ethernet_interface.cpp
@@ -29,7 +29,7 @@
     TestEthernetInterface() :
         bus(sdbusplus::bus::new_default()),
         manager(bus, "/xyz/openbmc_test/network", "/tmp/"),
-        interface(bus, "/xyz/openbmc_test/network/test0", false, manager)
+        interface(makeInterface(bus, manager))
 
     {
         setConfDir();
@@ -50,6 +50,13 @@
         }
     }
 
+    static EthernetInterface makeInterface(sdbusplus::bus::bus& bus,
+                                           MockManager& manager)
+    {
+        mock_addIF("test0", 1);
+        return {bus, "/xyz/openbmc_test/network/test0", false, manager};
+    }
+
     int countIPObjects()
     {
         return interface.getAddresses().size();
diff --git a/test/test_neighbor.cpp b/test/test_neighbor.cpp
index 6491b9f..ffb0d5d 100644
--- a/test/test_neighbor.cpp
+++ b/test/test_neighbor.cpp
@@ -1,3 +1,4 @@
+#include "mock_syscall.hpp"
 #include "neighbor.hpp"
 #include "util.hpp"
 
@@ -5,7 +6,6 @@
 #include <linux/netlink.h>
 #include <linux/rtnetlink.h>
 #include <net/ethernet.h>
-#include <net/if.h>
 
 #include <cstring>
 #include <stdexcept>
@@ -22,6 +22,9 @@
 namespace detail
 {
 
+constexpr auto ifStr = "eth0";
+constexpr auto ifIdx = 1;
+
 TEST(ParseNeighbor, NotNeighborType)
 {
     nlmsghdr hdr{};
@@ -58,10 +61,12 @@
 
 TEST(ParseNeighbor, NoAttrs)
 {
+    mock_addIF(ifStr, ifIdx);
+
     nlmsghdr hdr{};
     hdr.nlmsg_type = RTM_NEWNEIGH;
     ndmsg msg{};
-    msg.ndm_ifindex = if_nametoindex("lo");
+    msg.ndm_ifindex = ifIdx;
     ASSERT_NE(0, msg.ndm_ifindex);
     std::string data;
     data.append(reinterpret_cast<char*>(&msg), sizeof(msg));
@@ -73,10 +78,12 @@
 
 TEST(ParseNeighbor, NoAddress)
 {
+    mock_addIF(ifStr, ifIdx);
+
     nlmsghdr hdr{};
     hdr.nlmsg_type = RTM_NEWNEIGH;
     ndmsg msg{};
-    msg.ndm_ifindex = if_nametoindex("lo");
+    msg.ndm_ifindex = ifIdx;
     ASSERT_NE(0, msg.ndm_ifindex);
     ether_addr mac = {{0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa}};
     rtattr lladdr{};
@@ -97,13 +104,14 @@
 
 TEST(ParseNeighbor, NoMAC)
 {
-    constexpr auto ifstr = "lo";
+    mock_addIF(ifStr, ifIdx);
+
     nlmsghdr hdr{};
     hdr.nlmsg_type = RTM_NEWNEIGH;
     ndmsg msg{};
     msg.ndm_family = AF_INET;
     msg.ndm_state = NUD_PERMANENT;
-    msg.ndm_ifindex = if_nametoindex(ifstr);
+    msg.ndm_ifindex = ifIdx;
     ASSERT_NE(0, msg.ndm_ifindex);
     in_addr addr;
     ASSERT_EQ(1, inet_pton(msg.ndm_family, "192.168.10.1", &addr));
@@ -121,7 +129,7 @@
     std::vector<NeighborInfo> neighbors;
     parseNeighbor(hdr, data, neighbors);
     EXPECT_EQ(1, neighbors.size());
-    EXPECT_EQ(ifstr, neighbors[0].interface);
+    EXPECT_EQ(ifStr, neighbors[0].interface);
     EXPECT_TRUE(neighbors[0].permanent);
     EXPECT_FALSE(neighbors[0].mac);
     EXPECT_TRUE(equal(addr, std::get<in_addr>(neighbors[0].address)));
@@ -129,13 +137,14 @@
 
 TEST(ParseNeighbor, Full)
 {
-    constexpr auto ifstr = "lo";
+    mock_addIF(ifStr, ifIdx);
+
     nlmsghdr hdr{};
     hdr.nlmsg_type = RTM_NEWNEIGH;
     ndmsg msg{};
     msg.ndm_family = AF_INET6;
     msg.ndm_state = NUD_NOARP;
-    msg.ndm_ifindex = if_nametoindex(ifstr);
+    msg.ndm_ifindex = ifIdx;
     ether_addr mac = {{0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa}};
     rtattr lladdr{};
     lladdr.rta_len = RTA_LENGTH(sizeof(mac));
@@ -161,7 +170,7 @@
     std::vector<NeighborInfo> neighbors;
     parseNeighbor(hdr, data, neighbors);
     EXPECT_EQ(1, neighbors.size());
-    EXPECT_EQ(ifstr, neighbors[0].interface);
+    EXPECT_EQ(ifStr, neighbors[0].interface);
     EXPECT_FALSE(neighbors[0].permanent);
     EXPECT_TRUE(neighbors[0].mac);
     EXPECT_TRUE(equal(mac, *neighbors[0].mac));
diff --git a/test/test_network_manager.cpp b/test/test_network_manager.cpp
index ff0840e..f4de35a 100644
--- a/test/test_network_manager.cpp
+++ b/test/test_network_manager.cpp
@@ -71,6 +71,7 @@
     try
     {
         // Adds the following ip in the getifaddrs list.
+        mock_addIF("igb1", 2);
         mock_addIP("igb1", "192.0.2.3", "255.255.255.128",
                    IFF_UP | IFF_RUNNING);
 
@@ -92,9 +93,11 @@
 {
     try
     {
+        mock_addIF("igb0", 1);
         mock_addIP("igb0", "192.0.2.2", "255.255.255.128",
                    IFF_UP | IFF_RUNNING);
 
+        mock_addIF("igb1", 2);
         mock_addIP("igb1", "192.0.2.3", "255.255.255.128",
                    IFF_UP | IFF_RUNNING);
 
diff --git a/test/test_rtnetlink.cpp b/test/test_rtnetlink.cpp
index ecfa44a..794a0dd 100644
--- a/test/test_rtnetlink.cpp
+++ b/test/test_rtnetlink.cpp
@@ -27,7 +27,6 @@
 /** @brief refresh the network objects. */
 void refreshObjects()
 {
-
     if (manager)
     {
         manager->createChildObjects();
@@ -89,6 +88,7 @@
 {
     using namespace std::chrono;
     // Adds the following ip in the getifaddrs list.
+    mock_addIF("igb5", 6);
     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};
diff --git a/test/test_vlan_interface.cpp b/test/test_vlan_interface.cpp
index 7179212..0ff893c 100644
--- a/test/test_vlan_interface.cpp
+++ b/test/test_vlan_interface.cpp
@@ -31,7 +31,7 @@
     TestVlanInterface() :
         bus(sdbusplus::bus::new_default()),
         manager(bus, "/xyz/openbmc_test/network", "/tmp"),
-        interface(bus, "/xyz/openbmc_test/network/test0", false, manager)
+        interface(makeInterface(bus, manager))
 
     {
         setConfDir();
@@ -45,6 +45,13 @@
         }
     }
 
+    static EthernetInterface makeInterface(sdbusplus::bus::bus& bus,
+                                           MockManager& manager)
+    {
+        mock_addIF("test0", 1);
+        return {bus, "/xyz/openbmc_test/network/test0", false, manager};
+    }
+
     void setConfDir()
     {
         char tmp[] = "/tmp/VlanInterface.XXXXXX";
@@ -54,6 +61,9 @@
 
     void createVlan(VlanId id)
     {
+        std::string ifname = "test0.";
+        ifname += std::to_string(id);
+        mock_addIF(ifname.c_str(), 1000 + id);
         interface.createVLAN(id);
     }