test: Mock out MAC address access
This makes it possible for our ethernet interfaces to have MAC Addresses
detected and configured for testing without the system providing a real
NIC.
Change-Id: Ie985efec0a5e393b0b76f3d02bd3015fef6349e4
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/test/Makefile.am b/test/Makefile.am
index 388f679..842f8ca 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -37,7 +37,7 @@
test_CPPFLAGS = ${generic_cpp_flags}
test_CXXFLAGS = ${generic_cxx_flags}
-test_LDFLAGS = ${generic_ld_flags}
+test_LDFLAGS = ${generic_ld_flags} -ldl
test_dns_updater_CPPFLAGS = ${generic_cpp_flags}
test_dns_updater_CXXFLAGS = ${generic_cxx_flags}
diff --git a/test/mock_syscall.cpp b/test/mock_syscall.cpp
index d6338c5..3f96e1d 100644
--- a/test/mock_syscall.cpp
+++ b/test/mock_syscall.cpp
@@ -1,10 +1,14 @@
#include <arpa/inet.h>
+#include <dlfcn.h>
#include <ifaddrs.h>
+#include <net/ethernet.h>
#include <net/if.h>
#include <netinet/in.h>
+#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
+#include <cstdarg>
#include <cstring>
#include <map>
#include <stdexcept>
@@ -35,8 +39,9 @@
std::map<std::string, int> mock_if_nametoindex;
std::map<int, std::string> mock_if_indextoname;
+std::map<std::string, ether_addr> mock_macs;
-void mock_addIF(const std::string& name, int idx)
+void mock_addIF(const std::string& name, int idx, const ether_addr& mac)
{
if (idx == 0)
{
@@ -45,6 +50,7 @@
mock_if_nametoindex[name] = idx;
mock_if_indextoname[idx] = name;
+ mock_macs[name] = mac;
}
void mock_addIP(const char* name, const char* addr, const char* mask,
@@ -78,6 +84,8 @@
mock_ifaddrs = &mock_ifaddr_storage[0].ifaddr;
}
+extern "C" {
+
int getifaddrs(ifaddrs** ifap)
{
*ifap = mock_ifaddrs;
@@ -112,3 +120,30 @@
}
return std::strcpy(ifname, it->second.c_str());
}
+
+int ioctl(int fd, unsigned long int request, ...)
+{
+ va_list vl;
+ va_start(vl, request);
+ void* data = va_arg(vl, void*);
+ va_end(vl);
+
+ if (request == SIOCGIFHWADDR)
+ {
+ auto req = reinterpret_cast<ifreq*>(data);
+ auto it = mock_macs.find(req->ifr_name);
+ if (it == mock_macs.end())
+ {
+ errno = ENXIO;
+ return -1;
+ }
+ std::memcpy(req->ifr_hwaddr.sa_data, &it->second, sizeof(it->second));
+ return 0;
+ }
+
+ static auto real_ioctl =
+ reinterpret_cast<decltype(&ioctl)>(dlsym(RTLD_NEXT, "ioctl"));
+ return real_ioctl(fd, request, data);
+}
+
+} // extern "C"
diff --git a/test/mock_syscall.hpp b/test/mock_syscall.hpp
index f14bd96..4d934b3 100644
--- a/test/mock_syscall.hpp
+++ b/test/mock_syscall.hpp
@@ -1,4 +1,6 @@
#pragma once
+#include <net/ethernet.h>
+
#include <string>
/** @brief Adds the given interface and addr info
@@ -12,9 +14,11 @@
void mock_addIP(const char* name, const char* addr, const char* mask,
unsigned int flags);
-/** @brief Adds an address string to index mapping
+/** @brief Adds an address string to index mapping and MAC mapping
*
* @param[in] name - Interface name
* @param[in] idx - Interface index
+ * @param[in] mac - Interface MAC address
*/
-void mock_addIF(const std::string& name, int idx);
+void mock_addIF(const std::string& name, int idx,
+ const ether_addr& mac = ether_addr{});
diff --git a/test/test_ethernet_interface.cpp b/test/test_ethernet_interface.cpp
index a075423..c25bba9 100644
--- a/test/test_ethernet_interface.cpp
+++ b/test/test_ethernet_interface.cpp
@@ -2,6 +2,7 @@
#include "ipaddress.hpp"
#include "mock_network_manager.hpp"
#include "mock_syscall.hpp"
+#include "util.hpp"
#include <arpa/inet.h>
#include <net/if.h>
@@ -50,10 +51,12 @@
}
}
+ static constexpr ether_addr mac{0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
+
static EthernetInterface makeInterface(sdbusplus::bus::bus& bus,
MockManager& manager)
{
- mock_addIF("test0", 1);
+ mock_addIF("test0", 1, mac);
return {bus, "/xyz/openbmc_test/network/test0", false, manager};
}
@@ -125,6 +128,7 @@
TEST_F(TestEthernetInterface, NoIPaddress)
{
EXPECT_EQ(countIPObjects(), 0);
+ EXPECT_EQ(mac_address::toString(mac), interface.mACAddress());
}
TEST_F(TestEthernetInterface, AddIPAddress)