tests: test IP transports under various combos of address family/scope

In particular, link-local addresses are now tested as well.

Additionally, WebSocketTransport send/receive tests are extended
to check transport counters.

Change-Id: I5b35f498a5d8d70cb1f7a2bea3ce99d22370e050
Refs: #1428
diff --git a/tests/daemon/face/transport-test-common.hpp b/tests/daemon/face/transport-test-common.hpp
index 16b9038..fa3e4bd 100644
--- a/tests/daemon/face/transport-test-common.hpp
+++ b/tests/daemon/face/transport-test-common.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2015,  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,
@@ -28,12 +28,13 @@
 
 #include "face/transport.hpp"
 #include "tests/test-common.hpp"
+#include "test-ip.hpp"
 
 namespace nfd {
 namespace face {
 namespace tests {
 
-/** \brief check a transport has all its static properties set after initialization
+/** \brief Check that a transport has all its static properties set after initialization
  *
  *  This check shall be inserted to the StaticProperties test case for each transport,
  *  in addition to checking the values of properties.
@@ -51,8 +52,66 @@
   BOOST_CHECK_NE(transport.getMtu(), MTU_INVALID);
 }
 
+/** \brief Generic wrapper for transport fixtures that require an IP address
+ */
+template<typename TransportFixtureBase,
+         AddressFamily AF = AddressFamily::Any,
+         AddressScope AS = AddressScope::Any,
+         MulticastInterface MC = MulticastInterface::Any>
+class IpTransportFixture : public TransportFixtureBase
+{
+protected:
+  IpTransportFixture()
+  {
+    BOOST_TEST_MESSAGE("Testing with AddressFamily=" << AF <<
+                       " AddressScope=" << AS <<
+                       " MulticastInterface=" << MC <<
+                       " TestIp=" << address);
+  }
+
+  std::pair<bool, std::string>
+  checkPreconditions() const
+  {
+    return {!address.is_unspecified(), "no appropriate IP address available"};
+  }
+
+  template<typename... Args>
+  void
+  initialize(Args&&... args)
+  {
+    TransportFixtureBase::initialize(address, std::forward<Args>(args)...);
+  }
+
+protected:
+  static constexpr AddressFamily addressFamily = AF;
+  static constexpr AddressScope addressScope = AS;
+  const boost::asio::ip::address address = getTestIp(AF, AS, MC);
+};
+
 } // namespace tests
 } // namespace face
 } // namespace nfd
 
+#define GENERATE_IP_TRANSPORT_FIXTURE_INSTANTIATIONS(F) \
+  IpTransportFixture<F, AddressFamily::V4, AddressScope::Loopback>,  \
+  IpTransportFixture<F, AddressFamily::V4, AddressScope::Global>,    \
+  IpTransportFixture<F, AddressFamily::V6, AddressScope::Loopback>,  \
+  IpTransportFixture<F, AddressFamily::V6, AddressScope::LinkLocal>, \
+  IpTransportFixture<F, AddressFamily::V6, AddressScope::Global>
+
+#define TRANSPORT_TEST_CHECK_PRECONDITIONS() \
+  do { \
+    auto result = this->checkPreconditions(); \
+    if (!result.first) { \
+      BOOST_WARN_MESSAGE(false, "skipping test case: " << result.second); \
+      return; \
+    } \
+  } while (false)
+
+#define TRANSPORT_TEST_INIT(...) \
+  do { \
+    TRANSPORT_TEST_CHECK_PRECONDITIONS(); \
+    this->initialize(__VA_ARGS__); \
+  } while (false)
+
 #endif // NFD_TESTS_DAEMON_FACE_TRANSPORT_TEST_COMMON_HPP