face: configuration option to make UDP multicast face "ad hoc"

Change-Id: Ifd407f42e9646826697f73ab1890c819fce16857
Refs: #4018, #3967
diff --git a/tests/daemon/face/multicast-udp-transport-fixture.hpp b/tests/daemon/face/multicast-udp-transport-fixture.hpp
index b8ed524..574cb58 100644
--- a/tests/daemon/face/multicast-udp-transport-fixture.hpp
+++ b/tests/daemon/face/multicast-udp-transport-fixture.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2016,  Regents of the University of California,
+ * Copyright (c) 2014-2017,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -63,10 +63,12 @@
     udp::socket sockTx(g_io);
     localEp = udp::endpoint(address, 7001);
     openMulticastSockets(sockRx, sockTx, localEp.port());
+    ndn::nfd::LinkType linkType = ndn::nfd::LINK_TYPE_MULTI_ACCESS;
 
     face = make_unique<Face>(
              make_unique<DummyReceiveLinkService>(),
-             make_unique<MulticastUdpTransport>(localEp, multicastEp, std::move(sockRx), std::move(sockTx)));
+             make_unique<MulticastUdpTransport>(localEp, multicastEp, std::move(sockRx),
+                                                std::move(sockTx), linkType));
     transport = static_cast<MulticastUdpTransport*>(face->getTransport());
     receivedPackets = &static_cast<DummyReceiveLinkService*>(face->getLinkService())->receivedPackets;
 
diff --git a/tests/daemon/face/udp-factory.t.cpp b/tests/daemon/face/udp-factory.t.cpp
index 265bf97..14a0aee 100644
--- a/tests/daemon/face/udp-factory.t.cpp
+++ b/tests/daemon/face/udp-factory.t.cpp
@@ -124,15 +124,15 @@
   }
 
   std::vector<const Face*>
-  listUdpMcastFaces() const
+  listUdpMcastFaces(ndn::nfd::LinkType linkType = ndn::nfd::LINK_TYPE_MULTI_ACCESS) const
   {
-    return this->listFacesByScheme("udp4", ndn::nfd::LINK_TYPE_MULTI_ACCESS);
+    return this->listFacesByScheme("udp4", linkType);
   }
 
   size_t
-  countUdpMcastFaces() const
+  countUdpMcastFaces(ndn::nfd::LinkType linkType = ndn::nfd::LINK_TYPE_MULTI_ACCESS) const
   {
-    return this->listUdpMcastFaces().size();
+    return this->listUdpMcastFaces(linkType).size();
   }
 
   /** \brief determine whether a UDP multicast face is created on \p netif
@@ -199,6 +199,28 @@
   BOOST_CHECK_EQUAL(this->countUdpMcastFaces(), 0);
 }
 
+BOOST_FIXTURE_TEST_CASE(McastAdHoc, UdpMcastConfigFixture)
+{
+#ifdef __linux__
+  // need superuser privilege for creating multicast faces on linux
+  SKIP_IF_NOT_SUPERUSER();
+#endif // __linux__
+  SKIP_IF_UDP_MCAST_NETIF_COUNT_LT(1);
+
+  const std::string CONFIG = R"CONFIG(
+    face_system
+    {
+      udp
+      {
+        mcast_ad_hoc yes
+      }
+    }
+  )CONFIG";
+
+  parseConfig(CONFIG, false);
+  BOOST_CHECK_EQUAL(this->countUdpMcastFaces(ndn::nfd::LINK_TYPE_AD_HOC), netifs.size());
+}
+
 BOOST_FIXTURE_TEST_CASE(ChangeMcastEndpoint, UdpMcastConfigFixture)
 {
 #ifdef __linux__