helper+tests: API change and test case improvements of FaceContainer

Change-Id: Idf0c15907b7492404b83c9eb78a4cbeb9c721951
diff --git a/helper/ndn-face-container.cpp b/helper/ndn-face-container.cpp
index 1c37be7..5e9c6e3 100644
--- a/helper/ndn-face-container.cpp
+++ b/helper/ndn-face-container.cpp
@@ -24,9 +24,7 @@
 namespace ns3 {
 namespace ndn {
 
-FaceContainer::FaceContainer()
-{
-}
+FaceContainer::FaceContainer() = default;
 
 FaceContainer::FaceContainer(const FaceContainer& other)
 {
@@ -51,7 +49,13 @@
 void
 FaceContainer::AddAll(const FaceContainer& other)
 {
-  m_faces.insert(m_faces.end(), other.m_faces.begin(), other.m_faces.end());
+  if (this == &other) { // adding self to self, need to make a copy
+    auto copyOfFaces = other.m_faces;
+    m_faces.insert(m_faces.end(), copyOfFaces.begin(), copyOfFaces.end());
+  }
+  else {
+    m_faces.insert(m_faces.end(), other.m_faces.begin(), other.m_faces.end());
+  }
 }
 
 FaceContainer::Iterator
@@ -72,27 +76,16 @@
   return m_faces.size();
 }
 
-// void
-// FaceContainer::SetMetricToAll (uint16_t metric)
-// {
-//   for (FaceContainer::iterator it=m_faces.begin ();
-//        it != m_faces.end ();
-//        it++)
-//     {
-//       (*it)->SetMetric (metric);
-//     }
-// }
-
 void
-FaceContainer::Add(const shared_ptr<Face>& face)
+FaceContainer::Add(shared_ptr<Face> face)
 {
   m_faces.push_back(face);
 }
 
 shared_ptr<Face>
-FaceContainer::Get(FaceContainer::Iterator i) const
+FaceContainer::Get(size_t i) const
 {
-  return *i;
+  return m_faces.at(i);
 }
 
 } // namespace ndn
diff --git a/helper/ndn-face-container.hpp b/helper/ndn-face-container.hpp
index 84d8e7f..e55cc2a 100644
--- a/helper/ndn-face-container.hpp
+++ b/helper/ndn-face-container.hpp
@@ -46,100 +46,89 @@
   typedef std::vector<shared_ptr<Face>> Container;
 
 public:
-  typedef Container::const_iterator Iterator; ///< \brief Iterator over FaceContainer
+  typedef Container::const_iterator Iterator; ///< @brief Iterator over FaceContainer
 
   /**
-   * \brief Create an empty FaceContainer.
+   * @brief Create an empty FaceContainer.
    */
   FaceContainer();
 
   /**
-   * \brief Copy constructor for FaceContainer. Calls AddAll method
+   * @brief Copy constructor for FaceContainer. Calls AddAll method
    *
-   * \see FaceContainer::AddAll
+   * @see FaceContainer::AddAll
    */
   FaceContainer(const FaceContainer& other);
 
   /**
-   * \brief Copy operator for FaceContainer. Empties vector and calls AddAll method
+   * @brief Copy operator for FaceContainer. Empties vector and calls AddAll method
    *
    * All previously obtained iterators (Begin() and End()) will be invalidated
    *
-   * \see FaceContainer::AddAll
+   * @see FaceContainer::AddAll
    */
   FaceContainer&
   operator=(const FaceContainer& other);
 
   /**
-   * \brief Add all entries from other container
+   * Add an entry to the container
    *
-   * \param other smart pointer to a container
+   * @param face a smart pointer to a Face-derived object
+   */
+  void
+  Add(shared_ptr<Face> face);
+
+  /**
+   * @brief Add all entries from other container
+   *
+   * @param other smart pointer to a container
    */
   void
   AddAll(Ptr<FaceContainer> other);
 
   /**
-   * \brief Add all entries from other container
+   * @brief Add all entries from other container
    *
-   * \param other container
+   * @param other container
    */
   void
   AddAll(const FaceContainer& other);
 
+public: // accessors
   /**
-   * \brief Get an iterator which refers to the first pair in the
+   * @brief Get an iterator which refers to the first pair in the
    * container.
    *
-   * \returns an iterator which refers to the first pair in the container.
+   * @returns an iterator which refers to the first pair in the container.
    */
   Iterator
   Begin() const;
 
   /**
-   * \brief Get an iterator which indicates past-the-last Node in the
+   * @brief Get an iterator which indicates past-the-last Node in the
    * container.
    *
-   * \returns an iterator which indicates an ending condition for a loop.
+   * @returns an iterator which indicates an ending condition for a loop.
    */
   Iterator
   End() const;
 
   /**
-   * \brief Get the number of faces stored in this container
+   * @brief Get the number of faces stored in this container
    *
-   * \returns the number of faces stored in this container
+   * @returns the number of faces stored in this container
    */
   uint32_t
   GetN() const;
 
-  // /**
-  //  * \brief Set a metric for all faces in the container
-  //  *
-  //  * \param metric value of metric to assign to all faces in the container
-  //  */
-  // void SetMetricToAll (uint16_t metric);
-
   /**
-   * Add an entry to the container
+   * Get a Face stored in the container
    *
-   * \param face a smart pointer to a Face-derived object
-   *
-   * @see Face
-   */
-  void
-  Add(const shared_ptr<Face>& face);
-
-  /**
-   * Get a smart pointer to Face-derived object stored in the container
-   *
-   * \param i the iterator corresponding to the requested object
-   *
-   * This method is redundant and simple dereferencing of the iterator should be used instead
-   *
-   * @see Face
+   * @param pos index of the Face in the container
+   * @throw std::out_of_range if !(pos < GetN()).
    */
   shared_ptr<Face>
-  Get(Iterator i) const;
+  Get(size_t pos) const;
 
 private:
   Container m_faces;
diff --git a/tests/unit-tests/helper/ndn-face-container.t.cpp b/tests/unit-tests/helper/ndn-face-container.t.cpp
index 59df4b9..5d0800d 100644
--- a/tests/unit-tests/helper/ndn-face-container.t.cpp
+++ b/tests/unit-tests/helper/ndn-face-container.t.cpp
@@ -27,6 +27,8 @@
 #include "ns3/point-to-point-module.h"
 #include "ns3/ndnSIM-module.h"
 
+#include "NFD/daemon/face/null-face.hpp"
+
 #include "../tests-common.hpp"
 
 namespace ns3 {
@@ -34,25 +36,63 @@
 
 BOOST_FIXTURE_TEST_SUITE(HelperNdnFaceContainer, CleanupFixture)
 
+BOOST_AUTO_TEST_CASE(Basic)
+{
+  FaceContainer c1;
+  BOOST_CHECK_EQUAL(c1.GetN(), 0);
+
+  c1.Add(std::make_shared<nfd::NullFace>(FaceUri("null://1")));
+  BOOST_CHECK_EQUAL(c1.GetN(), 1);
+
+  c1.Add(std::make_shared<nfd::NullFace>(FaceUri("null://2")));
+  BOOST_CHECK_EQUAL(c1.GetN(), 2);
+
+  FaceContainer c2(c1);
+  BOOST_CHECK_EQUAL(c2.GetN(), c1.GetN());
+
+  FaceContainer c3;
+  BOOST_CHECK_EQUAL(c3.GetN(), 0);
+
+  c3 = c1;
+  BOOST_CHECK_EQUAL(c3.GetN(), c1.GetN());
+
+  for (size_t i = 0; i < c1.GetN(); ++i) {
+    BOOST_CHECK_EQUAL(c1.Get(i)->getLocalUri(), c2.Get(i)->getLocalUri());
+    BOOST_CHECK_EQUAL(c1.Get(i)->getLocalUri(), c3.Get(i)->getLocalUri());
+  }
+
+  size_t pos = 0;
+  for (FaceContainer::Iterator i = c1.Begin(); i != c1.End(); ++i, ++pos) {
+    BOOST_CHECK_EQUAL((*i)->getLocalUri(), c2.Get(pos)->getLocalUri());
+    BOOST_CHECK_EQUAL((*i)->getLocalUri(), c3.Get(pos)->getLocalUri());
+  }
+}
+
 BOOST_AUTO_TEST_CASE(AddAll)
 {
- NodeContainer nodes;
- nodes.Create(4);
+  FaceContainer c1;
+  c1.Add(std::make_shared<nfd::NullFace>(FaceUri("null://1")));
+  c1.Add(std::make_shared<nfd::NullFace>(FaceUri("null://2")));
 
- PointToPointHelper p2p;
- p2p.Install(nodes.Get(0), nodes.Get(1));
- p2p.Install(nodes.Get(0), nodes.Get(2));
- p2p.Install(nodes.Get(0), nodes.Get(3));
+  FaceContainer c2(c1);
+  c2.AddAll(c1);
+  BOOST_CHECK_EQUAL(c2.GetN(), 4);
 
- StackHelper ndnHelper;
- ndnHelper.SetDefaultRoutes(true);
+  FaceContainer c3(c1);
+  c3.AddAll(c3);
+  BOOST_CHECK_EQUAL(c3.GetN(), 4);
 
- Ptr<FaceContainer> a = ndnHelper.InstallAll();
- FaceContainer b;
- b.AddAll(a);
+  Ptr<FaceContainer> c4 = Create<FaceContainer>(c1);
+  c4->AddAll(c4);
 
- BOOST_CHECK_EQUAL_COLLECTIONS(a->Begin(), a->Begin() + a->GetN(),
-                               b.Begin(), b.End());
+  BOOST_CHECK_EQUAL_COLLECTIONS(c2.Begin(), c2.Begin() + c1.GetN(),
+                                c1.Begin(), c1.End());
+
+  BOOST_CHECK_EQUAL_COLLECTIONS(c2.Begin() + c1.GetN(), c2.End(),
+                                c1.Begin(), c1.End());
+
+  BOOST_CHECK_EQUAL_COLLECTIONS(c2.Begin(), c2.End(), c3.Begin(), c3.End());
+  BOOST_CHECK_EQUAL_COLLECTIONS(c2.Begin(), c2.End(), c4->Begin(), c4->End());
 }
 
 BOOST_AUTO_TEST_SUITE_END()