tests: expand test coverage of EthernetFactory and UdpFactory
Change-Id: I469ac8682502ca7a0e360703b462bfb119eaedf1
diff --git a/tests/daemon/face/udp-factory.t.cpp b/tests/daemon/face/udp-factory.t.cpp
index fd83656..55d601c 100644
--- a/tests/daemon/face/udp-factory.t.cpp
+++ b/tests/daemon/face/udp-factory.t.cpp
@@ -32,6 +32,7 @@
namespace nfd::tests {
+namespace ip = boost::asio::ip;
using face::UdpChannel;
using face::UdpFactory;
using ndn::net::NetworkInterface;
@@ -42,7 +43,7 @@
shared_ptr<UdpChannel>
createChannel(const std::string& localIp, uint16_t localPort)
{
- udp::Endpoint endpoint(boost::asio::ip::make_address(localIp), localPort);
+ udp::Endpoint endpoint(ip::make_address(localIp), localPort);
return factory.createChannel(endpoint, 5_min);
}
};
@@ -53,7 +54,7 @@
UdpFactoryMcastFixture()
{
for (const auto& netif : collectNetworkInterfaces()) {
- // same filtering logic as UdpFactory::applyMcastConfigToNetif()
+ // similar filtering logic to UdpFactory::applyMcastConfigToNetif()
if (netif->isUp() && !netif->isLoopback() && netif->canMulticast()) {
bool hasValidIpAddress = false;
if (hasAddressFamily(*netif, ndn::net::AddressFamily::V4)) {
@@ -69,38 +70,6 @@
}
}
}
- copyRealNetifsToNetmon();
- }
-
- shared_ptr<Face>
- createMulticastFace(const std::string& localIp, const std::string& mcastIp, uint16_t mcastPort)
- {
- auto localAddress = boost::asio::ip::make_address(localIp);
- udp::Endpoint mcastEndpoint(boost::asio::ip::make_address(mcastIp), mcastPort);
-
- if (localAddress.is_v4()) {
- BOOST_ASSERT(!netifsV4.empty());
- return factory.createMulticastFace(*netifsV4.front(), localAddress, mcastEndpoint);
- }
- else {
- BOOST_ASSERT(!netifsV6.empty());
- return factory.createMulticastFace(*netifsV6.front(), localAddress, mcastEndpoint);
- }
- }
-
- /** \brief Returns a non-loopback IP address suitable for the creation of a UDP multicast face.
- */
- boost::asio::ip::address
- findNonLoopbackAddressForMulticastFace(ndn::net::AddressFamily af) const
- {
- const auto& netifList = af == ndn::net::AddressFamily::V4 ? netifsV4 : netifsV6;
- for (const auto& netif : netifList) {
- for (const auto& a : netif->getNetworkAddresses()) {
- if (a.getFamily() == af && !a.getIp().is_loopback())
- return a.getIp();
- }
- }
- return {};
}
std::vector<const Face*>
@@ -115,6 +84,35 @@
return listFacesByScheme("udp6", linkType);
}
+ shared_ptr<NetworkInterface>
+ makeFakeNetif(bool addNetworkAddresses = true)
+ {
+ using namespace ndn::net;
+
+ static int counter = 0;
+ ++counter;
+
+ auto netif = netmon->makeNetworkInterface();
+ netif->setIndex(1000 + counter);
+ netif->setName("ethdummy" + std::to_string(counter));
+ netif->setType(InterfaceType::ETHERNET);
+ netif->setFlags(IFF_MULTICAST | IFF_UP);
+ netif->setState(InterfaceState::RUNNING);
+ netif->setMtu(1500);
+ netif->setEthernetAddress(ethernet::Address{0x3e, 0x15, 0xc2, 0x8b, 0x65, 0x00});
+ if (addNetworkAddresses) {
+ netif->addNetworkAddress(NetworkAddress(AddressFamily::V4,
+ ip::make_address_v4("192.168.2.1"),
+ ip::make_address_v4("192.168.2.255"),
+ 24, AddressScope::GLOBAL, 0));
+ netif->addNetworkAddress(NetworkAddress(AddressFamily::V6,
+ ip::make_address_v6("2001:db8:2::1"),
+ ip::make_address_v6("2001:db8:2::ffff:ffff:ffff:ffff"),
+ 64, AddressScope::GLOBAL, 0));
+ }
+ return netif;
+ }
+
/**
* \brief Determine whether \p netif has at least one IP address of the given family.
*/
@@ -131,9 +129,9 @@
static bool
isFaceOnNetif(const Face& face, const NetworkInterface& netif)
{
- auto ip = boost::asio::ip::make_address(face.getLocalUri().getHost());
+ auto faceIp = ip::make_address(face.getLocalUri().getHost());
return std::any_of(netif.getNetworkAddresses().begin(), netif.getNetworkAddresses().end(),
- [ip] (const auto& a) { return a.getIp() == ip; });
+ [faceIp] (const auto& a) { return a.getIp() == faceIp; });
}
protected:
@@ -152,6 +150,47 @@
std::vector<shared_ptr<const NetworkInterface>> netifsV6;
};
+class UdpFactoryMcastFixtureWithRealNetifs : public UdpFactoryMcastFixture
+{
+protected:
+ UdpFactoryMcastFixtureWithRealNetifs()
+ {
+ copyRealNetifsToNetmon();
+ }
+
+ shared_ptr<Face>
+ createMulticastFace(const std::string& localIp, const std::string& mcastIp, uint16_t mcastPort)
+ {
+ auto localAddress = ip::make_address(localIp);
+ udp::Endpoint mcastEndpoint(ip::make_address(mcastIp), mcastPort);
+
+ if (localAddress.is_v4()) {
+ BOOST_ASSERT(!netifsV4.empty());
+ return factory.createMulticastFace(*netifsV4.front(), localAddress, mcastEndpoint);
+ }
+ else {
+ BOOST_ASSERT(!netifsV6.empty());
+ return factory.createMulticastFace(*netifsV6.front(), localAddress, mcastEndpoint);
+ }
+ }
+
+ /**
+ * \brief Returns a non-loopback IP address suitable for the creation of a UDP multicast face.
+ */
+ ip::address
+ findNonLoopbackAddressForMulticastFace(ndn::net::AddressFamily af) const
+ {
+ const auto& netifList = af == ndn::net::AddressFamily::V4 ? netifsV4 : netifsV6;
+ for (const auto& netif : netifList) {
+ for (const auto& a : netif->getNetworkAddresses()) {
+ if (a.getFamily() == af && !a.getIp().is_loopback())
+ return a.getIp();
+ }
+ }
+ return {};
+ }
+};
+
#define SKIP_IF_UDP_MCAST_NETIF_COUNT_LT(n) \
do { \
if (this->netifs.size() < (n)) { \
@@ -180,11 +219,9 @@
} while (false)
BOOST_AUTO_TEST_SUITE(Face)
-BOOST_FIXTURE_TEST_SUITE(TestUdpFactory, UdpFactoryFixture)
+BOOST_AUTO_TEST_SUITE(TestUdpFactory)
-BOOST_AUTO_TEST_SUITE(ProcessConfig)
-
-using nfd::Face;
+BOOST_FIXTURE_TEST_SUITE(ProcessConfig, UdpFactoryFixture)
BOOST_AUTO_TEST_CASE(Defaults)
{
@@ -278,7 +315,7 @@
}
}
-BOOST_FIXTURE_TEST_CASE(EnableDisableMcast, UdpFactoryMcastFixture)
+BOOST_FIXTURE_TEST_CASE(EnableDisableMcast, UdpFactoryMcastFixtureWithRealNetifs)
{
const std::string CONFIG_WITH_MCAST = R"CONFIG(
face_system
@@ -313,13 +350,13 @@
BOOST_CHECK_EQUAL(this->listUdp4McastFaces().size(), netifsV4.size());
BOOST_CHECK_EQUAL(this->listUdp6McastFaces().size(), netifsV6.size());
- BOOST_REQUIRE_EQUAL(factory.getChannels().size(), 2);
- for (const auto& face : this->listUdp4McastFaces()) {
+ BOOST_CHECK_EQUAL(factory.getChannels().size(), 2);
+ for (const auto* face : this->listUdp4McastFaces()) {
BOOST_REQUIRE(face->getChannel().lock());
BOOST_CHECK_EQUAL(face->getChannel().lock()->getUri().getScheme(), "udp4");
}
- for (const auto& face : this->listUdp6McastFaces()) {
+ for (const auto* face : this->listUdp6McastFaces()) {
BOOST_REQUIRE(face->getChannel().lock());
BOOST_CHECK_EQUAL(face->getChannel().lock()->getUri().getScheme(), "udp6");
}
@@ -330,7 +367,7 @@
BOOST_CHECK_EQUAL(this->listUdp6McastFaces().size(), 0);
}
-BOOST_FIXTURE_TEST_CASE(McastAdHoc, UdpFactoryMcastFixture)
+BOOST_FIXTURE_TEST_CASE(McastAdHoc, UdpFactoryMcastFixtureWithRealNetifs)
{
#ifdef __linux__
// need superuser privileges to create multicast faces on Linux
@@ -349,11 +386,13 @@
)CONFIG";
parseConfig(CONFIG, false);
+ BOOST_CHECK_EQUAL(this->listUdp4McastFaces(ndn::nfd::LINK_TYPE_MULTI_ACCESS).size(), 0);
+ BOOST_CHECK_EQUAL(this->listUdp6McastFaces(ndn::nfd::LINK_TYPE_MULTI_ACCESS).size(), 0);
BOOST_CHECK_EQUAL(this->listUdp4McastFaces(ndn::nfd::LINK_TYPE_AD_HOC).size(), netifsV4.size());
BOOST_CHECK_EQUAL(this->listUdp6McastFaces(ndn::nfd::LINK_TYPE_AD_HOC).size(), netifsV6.size());
}
-BOOST_FIXTURE_TEST_CASE(ChangeMcastEndpointV4, UdpFactoryMcastFixture)
+BOOST_FIXTURE_TEST_CASE(ChangeMcastEndpointV4, UdpFactoryMcastFixtureWithRealNetifs)
{
#ifdef __linux__
// need superuser privileges to create multicast faces on Linux
@@ -383,6 +422,7 @@
)CONFIG";
parseConfig(CONFIG1, false);
+ g_io.poll();
auto udpMcastFaces = this->listUdp4McastFaces();
BOOST_REQUIRE_EQUAL(udpMcastFaces.size(), netifsV4.size());
BOOST_CHECK_EQUAL(udpMcastFaces.front()->getRemoteUri(), FaceUri("udp4://239.66.30.1:7011"));
@@ -394,7 +434,7 @@
BOOST_CHECK_EQUAL(udpMcastFaces.front()->getRemoteUri(), FaceUri("udp4://239.66.30.2:7012"));
}
-BOOST_FIXTURE_TEST_CASE(ChangeMcastEndpointV6, UdpFactoryMcastFixture)
+BOOST_FIXTURE_TEST_CASE(ChangeMcastEndpointV6, UdpFactoryMcastFixtureWithRealNetifs)
{
#ifdef __linux__
// need superuser privileges to create multicast faces on Linux
@@ -424,14 +464,15 @@
)CONFIG";
parseConfig(CONFIG1, false);
+ g_io.poll();
auto udpMcastFaces = this->listUdp6McastFaces();
BOOST_REQUIRE_EQUAL(udpMcastFaces.size(), netifsV6.size());
auto uri = udpMcastFaces.front()->getRemoteUri();
BOOST_CHECK_EQUAL(uri.getScheme(), "udp6");
// check the address ignoring the scope id
- auto addr = boost::asio::ip::make_address_v6(uri.getHost());
+ auto addr = ip::make_address_v6(uri.getHost());
addr.scope_id(0);
- BOOST_CHECK_EQUAL(addr, boost::asio::ip::make_address_v6("ff02::1101"));
+ BOOST_CHECK_EQUAL(addr, ip::make_address_v6("ff02::1101"));
BOOST_CHECK_EQUAL(uri.getPort(), "7011");
parseConfig(CONFIG2, false);
@@ -441,13 +482,13 @@
uri = udpMcastFaces.front()->getRemoteUri();
BOOST_CHECK_EQUAL(uri.getScheme(), "udp6");
// check the address ignoring the scope id
- addr = boost::asio::ip::make_address_v6(uri.getHost());
+ addr = ip::make_address_v6(uri.getHost());
addr.scope_id(0);
- BOOST_CHECK_EQUAL(addr, boost::asio::ip::make_address_v6("ff02::1102"));
+ BOOST_CHECK_EQUAL(addr, ip::make_address_v6("ff02::1102"));
BOOST_CHECK_EQUAL(uri.getPort(), "7012");
}
-BOOST_FIXTURE_TEST_CASE(Whitelist, UdpFactoryMcastFixture)
+BOOST_FIXTURE_TEST_CASE(Whitelist, UdpFactoryMcastFixtureWithRealNetifs)
{
#ifdef __linux__
// need superuser privileges to create multicast faces on Linux
@@ -478,10 +519,10 @@
udpMcastFaces.insert(udpMcastFaces.end(), udpMcastFacesV6.begin(), udpMcastFacesV6.end());
BOOST_CHECK_GE(udpMcastFaces.size(), 1);
BOOST_CHECK(std::all_of(udpMcastFaces.begin(), udpMcastFaces.end(),
- [this] (const Face* face) { return isFaceOnNetif(*face, *netifs.front()); }));
+ [this] (const auto* face) { return isFaceOnNetif(*face, *netifs.front()); }));
}
-BOOST_FIXTURE_TEST_CASE(Blacklist, UdpFactoryMcastFixture)
+BOOST_FIXTURE_TEST_CASE(Blacklist, UdpFactoryMcastFixtureWithRealNetifs)
{
#ifdef __linux__
// need superuser privileges to create multicast faces on Linux
@@ -514,10 +555,10 @@
udpMcastFaces.insert(udpMcastFaces.end(), udpMcastFacesV6.begin(), udpMcastFacesV6.end());
BOOST_CHECK_LT(udpMcastFaces.size(), netifsV4.size() + netifsV6.size());
BOOST_CHECK(std::none_of(udpMcastFaces.begin(), udpMcastFaces.end(),
- [this] (const Face* face) { return isFaceOnNetif(*face, *netifs.front()); }));
+ [this] (const auto* face) { return isFaceOnNetif(*face, *netifs.front()); }));
}
-BOOST_FIXTURE_TEST_CASE(ChangePredicate, UdpFactoryMcastFixture)
+BOOST_FIXTURE_TEST_CASE(ChangePredicate, UdpFactoryMcastFixtureWithRealNetifs)
{
#ifdef __linux__
// need superuser privileges to create multicast faces on Linux
@@ -542,13 +583,14 @@
boost::replace_first(CONFIG2, "%ifname", netifs.back()->getName());
parseConfig(CONFIG1, false);
+ g_io.poll();
auto udpMcastFaces = this->listUdp4McastFaces();
auto udpMcastFacesV6 = this->listUdp6McastFaces();
udpMcastFaces.insert(udpMcastFaces.end(), udpMcastFacesV6.begin(), udpMcastFacesV6.end());
BOOST_CHECK_GE(udpMcastFaces.size(), 1);
BOOST_CHECK(std::all_of(udpMcastFaces.begin(), udpMcastFaces.end(),
- [this] (const Face* face) { return isFaceOnNetif(*face, *netifs.front()); }));
+ [this] (const auto* face) { return isFaceOnNetif(*face, *netifs.front()); }));
parseConfig(CONFIG2, false);
g_io.poll();
@@ -558,7 +600,7 @@
udpMcastFaces.insert(udpMcastFaces.end(), udpMcastFacesV6.begin(), udpMcastFacesV6.end());
BOOST_CHECK_GE(udpMcastFaces.size(), 1);
BOOST_CHECK(std::all_of(udpMcastFaces.begin(), udpMcastFaces.end(),
- [this] (const Face* face) { return isFaceOnNetif(*face, *netifs.back()); }));
+ [this] (const auto* face) { return isFaceOnNetif(*face, *netifs.back()); }));
}
BOOST_AUTO_TEST_CASE(Omitted)
@@ -914,7 +956,7 @@
BOOST_AUTO_TEST_SUITE_END() // ProcessConfig
-BOOST_AUTO_TEST_CASE(GetChannels)
+BOOST_FIXTURE_TEST_CASE(GetChannels, UdpFactoryFixture)
{
BOOST_CHECK_EQUAL(factory.getChannels().empty(), true);
@@ -925,47 +967,49 @@
checkChannelListEqual(factory, expected);
}
-BOOST_FIXTURE_TEST_CASE(CreateChannel, UdpFactoryMcastFixture)
+BOOST_FIXTURE_TEST_CASE(CreateChannel, UdpFactoryMcastFixtureWithRealNetifs)
{
auto channel1 = createChannel("127.0.0.1", 20070);
auto channel1a = createChannel("127.0.0.1", 20070);
BOOST_CHECK_EQUAL(channel1, channel1a);
BOOST_CHECK_EQUAL(channel1->getUri().toString(), "udp4://127.0.0.1:20070");
+ BOOST_CHECK_EQUAL(factory.getChannels().size(), 1);
auto channel2 = createChannel("127.0.0.1", 20071);
BOOST_CHECK_NE(channel1, channel2);
+ BOOST_CHECK_EQUAL(factory.getChannels().size(), 2);
auto channel3 = createChannel("::1", 20071);
BOOST_CHECK_NE(channel2, channel3);
BOOST_CHECK_EQUAL(channel3->getUri().toString(), "udp6://[::1]:20071");
+ BOOST_CHECK_EQUAL(factory.getChannels().size(), 3);
#ifdef __linux__
// need superuser privileges to create multicast faces on Linux
SKIP_IF_NOT_SUPERUSER();
#endif // __linux__
+ SKIP_IF_UDP_MCAST_NETIF_COUNT_LT(1);
// createChannel with a local endpoint that has already been allocated to a UDP multicast face
if (!netifsV4.empty()) {
auto mcastFace = createMulticastFace("127.0.0.1", "224.0.0.254", 20072);
BOOST_CHECK_EXCEPTION(createChannel("127.0.0.1", 20072), UdpFactory::Error,
[] (const UdpFactory::Error& e) {
- return strcmp(e.what(),
- "Cannot create UDP channel on 127.0.0.1:20072, "
- "endpoint already allocated to a UDP multicast face") == 0;
+ return e.what() == "Cannot create UDP channel on 127.0.0.1:20072, "
+ "endpoint already allocated to a UDP multicast face"s;
});
}
if (!netifsV6.empty()) {
auto mcastFace = createMulticastFace("::1", "ff02::114", 20072);
BOOST_CHECK_EXCEPTION(createChannel("::1", 20072), UdpFactory::Error,
[] (const UdpFactory::Error& e) {
- return strcmp(e.what(),
- "Cannot create UDP channel on [::1]:20072, "
- "endpoint already allocated to a UDP multicast face") == 0;
+ return e.what() == "Cannot create UDP channel on [::1]:20072, "
+ "endpoint already allocated to a UDP multicast face"s;
});
}
}
-BOOST_FIXTURE_TEST_CASE(CreateMulticastFaceV4, UdpFactoryMcastFixture)
+BOOST_FIXTURE_TEST_CASE(CreateMulticastFaceV4, UdpFactoryMcastFixtureWithRealNetifs)
{
#ifdef __linux__
// need superuser privileges to create multicast faces on Linux
@@ -990,21 +1034,19 @@
auto channel = createChannel("127.0.0.1", 20071);
BOOST_CHECK_EXCEPTION(createMulticastFace("127.0.0.1", "224.0.0.254", 20071), UdpFactory::Error,
[] (const UdpFactory::Error& e) {
- return strcmp(e.what(),
- "Cannot create UDP multicast face on 127.0.0.1:20071, "
- "endpoint already allocated to a UDP channel") == 0;
+ return e.what() == "Cannot create UDP multicast face on 127.0.0.1:20071, "
+ "endpoint already allocated to a UDP channel"s;
});
// create with a local endpoint already used by a multicast face on a different multicast group
BOOST_CHECK_EXCEPTION(createMulticastFace("127.0.0.1", "224.0.0.42", 20070), UdpFactory::Error,
[] (const UdpFactory::Error& e) {
- return strcmp(e.what(),
- "Cannot create UDP multicast face on 127.0.0.1:20070, "
- "endpoint already allocated to a different UDP multicast face") == 0;
+ return e.what() == "Cannot create UDP multicast face on 127.0.0.1:20070, "
+ "endpoint already allocated to a different UDP multicast face"s;
});
}
-BOOST_FIXTURE_TEST_CASE(CreateMulticastFaceV6, UdpFactoryMcastFixture)
+BOOST_FIXTURE_TEST_CASE(CreateMulticastFaceV6, UdpFactoryMcastFixtureWithRealNetifs)
{
#ifdef __linux__
// need superuser privileges to create multicast faces on Linux
@@ -1029,21 +1071,19 @@
auto channel = createChannel("::1", 20071);
BOOST_CHECK_EXCEPTION(createMulticastFace("::1", "ff02::114", 20071), UdpFactory::Error,
[] (const UdpFactory::Error& e) {
- return strcmp(e.what(),
- "Cannot create UDP multicast face on [::1]:20071, "
- "endpoint already allocated to a UDP channel") == 0;
+ return e.what() == "Cannot create UDP multicast face on [::1]:20071, "
+ "endpoint already allocated to a UDP channel"s;
});
// create with a local endpoint already used by a multicast face on a different multicast group
BOOST_CHECK_EXCEPTION(createMulticastFace("::1", "ff02::42", 20070), UdpFactory::Error,
[] (const UdpFactory::Error& e) {
- return strcmp(e.what(),
- "Cannot create UDP multicast face on [::1]:20070, "
- "endpoint already allocated to a different UDP multicast face") == 0;
+ return e.what() == "Cannot create UDP multicast face on [::1]:20070, "
+ "endpoint already allocated to a different UDP multicast face"s;
});
}
-BOOST_AUTO_TEST_CASE(CreateFace)
+BOOST_FIXTURE_TEST_CASE(CreateFace, UdpFactoryFixture)
{
createFace(factory,
FaceUri("udp4://127.0.0.1:6363"),
@@ -1090,10 +1130,8 @@
{CreateFaceExpectedResult::SUCCESS, 0, ""});
}
-BOOST_AUTO_TEST_CASE(UnsupportedCreateFace)
+BOOST_FIXTURE_TEST_CASE(CreateFaceInvalidRequest, UdpFactoryFixture)
{
- createChannel("127.0.0.1", 20071);
-
createFace(factory,
FaceUri("udp4://127.0.0.1:20072"),
FaceUri("udp4://127.0.0.1:20071"),
@@ -1121,8 +1159,132 @@
{ndn::nfd::FACE_PERSISTENCY_PERSISTENT, {}, {}, {}, true, false, false},
{CreateFaceExpectedResult::FAILURE, 406,
"Local fields can only be enabled on faces with local scope"});
+
+ createFace(factory,
+ FaceUri("udp4://127.0.0.1:20072"),
+ {},
+ {ndn::nfd::FACE_PERSISTENCY_PERSISTENT, {}, {}, 42, false, false, false},
+ {CreateFaceExpectedResult::FAILURE, 406,
+ "Override MTU cannot be less than 64"});
}
+BOOST_FIXTURE_TEST_SUITE(OnInterfaceAdded, UdpFactoryMcastFixture)
+
+BOOST_AUTO_TEST_CASE(EligibleV4)
+{
+#ifdef __linux__
+ // need superuser privileges to create multicast faces on Linux
+ SKIP_IF_NOT_SUPERUSER();
+#endif // __linux__
+ SKIP_IF_UDP_MCAST_V4_NETIF_COUNT_LT(1);
+
+ parseConfig(R"CONFIG(
+ face_system
+ {
+ udp
+ }
+ )CONFIG", false);
+ g_io.poll();
+ BOOST_CHECK_EQUAL(this->listUdp4McastFaces().size(), 0);
+ BOOST_CHECK_EQUAL(this->listUdp6McastFaces().size(), 0);
+
+ netmon->addInterface(const_pointer_cast<NetworkInterface>(netifsV4.front()));
+ BOOST_CHECK_EQUAL(this->listUdp4McastFaces().size(), 1);
+ BOOST_CHECK_LE(this->listUdp6McastFaces().size(), 1);
+}
+
+BOOST_AUTO_TEST_CASE(EligibleV6)
+{
+#ifdef __linux__
+ // need superuser privileges to create multicast faces on Linux
+ SKIP_IF_NOT_SUPERUSER();
+#endif // __linux__
+ SKIP_IF_UDP_MCAST_V6_NETIF_COUNT_LT(1);
+
+ parseConfig(R"CONFIG(
+ face_system
+ {
+ udp
+ }
+ )CONFIG", false);
+ g_io.poll();
+ BOOST_CHECK_EQUAL(this->listUdp4McastFaces().size(), 0);
+ BOOST_CHECK_EQUAL(this->listUdp6McastFaces().size(), 0);
+
+ netmon->addInterface(const_pointer_cast<NetworkInterface>(netifsV6.front()));
+ BOOST_CHECK_LE(this->listUdp4McastFaces().size(), 1);
+ BOOST_CHECK_EQUAL(this->listUdp6McastFaces().size(), 1);
+}
+
+BOOST_AUTO_TEST_CASE(EligibleFailure)
+{
+ parseConfig(R"CONFIG(
+ face_system
+ {
+ udp
+ }
+ )CONFIG", false);
+ g_io.poll();
+
+ // Add a fake interface that satisfies the multicast criteria.
+ netmon->addInterface(this->makeFakeNetif());
+ // Creation of multicast faces fails because the interface does not actually exist.
+ // This test is to ensure that the factory handles failures gracefully.
+ BOOST_CHECK_EQUAL(this->listUdp4McastFaces().size(), 0);
+ BOOST_CHECK_EQUAL(this->listUdp6McastFaces().size(), 0);
+}
+
+BOOST_AUTO_TEST_CASE(Ineligible)
+{
+ parseConfig(R"CONFIG(
+ face_system
+ {
+ udp
+ }
+ )CONFIG", false);
+ g_io.poll();
+
+ // netif is down
+ auto netif = this->makeFakeNetif();
+ netif->setFlags(netif->getFlags() & ~IFF_UP);
+ netmon->addInterface(netif);
+ BOOST_CHECK_EQUAL(this->listUdp4McastFaces().size(), 0);
+ BOOST_CHECK_EQUAL(this->listUdp6McastFaces().size(), 0);
+
+ // netif is loopback
+ netif = this->makeFakeNetif();
+ netif->setFlags(netif->getFlags() | IFF_LOOPBACK);
+ netmon->addInterface(netif);
+ BOOST_CHECK_EQUAL(this->listUdp4McastFaces().size(), 0);
+ BOOST_CHECK_EQUAL(this->listUdp6McastFaces().size(), 0);
+
+ // netif cannot multicast
+ netif = this->makeFakeNetif();
+ netif->setFlags(netif->getFlags() & ~IFF_MULTICAST);
+ netmon->addInterface(netif);
+ BOOST_CHECK_EQUAL(this->listUdp4McastFaces().size(), 0);
+ BOOST_CHECK_EQUAL(this->listUdp6McastFaces().size(), 0);
+
+ // no viable IP address
+ netmon->addInterface(this->makeFakeNetif(false));
+ BOOST_CHECK_EQUAL(this->listUdp4McastFaces().size(), 0);
+ BOOST_CHECK_EQUAL(this->listUdp6McastFaces().size(), 0);
+}
+
+BOOST_AUTO_TEST_CASE(Disabled)
+{
+ SKIP_IF_UDP_MCAST_NETIF_COUNT_LT(1);
+
+ parseConfig("", false);
+ g_io.poll();
+
+ netmon->addInterface(const_pointer_cast<NetworkInterface>(netifs.front()));
+ BOOST_CHECK_EQUAL(this->listUdp4McastFaces().size(), 0);
+ BOOST_CHECK_EQUAL(this->listUdp6McastFaces().size(), 0);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // OnInterfaceAdded
+
BOOST_AUTO_TEST_SUITE_END() // TestUdpFactory
BOOST_AUTO_TEST_SUITE_END() // Face