nlsr: discover Faces from NFD

refs: #2954

Change-Id: I072972d88bce0e1012e96f33577657048b7df1e1
diff --git a/tests/test-common.hpp b/tests/test-common.hpp
index 817b77e..dcba6c0 100644
--- a/tests/test-common.hpp
+++ b/tests/test-common.hpp
@@ -17,7 +17,6 @@
  * You should have received a copy of the GNU General Public License along with
  * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  *
- *
  **/
 
 #ifndef NLSR_TEST_COMMON_HPP
@@ -32,9 +31,25 @@
 #include <ndn-cxx/security/key-chain.hpp>
 #include <ndn-cxx/util/time-unit-test-clock.hpp>
 
+#include <ndn-cxx/security/signature-sha256-with-rsa.hpp>
+#include <ndn-cxx/face.hpp>
+#include <ndn-cxx/util/dummy-client-face.hpp>
+
 namespace nlsr {
 namespace test {
 
+ndn::Data&
+signData(ndn::Data& data);
+
+/** \brief add a fake signature to Data
+ */
+inline shared_ptr<ndn::Data>
+signData(shared_ptr<ndn::Data> data)
+{
+  signData(*data);
+  return data;
+}
+
 class BaseFixture
 {
 public:
@@ -65,25 +80,89 @@
   }
 
   void
-  advanceClocks(const ndn::time::nanoseconds& tick, size_t nTicks = 1)
-  {
-    for (size_t i = 0; i < nTicks; ++i) {
-      steadyClock->advance(tick);
-      systemClock->advance(tick);
-
-      if (g_ioService.stopped()) {
-        g_ioService.reset();
-      }
-
-      g_ioService.poll();
-    }
-  }
+  advanceClocks(const ndn::time::nanoseconds& tick, size_t nTicks = 1);
 
 protected:
   std::shared_ptr<ndn::time::UnitTestSteadyClock> steadyClock;
   std::shared_ptr<ndn::time::UnitTestSystemClock> systemClock;
 };
 
+class MockNfdMgmtFixture : public UnitTestTimeFixture
+{
+public:
+  MockNfdMgmtFixture();
+
+  /** \brief send one WireEncodable in reply to StatusDataset request
+   *  \param prefix dataset prefix without version and segment
+   *  \param payload payload block
+   *  \note payload must fit in one Data
+   *  \pre Interest for dataset has been expressed, sendDataset has not been invoked
+   */
+  template<typename T>
+  void
+  sendDataset(const ndn::Name& prefix, const T& payload)
+  {
+    BOOST_CONCEPT_ASSERT((ndn::WireEncodable<T>));
+
+    this->sendDatasetReply(prefix, payload.wireEncode());
+  }
+
+  /** \brief send two WireEncodables in reply to StatusDataset request
+   *  \param prefix dataset prefix without version and segment
+   *  \param payload1 first vector item
+   *  \param payload2 second vector item
+   *  \note all payloads must fit in one Data
+   *  \pre Interest for dataset has been expressed, sendDataset has not been invoked
+   */
+  template<typename T1, typename T2>
+  void
+  sendDataset(const ndn::Name& prefix, const T1& payload1, const T2& payload2)
+  {
+    BOOST_CONCEPT_ASSERT((ndn::WireEncodable<T1>));
+    BOOST_CONCEPT_ASSERT((ndn::WireEncodable<T2>));
+
+    ndn::encoding::EncodingBuffer buffer;
+    payload2.wireEncode(buffer);
+    payload1.wireEncode(buffer);
+
+    this->sendDatasetReply(prefix, buffer.buf(), buffer.size());
+  }
+
+  /** \brief send a payload in reply to StatusDataset request
+   *  \param name dataset prefix without version and segment
+   *  \param contentArgs passed to Data::setContent
+   */
+  template<typename ...ContentArgs>
+  void
+  sendDatasetReply(ndn::Name name, ContentArgs&&... contentArgs)
+  {
+    name.appendVersion().appendSegment(0);
+
+    // These warnings assist in debugging when nfdc does not receive StatusDataset.
+    // They usually indicate a misspelled prefix or incorrect timing in the test case.
+    if (face->sentInterests.empty()) {
+      BOOST_WARN_MESSAGE(false, "no Interest expressed");
+    }
+    else {
+      BOOST_WARN_MESSAGE(face->sentInterests.back().getName().isPrefixOf(name),
+                         "last Interest " << face->sentInterests.back().getName() <<
+                         " cannot be satisfied by this Data " << name);
+    }
+
+    auto data = make_shared<ndn::Data>(name);
+    data->setFinalBlockId(name[-1]);
+    data->setContent(std::forward<ContentArgs>(contentArgs)...);
+    this->signDatasetReply(*data);
+    face->receive(*data);
+  }
+
+  virtual void
+  signDatasetReply(ndn::Data& data);
+
+public:
+  std::shared_ptr<ndn::util::DummyClientFace> face;
+};
+
 } // namespace test
 } // namespace nlsr