/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014,  Regents of the University of California,
 *                      Arizona Board of Regents,
 *                      Colorado State University,
 *                      University Pierre & Marie Curie, Sorbonne University,
 *                      Washington University in St. Louis,
 *                      Beijing Institute of Technology,
 *                      The University of Memphis
 *
 * This file is part of NFD (Named Data Networking Forwarding Daemon).
 * See AUTHORS.md for complete list of NFD authors and contributors.
 *
 * NFD is free software: you can redistribute it and/or modify it under the terms
 * of the GNU General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE.  See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "mgmt/face-manager.hpp"
#include "mgmt/internal-face.hpp"
#include "mgmt/face-status-publisher.hpp"

#include "face/face.hpp"
#include "../face/dummy-face.hpp"
#include "fw/face-table.hpp"
#include "fw/forwarder.hpp"
#include "face/udp-factory.hpp"

#ifdef HAVE_LIBPCAP
#include "face/ethernet-factory.hpp"
#endif // HAVE_LIBPCAP

#include "common.hpp"
#include "tests/test-common.hpp"
#include "validation-common.hpp"
#include "face-status-publisher-common.hpp"
#include "face-query-status-publisher-common.hpp"
#include "channel-status-common.hpp"

#include <ndn-cxx/encoding/tlv.hpp>
#include <ndn-cxx/management/nfd-face-event-notification.hpp>

namespace nfd {
namespace tests {

NFD_LOG_INIT("FaceManagerTest");

class FaceManagerTestFace : public DummyFace
{
public:

  FaceManagerTestFace()
    : m_closeFired(false)
  {

  }

  virtual
  ~FaceManagerTestFace()
  {

  }

  virtual void
  close()
  {
    m_closeFired = true;
  }

  bool
  didCloseFire() const
  {
    return m_closeFired;
  }

private:
  bool m_closeFired;
};

class TestFaceTable : public FaceTable
{
public:
  TestFaceTable(Forwarder& forwarder)
    : FaceTable(forwarder),
      m_addFired(false),
      m_getFired(false),
      m_dummy(make_shared<FaceManagerTestFace>())
  {

  }

  virtual
  ~TestFaceTable()
  {

  }

  virtual void
  add(shared_ptr<Face> face)
  {
    m_addFired = true;
  }

  virtual shared_ptr<Face>
  get(FaceId id) const
  {
    m_getFired = true;
    return m_dummy;
  }

  bool
  didAddFire() const
  {
    return m_addFired;
  }

  bool
  didGetFire() const
  {
    return m_getFired;
  }

  void
  reset()
  {
    m_addFired = false;
    m_getFired = false;
  }

  shared_ptr<FaceManagerTestFace>&
  getDummyFace()
  {
    return m_dummy;
  }

private:
  bool m_addFired;
  mutable bool m_getFired;
  shared_ptr<FaceManagerTestFace> m_dummy;
};


class TestFaceTableFixture : public BaseFixture
{
public:
  TestFaceTableFixture()
    : m_faceTable(m_forwarder)
  {

  }

  virtual
  ~TestFaceTableFixture()
  {

  }

protected:
  Forwarder m_forwarder;
  TestFaceTable m_faceTable;
};

class TestFaceManagerCommon
{
public:
  TestFaceManagerCommon()
    : m_face(make_shared<InternalFace>()),
      m_callbackFired(false)
  {

  }

  virtual
  ~TestFaceManagerCommon()
  {

  }

  shared_ptr<InternalFace>&
  getFace()
  {
    return m_face;
  }

  void
  validateControlResponseCommon(const Data& response,
                                const Name& expectedName,
                                uint32_t expectedCode,
                                const std::string& expectedText,
                                ControlResponse& control)
  {
    m_callbackFired = true;
    Block controlRaw = response.getContent().blockFromValue();

    control.wireDecode(controlRaw);

    // NFD_LOG_DEBUG("received control response"
    //               << " Name: " << response.getName()
    //               << " code: " << control.getCode()
    //               << " text: " << control.getText());

    BOOST_CHECK_EQUAL(response.getName(), expectedName);
    BOOST_CHECK_EQUAL(control.getCode(), expectedCode);
    BOOST_CHECK_EQUAL(control.getText(), expectedText);
  }

  void
  validateControlResponse(const Data& response,
                          const Name& expectedName,
                          uint32_t expectedCode,
                          const std::string& expectedText)
  {
    ControlResponse control;
    validateControlResponseCommon(response, expectedName,
                                  expectedCode, expectedText, control);

    if (!control.getBody().empty())
      {
        BOOST_FAIL("found unexpected control response body");
      }
  }

  void
  validateControlResponse(const Data& response,
                          const Name& expectedName,
                          uint32_t expectedCode,
                          const std::string& expectedText,
                          const Block& expectedBody)
  {
    ControlResponse control;
    validateControlResponseCommon(response, expectedName,
                                  expectedCode, expectedText, control);

    BOOST_REQUIRE(!control.getBody().empty());
    BOOST_REQUIRE(control.getBody().value_size() == expectedBody.value_size());

    BOOST_CHECK(memcmp(control.getBody().value(), expectedBody.value(),
                       expectedBody.value_size()) == 0);

  }

  bool
  didCallbackFire() const
  {
    return m_callbackFired;
  }

  void
  resetCallbackFired()
  {
    m_callbackFired = false;
  }

protected:
  shared_ptr<InternalFace> m_face;
  bool m_callbackFired;
  ndn::KeyChain m_testKeyChain;
};

class FaceManagerFixture : public TestFaceTableFixture, public TestFaceManagerCommon
{
public:
  FaceManagerFixture()
    : m_manager(m_faceTable, m_face, m_testKeyChain)
  {
    m_manager.setConfigFile(m_config);
  }

  virtual
  ~FaceManagerFixture()
  {

  }

  void
  parseConfig(const std::string configuration, bool isDryRun)
  {
    m_config.parse(configuration, isDryRun, "dummy-config");
  }

  FaceManager&
  getManager()
  {
    return m_manager;
  }

  void
  addInterestRule(const std::string& regex,
                  ndn::IdentityCertificate& certificate)
  {
    m_manager.addInterestRule(regex, certificate);
  }

  bool
  didFaceTableAddFire() const
  {
    return m_faceTable.didAddFire();
  }

  bool
  didFaceTableGetFire() const
  {
    return m_faceTable.didGetFire();
  }

  void
  resetFaceTable()
  {
    m_faceTable.reset();
  }

protected:
  FaceManager m_manager;
  ConfigFile m_config;
};

BOOST_FIXTURE_TEST_SUITE(MgmtFaceManager, FaceManagerFixture)

bool
isExpectedException(const ConfigFile::Error& error, const std::string& expectedMessage)
{
  if (error.what() != expectedMessage)
    {
      NFD_LOG_ERROR("expected: " << expectedMessage << "\tgot: " << error.what());
    }
  return error.what() == expectedMessage;
}

#ifdef HAVE_UNIX_SOCKETS

BOOST_AUTO_TEST_CASE(TestProcessSectionUnix)
{
  const std::string CONFIG =
    "face_system\n"
    "{\n"
    "  unix\n"
    "  {\n"
    "    path /tmp/nfd.sock\n"
    "  }\n"
    "}\n";
  BOOST_TEST_CHECKPOINT("Calling parse");
  BOOST_CHECK_NO_THROW(parseConfig(CONFIG, false));
}

BOOST_AUTO_TEST_CASE(TestProcessSectionUnixDryRun)
{
  const std::string CONFIG =
    "face_system\n"
    "{\n"
    "  unix\n"
    "  {\n"
    "    path /var/run/nfd.sock\n"
    "  }\n"
    "}\n";

  BOOST_CHECK_NO_THROW(parseConfig(CONFIG, true));
}

BOOST_AUTO_TEST_CASE(TestProcessSectionUnixUnknownOption)
{
  const std::string CONFIG =
    "face_system\n"
    "{\n"
    "  unix\n"
    "  {\n"
    "    hello\n"
    "  }\n"
    "}\n";
  BOOST_CHECK_EXCEPTION(parseConfig(CONFIG, false), ConfigFile::Error,
                        bind(&isExpectedException, _1,
                             "Unrecognized option \"hello\" in \"unix\" section"));
}

#endif // HAVE_UNIX_SOCKETS


BOOST_AUTO_TEST_CASE(TestProcessSectionTcp)
{
  const std::string CONFIG =
    "face_system\n"
    "{\n"
    "  tcp\n"
    "  {\n"
    "    listen yes\n"
    "    port 6363\n"
    "    enable_v4 yes\n"
    "    enable_v6 yes\n"
    "  }\n"
    "}\n";
  try
    {
      parseConfig(CONFIG, false);
    }
  catch (const std::runtime_error& e)
    {
      const std::string reason = e.what();
      if (reason.find("Address in use") != std::string::npos)
        {
          BOOST_FAIL(reason);
        }
    }
}

BOOST_AUTO_TEST_CASE(TestProcessSectionTcpDryRun)
{
  const std::string CONFIG =
    "face_system\n"
    "{\n"
    "  tcp\n"
    "  {\n"
    "    listen yes\n"
    "    port 6363\n"
    "    enable_v4 yes\n"
    "    enable_v6 yes\n"
    "  }\n"
    "}\n";
  BOOST_CHECK_NO_THROW(parseConfig(CONFIG, true));
}

BOOST_AUTO_TEST_CASE(TestProcessSectionTcpBadListen)
{
  const std::string CONFIG =
    "face_system\n"
    "{\n"
    "  tcp\n"
    "  {\n"
    "    listen hello\n"
    "  }\n"
    "}\n";
  BOOST_CHECK_EXCEPTION(parseConfig(CONFIG, false), ConfigFile::Error,
                        bind(&isExpectedException, _1,
                             "Invalid value for option \"listen\" in \"tcp\" section"));
}

BOOST_AUTO_TEST_CASE(TestProcessSectionTcpChannelsDisabled)
{
  const std::string CONFIG =
    "face_system\n"
    "{\n"
    "  tcp\n"
    "  {\n"
    "    port 6363\n"
    "    enable_v4 no\n"
    "    enable_v6 no\n"
    "  }\n"
    "}\n";
  BOOST_CHECK_EXCEPTION(parseConfig(CONFIG, false), ConfigFile::Error,
                        bind(&isExpectedException, _1,
                             "IPv4 and IPv6 channels have been disabled."
                             " Remove \"tcp\" section to disable TCP channels or"
                             " re-enable at least one channel type."));
}

BOOST_AUTO_TEST_CASE(TestProcessSectionTcpUnknownOption)
{
  const std::string CONFIG =
    "face_system\n"
    "{\n"
    "  tcp\n"
    "  {\n"
    "    hello\n"
    "  }\n"
    "}\n";
  BOOST_CHECK_EXCEPTION(parseConfig(CONFIG, false), ConfigFile::Error,
                        bind(&isExpectedException, _1,
                             "Unrecognized option \"hello\" in \"tcp\" section"));
}

BOOST_AUTO_TEST_CASE(TestProcessSectionUdp)
{
  const std::string CONFIG =
    "face_system\n"
    "{\n"
    "  udp\n"
    "  {\n"
    "    port 6363\n"
    "    enable_v4 yes\n"
    "    enable_v6 yes\n"
    "    idle_timeout 30\n"
    "    keep_alive_interval 25\n"
    "    mcast yes\n"
    "    mcast_port 56363\n"
    "    mcast_group 224.0.23.170\n"
    "  }\n"
    "}\n";
  BOOST_CHECK_NO_THROW(parseConfig(CONFIG, false));
}

BOOST_AUTO_TEST_CASE(TestProcessSectionUdpDryRun)
{
  const std::string CONFIG =
    "face_system\n"
    "{\n"
    "  udp\n"
    "  {\n"
    "    port 6363\n"
    "    idle_timeout 30\n"
    "    keep_alive_interval 25\n"
    "    mcast yes\n"
    "    mcast_port 56363\n"
    "    mcast_group 224.0.23.170\n"
    "  }\n"
    "}\n";
  BOOST_CHECK_NO_THROW(parseConfig(CONFIG, true));
}

BOOST_AUTO_TEST_CASE(TestProcessSectionUdpBadIdleTimeout)
{
  const std::string CONFIG =
    "face_system\n"
    "{\n"
    "  udp\n"
    "  {\n"
    "    idle_timeout hello\n"
    "  }\n"
    "}\n";

  BOOST_CHECK_EXCEPTION(parseConfig(CONFIG, false), ConfigFile::Error,
                        bind(&isExpectedException, _1,
                             "Invalid value for option \"idle_timeout\" in \"udp\" section"));
}

BOOST_AUTO_TEST_CASE(TestProcessSectionUdpBadMcast)
{
  const std::string CONFIG =
    "face_system\n"
    "{\n"
    "  udp\n"
    "  {\n"
    "    mcast hello\n"
    "  }\n"
    "}\n";

  BOOST_CHECK_EXCEPTION(parseConfig(CONFIG, false), ConfigFile::Error,
                        bind(&isExpectedException, _1,
                             "Invalid value for option \"mcast\" in \"udp\" section"));
}

BOOST_AUTO_TEST_CASE(TestProcessSectionUdpBadMcastGroup)
{
  const std::string CONFIG =
    "face_system\n"
    "{\n"
    "  udp\n"
    "  {\n"
    "    mcast no\n"
    "    mcast_port 50\n"
    "    mcast_group hello\n"
    "  }\n"
    "}\n";

  BOOST_CHECK_EXCEPTION(parseConfig(CONFIG, false), ConfigFile::Error,
                        bind(&isExpectedException, _1,
                             "Invalid value for option \"mcast_group\" in \"udp\" section"));
}

BOOST_AUTO_TEST_CASE(TestProcessSectionUdpBadMcastGroupV6)
{
  const std::string CONFIG =
    "face_system\n"
    "{\n"
    "  udp\n"
    "  {\n"
    "    mcast no\n"
    "    mcast_port 50\n"
    "    mcast_group ::1\n"
    "  }\n"
    "}\n";

  BOOST_CHECK_EXCEPTION(parseConfig(CONFIG, false), ConfigFile::Error,
                        bind(&isExpectedException, _1,
                             "Invalid value for option \"mcast_group\" in \"udp\" section"));
}

BOOST_AUTO_TEST_CASE(TestProcessSectionUdpChannelsDisabled)
{
  const std::string CONFIG =
    "face_system\n"
    "{\n"
    "  udp\n"
    "  {\n"
    "    port 6363\n"
    "    enable_v4 no\n"
    "    enable_v6 no\n"
    "    idle_timeout 30\n"
    "    keep_alive_interval 25\n"
    "    mcast yes\n"
    "    mcast_port 56363\n"
    "    mcast_group 224.0.23.170\n"
    "  }\n"
    "}\n";
  BOOST_CHECK_EXCEPTION(parseConfig(CONFIG, false), ConfigFile::Error,
                        bind(&isExpectedException, _1,
                             "IPv4 and IPv6 channels have been disabled."
                             " Remove \"udp\" section to disable UDP channels or"
                             " re-enable at least one channel type."));
}

BOOST_AUTO_TEST_CASE(TestProcessSectionUdpConflictingMcast)
{
  const std::string CONFIG =
    "face_system\n"
    "{\n"
    "  udp\n"
    "  {\n"
    "    port 6363\n"
    "    enable_v4 no\n"
    "    enable_v6 yes\n"
    "    idle_timeout 30\n"
    "    keep_alive_interval 25\n"
    "    mcast yes\n"
    "    mcast_port 56363\n"
    "    mcast_group 224.0.23.170\n"
    "  }\n"
    "}\n";
  BOOST_CHECK_EXCEPTION(parseConfig(CONFIG, false), ConfigFile::Error,
                        bind(&isExpectedException, _1,
                             "IPv4 multicast requested, but IPv4 channels"
                             " have been disabled (conflicting configuration options set)"));
}



BOOST_AUTO_TEST_CASE(TestProcessSectionUdpUnknownOption)
{
  const std::string CONFIG =
    "face_system\n"
    "{\n"
    "  udp\n"
    "  {\n"
    "    hello\n"
    "  }\n"
    "}\n";
  BOOST_CHECK_EXCEPTION(parseConfig(CONFIG, false), ConfigFile::Error,
                        bind(&isExpectedException, _1,
                             "Unrecognized option \"hello\" in \"udp\" section"));
}


BOOST_AUTO_TEST_CASE(TestProcessSectionUdpMulticastReinit)
{
  const std::string CONFIG_WITH_MCAST =
    "face_system\n"
    "{\n"
    "  udp\n"
    "  {\n"
    "    mcast yes\n"
    "  }\n"
    "}\n";
  BOOST_CHECK_NO_THROW(parseConfig(CONFIG_WITH_MCAST, false));

  shared_ptr<UdpFactory> factory = static_pointer_cast<UdpFactory>(getManager().findFactory("udp"));
  BOOST_REQUIRE(static_cast<bool>(factory));

  if (factory->getMulticastFaces().size() == 0) {
    BOOST_TEST_MESSAGE("Destroying multicast faces is not tested because "
                       "no UDP multicast faces are available");
  }

  const std::string CONFIG_WITHOUT_MCAST =
    "face_system\n"
    "{\n"
    "  udp\n"
    "  {\n"
    "    mcast no\n"
    "  }\n"
    "}\n";
  BOOST_CHECK_NO_THROW(parseConfig(CONFIG_WITHOUT_MCAST, false));
  BOOST_CHECK_EQUAL(factory->getMulticastFaces().size(), 0);
}


#ifdef HAVE_LIBPCAP

BOOST_AUTO_TEST_CASE(TestProcessSectionEther)
{

  const std::string CONFIG =
    "face_system\n"
    "{\n"
    "  ether\n"
    "  {\n"
    "    mcast yes\n"
    "    mcast_group 01:00:5E:00:17:AA\n"
    "  }\n"
    "}\n";

  BOOST_CHECK_NO_THROW(parseConfig(CONFIG, false));
}

BOOST_AUTO_TEST_CASE(TestProcessSectionEtherDryRun)
{
  const std::string CONFIG =
    "face_system\n"
    "{\n"
    "  ether\n"
    "  {\n"
    "    mcast yes\n"
    "    mcast_group 01:00:5E:00:17:AA\n"
    "  }\n"
    "}\n";

  BOOST_CHECK_NO_THROW(parseConfig(CONFIG, true));
}

BOOST_AUTO_TEST_CASE(TestProcessSectionEtherBadMcast)
{
  const std::string CONFIG =
    "face_system\n"
    "{\n"
    "  ether\n"
    "  {\n"
    "    mcast hello\n"
    "  }\n"
    "}\n";

  BOOST_CHECK_EXCEPTION(parseConfig(CONFIG, false), ConfigFile::Error,
                        bind(&isExpectedException, _1,
                             "Invalid value for option \"mcast\" in \"ether\" section"));
}

BOOST_AUTO_TEST_CASE(TestProcessSectionEtherBadMcastGroup)
{
  const std::string CONFIG =
    "face_system\n"
    "{\n"
    "  ether\n"
    "  {\n"
    "    mcast yes\n"
    "    mcast_group\n"
    "  }\n"
    "}\n";

  BOOST_CHECK_EXCEPTION(parseConfig(CONFIG, false), ConfigFile::Error,
                        bind(&isExpectedException, _1,
                             "Invalid value for option \"mcast_group\" in \"ether\" section"));
}

BOOST_AUTO_TEST_CASE(TestProcessSectionEtherUnknownOption)
{
  const std::string CONFIG =
    "face_system\n"
    "{\n"
    "  ether\n"
    "  {\n"
    "    hello\n"
    "  }\n"
    "}\n";
  BOOST_CHECK_EXCEPTION(parseConfig(CONFIG, false), ConfigFile::Error,
                        bind(&isExpectedException, _1,
                             "Unrecognized option \"hello\" in \"ether\" section"));
}

BOOST_AUTO_TEST_CASE(TestProcessSectionEtherMulticastReinit)
{
  const std::string CONFIG_WITH_MCAST =
    "face_system\n"
    "{\n"
    "  ether\n"
    "  {\n"
    "    mcast yes\n"
    "  }\n"
    "}\n";
  BOOST_CHECK_NO_THROW(parseConfig(CONFIG_WITH_MCAST, false));

  shared_ptr<EthernetFactory> factory =
    static_pointer_cast<EthernetFactory>(getManager().findFactory("ether"));
  BOOST_REQUIRE(static_cast<bool>(factory));

  if (factory->getMulticastFaces().size() == 0) {
    BOOST_TEST_MESSAGE("Destroying multicast faces is not tested because "
                       "no Ethernet multicast faces are available");
  }

  const std::string CONFIG_WITHOUT_MCAST =
    "face_system\n"
    "{\n"
    "  ether\n"
    "  {\n"
    "    mcast no\n"
    "  }\n"
    "}\n";
  BOOST_CHECK_NO_THROW(parseConfig(CONFIG_WITHOUT_MCAST, false));
  BOOST_CHECK_EQUAL(factory->getMulticastFaces().size(), 0);
}

#endif // HAVE_LIBPCAP

BOOST_AUTO_TEST_CASE(ShortName)
{
  shared_ptr<Interest> command(make_shared<Interest>("/localhost/nfd/faces"));

  getFace()->onReceiveData.connect([this, command] (const Data& response) {
    this->validateControlResponse(response, command->getName(), 400, "Malformed command");
  });

  getFace()->sendInterest(*command);
  g_io.run_one();

  BOOST_REQUIRE(didCallbackFire());
}

BOOST_AUTO_TEST_CASE(MalformedCommmand)
{
  shared_ptr<Interest> command(make_shared<Interest>("/localhost/nfd/faces"));

  getFace()->onReceiveData.connect([this, command] (const Data& response) {
    this->validateControlResponse(response, command->getName(), 400, "Malformed command");
  });

  getManager().onFaceRequest(*command);

  BOOST_REQUIRE(didCallbackFire());
}

BOOST_AUTO_TEST_CASE(UnsignedCommand)
{
  ControlParameters parameters;
  parameters.setUri("tcp4://127.0.0.1:6363");

  Block encodedParameters(parameters.wireEncode());

  Name commandName("/localhost/nfd/faces");
  commandName.append("create");
  commandName.append(encodedParameters);

  shared_ptr<Interest> command(make_shared<Interest>(commandName));

  getFace()->onReceiveData.connect([this, command] (const Data& response) {
    this->validateControlResponse(response, command->getName(), 401, "Signature required");
  });

  getManager().onFaceRequest(*command);

  BOOST_REQUIRE(didCallbackFire());
}

BOOST_FIXTURE_TEST_CASE(UnauthorizedCommand, UnauthorizedCommandFixture<FaceManagerFixture>)
{
  ControlParameters parameters;
  parameters.setUri("tcp4://127.0.0.1:6363");

  Block encodedParameters(parameters.wireEncode());

  Name commandName("/localhost/nfd/faces");
  commandName.append("create");
  commandName.append(encodedParameters);

  shared_ptr<Interest> command(make_shared<Interest>(commandName));
  generateCommand(*command);

  getFace()->onReceiveData.connect([this, command] (const Data& response) {
    this->validateControlResponse(response, command->getName(), 403, "Unauthorized command");
  });

  getManager().onFaceRequest(*command);

  BOOST_REQUIRE(didCallbackFire());
}

template <typename T> class AuthorizedCommandFixture : public CommandFixture<T>
{
public:
  AuthorizedCommandFixture()
  {
    const std::string regex = "^<localhost><nfd><faces>";
    T::addInterestRule(regex, *CommandFixture<T>::m_certificate);
  }

  virtual
  ~AuthorizedCommandFixture()
  {

  }
};

BOOST_FIXTURE_TEST_CASE(UnsupportedCommand, AuthorizedCommandFixture<FaceManagerFixture>)
{
  ControlParameters parameters;

  Block encodedParameters(parameters.wireEncode());

  Name commandName("/localhost/nfd/faces");
  commandName.append("unsupported");
  commandName.append(encodedParameters);

  shared_ptr<Interest> command(make_shared<Interest>(commandName));
  generateCommand(*command);

  getFace()->onReceiveData.connect([this, command] (const Data& response) {
    this->validateControlResponse(response, command->getName(), 501, "Unsupported command");
  });

  getManager().onFaceRequest(*command);

  BOOST_REQUIRE(didCallbackFire());
}

class ValidatedFaceRequestFixture : public TestFaceTableFixture,
                                    public TestFaceManagerCommon,
                                    public FaceManager
{
public:

  ValidatedFaceRequestFixture()
    : FaceManager(TestFaceTableFixture::m_faceTable, getFace(), m_testKeyChain),
      m_createFaceFired(false),
      m_destroyFaceFired(false)
  {

  }

  virtual void
  createFace(const Interest& request,
             ControlParameters& parameters)
  {
    m_createFaceFired = true;
  }

  virtual void
  destroyFace(const Interest& request,
              ControlParameters& parameters)
  {
    m_destroyFaceFired = true;
  }

  virtual
  ~ValidatedFaceRequestFixture()
  {

  }

  bool
  didCreateFaceFire() const
  {
    return m_createFaceFired;
  }

  bool
  didDestroyFaceFire() const
  {
    return m_destroyFaceFired;
  }

private:
  bool m_createFaceFired;
  bool m_destroyFaceFired;
};

BOOST_FIXTURE_TEST_CASE(ValidatedFaceRequestBadOptionParse,
                        AuthorizedCommandFixture<ValidatedFaceRequestFixture>)
{
  Name commandName("/localhost/nfd/faces");
  commandName.append("create");
  commandName.append("NotReallyParameters");

  shared_ptr<Interest> command(make_shared<Interest>(commandName));
  generateCommand(*command);

  getFace()->onReceiveData.connect([this, command] (const Data& response) {
    this->validateControlResponse(response, command->getName(), 400, "Malformed command");
  });

  onValidatedFaceRequest(command);

  BOOST_REQUIRE(didCallbackFire());
}

BOOST_FIXTURE_TEST_CASE(ValidatedFaceRequestCreateFace,
                        AuthorizedCommandFixture<ValidatedFaceRequestFixture>)
{
  ControlParameters parameters;
  parameters.setUri("tcp4://127.0.0.1:6363");

  Block encodedParameters(parameters.wireEncode());

  Name commandName("/localhost/nfd/faces");
  commandName.append("create");
  commandName.append(encodedParameters);

  shared_ptr<Interest> command(make_shared<Interest>(commandName));
  generateCommand(*command);

  onValidatedFaceRequest(command);
  BOOST_CHECK(didCreateFaceFire());
}

BOOST_FIXTURE_TEST_CASE(ValidatedFaceRequestDestroyFace,
                        AuthorizedCommandFixture<ValidatedFaceRequestFixture>)
{
  ControlParameters parameters;
  parameters.setUri("tcp4://127.0.0.1:6363");

  Block encodedParameters(parameters.wireEncode());

  Name commandName("/localhost/nfd/faces");
  commandName.append("destroy");
  commandName.append(encodedParameters);

  shared_ptr<Interest> command(make_shared<Interest>(commandName));
  generateCommand(*command);

  onValidatedFaceRequest(command);
  BOOST_CHECK(didDestroyFaceFire());
}

class FaceTableFixture
{
public:
  FaceTableFixture()
    : m_faceTable(m_forwarder)
  {
  }

  virtual
  ~FaceTableFixture()
  {
  }

protected:
  Forwarder m_forwarder;
  FaceTable m_faceTable;
};

class LocalControlFixture : public FaceTableFixture,
                            public TestFaceManagerCommon,
                            public FaceManager
{
public:
  LocalControlFixture()
    : FaceManager(FaceTableFixture::m_faceTable, getFace(), m_testKeyChain)
  {
  }
};

BOOST_FIXTURE_TEST_CASE(LocalControlInFaceId,
                        AuthorizedCommandFixture<LocalControlFixture>)
{
  shared_ptr<LocalFace> dummy = make_shared<DummyLocalFace>();
  BOOST_REQUIRE(dummy->isLocal());
  FaceTableFixture::m_faceTable.add(dummy);

  ControlParameters parameters;
  parameters.setLocalControlFeature(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID);

  Block encodedParameters(parameters.wireEncode());

  Name enable("/localhost/nfd/faces/enable-local-control");
  enable.append(encodedParameters);

  shared_ptr<Interest> enableCommand(make_shared<Interest>(enable));
  enableCommand->setIncomingFaceId(dummy->getId());

  generateCommand(*enableCommand);

  signal::Connection conn = getFace()->onReceiveData.connect(
      [this, enableCommand, encodedParameters] (const Data& response) {
        this->validateControlResponse(response, enableCommand->getName(),
                                      200, "Success", encodedParameters);
      });

  onValidatedFaceRequest(enableCommand);

  BOOST_REQUIRE(didCallbackFire());
  BOOST_REQUIRE(dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
  BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));

  conn.disconnect();
  resetCallbackFired();

  Name disable("/localhost/nfd/faces/disable-local-control");
  disable.append(encodedParameters);

  shared_ptr<Interest> disableCommand(make_shared<Interest>(disable));
  disableCommand->setIncomingFaceId(dummy->getId());

  generateCommand(*disableCommand);

  getFace()->onReceiveData.connect(
      [this, disableCommand, encodedParameters] (const Data& response) {
        this->validateControlResponse(response, disableCommand->getName(),
                                      200, "Success", encodedParameters);
      });

  onValidatedFaceRequest(disableCommand);

  BOOST_REQUIRE(didCallbackFire());
  BOOST_REQUIRE(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
  BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
}

BOOST_FIXTURE_TEST_CASE(LocalControlInFaceIdFaceNotFound,
                        AuthorizedCommandFixture<LocalControlFixture>)
{
  shared_ptr<LocalFace> dummy = make_shared<DummyLocalFace>();
  BOOST_REQUIRE(dummy->isLocal());
  FaceTableFixture::m_faceTable.add(dummy);

  ControlParameters parameters;
  parameters.setLocalControlFeature(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID);

  Block encodedParameters(parameters.wireEncode());

  Name enable("/localhost/nfd/faces/enable-local-control");
  enable.append(encodedParameters);

  shared_ptr<Interest> enableCommand(make_shared<Interest>(enable));
  enableCommand->setIncomingFaceId(dummy->getId() + 100);

  generateCommand(*enableCommand);

  signal::Connection conn = getFace()->onReceiveData.connect(
      [this, enableCommand] (const Data& response) {
        this->validateControlResponse(response, enableCommand->getName(), 410, "Face not found");
      });

  onValidatedFaceRequest(enableCommand);

  BOOST_REQUIRE(didCallbackFire());
  BOOST_REQUIRE(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
  BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));

  conn.disconnect();
  resetCallbackFired();

  Name disable("/localhost/nfd/faces/disable-local-control");
  disable.append(encodedParameters);

  shared_ptr<Interest> disableCommand(make_shared<Interest>(disable));
  disableCommand->setIncomingFaceId(dummy->getId() + 100);

  generateCommand(*disableCommand);

  getFace()->onReceiveData.connect(
      [this, disableCommand] (const Data& response) {
        this->validateControlResponse(response, disableCommand->getName(), 410, "Face not found");
      });

  onValidatedFaceRequest(disableCommand);

  BOOST_REQUIRE(didCallbackFire());
  BOOST_REQUIRE(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
  BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
}

BOOST_FIXTURE_TEST_CASE(LocalControlMissingFeature,
                        AuthorizedCommandFixture<LocalControlFixture>)
{
  shared_ptr<LocalFace> dummy = make_shared<DummyLocalFace>();
  BOOST_REQUIRE(dummy->isLocal());
  FaceTableFixture::m_faceTable.add(dummy);

  ControlParameters parameters;

  Block encodedParameters(parameters.wireEncode());

  Name enable("/localhost/nfd/faces/enable-local-control");
  enable.append(encodedParameters);

  shared_ptr<Interest> enableCommand(make_shared<Interest>(enable));
  enableCommand->setIncomingFaceId(dummy->getId());

  generateCommand(*enableCommand);

  signal::Connection conn = getFace()->onReceiveData.connect(
      [this, enableCommand] (const Data& response) {
        this->validateControlResponse(response, enableCommand->getName(),
                                      400, "Malformed command");
      });

  onValidatedFaceRequest(enableCommand);

  BOOST_REQUIRE(didCallbackFire());
  BOOST_REQUIRE(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
  BOOST_REQUIRE(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));

  conn.disconnect();
  resetCallbackFired();

  Name disable("/localhost/nfd/faces/disable-local-control");
  disable.append(encodedParameters);

  shared_ptr<Interest> disableCommand(make_shared<Interest>(disable));
  disableCommand->setIncomingFaceId(dummy->getId());

  generateCommand(*disableCommand);

  getFace()->onReceiveData.connect(
      [this, disableCommand] (const Data& response) {
        this->validateControlResponse(response, disableCommand->getName(),
                                      400, "Malformed command");
      });

  onValidatedFaceRequest(disableCommand);

  BOOST_REQUIRE(didCallbackFire());
  BOOST_REQUIRE(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
  BOOST_REQUIRE(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
}

BOOST_FIXTURE_TEST_CASE(LocalControlInFaceIdNonLocal,
                        AuthorizedCommandFixture<LocalControlFixture>)
{
  shared_ptr<DummyFace> dummy = make_shared<DummyFace>();
  BOOST_REQUIRE(!dummy->isLocal());
  FaceTableFixture::m_faceTable.add(dummy);

  ControlParameters parameters;
  parameters.setLocalControlFeature(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID);

  Block encodedParameters(parameters.wireEncode());

  Name enable("/localhost/nfd/faces/enable-local-control");
  enable.append(encodedParameters);

  shared_ptr<Interest> enableCommand(make_shared<Interest>(enable));
  enableCommand->setIncomingFaceId(dummy->getId());

  generateCommand(*enableCommand);

  signal::Connection conn = getFace()->onReceiveData.connect(
      [this, enableCommand] (const Data& response) {
        this->validateControlResponse(response, enableCommand->getName(),
                                      412, "Face is non-local");
      });

  onValidatedFaceRequest(enableCommand);

  BOOST_REQUIRE(didCallbackFire());

  conn.disconnect();
  resetCallbackFired();

  Name disable("/localhost/nfd/faces/disable-local-control");
  enable.append(encodedParameters);

  shared_ptr<Interest> disableCommand(make_shared<Interest>(enable));
  disableCommand->setIncomingFaceId(dummy->getId());

  generateCommand(*disableCommand);

  getFace()->onReceiveData.connect(
      [this, disableCommand] (const Data& response) {
        this->validateControlResponse(response, disableCommand->getName(),
                                      412, "Face is non-local");
      });

  onValidatedFaceRequest(disableCommand);

  BOOST_REQUIRE(didCallbackFire());
}

BOOST_FIXTURE_TEST_CASE(LocalControlNextHopFaceId,
                        AuthorizedCommandFixture<LocalControlFixture>)
{
  shared_ptr<LocalFace> dummy = make_shared<DummyLocalFace>();
  BOOST_REQUIRE(dummy->isLocal());
  FaceTableFixture::m_faceTable.add(dummy);

  ControlParameters parameters;
  parameters.setLocalControlFeature(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID);

  Block encodedParameters(parameters.wireEncode());

  Name enable("/localhost/nfd/faces/enable-local-control");
  enable.append(encodedParameters);

  shared_ptr<Interest> enableCommand(make_shared<Interest>(enable));
  enableCommand->setIncomingFaceId(dummy->getId());

  generateCommand(*enableCommand);

  signal::Connection conn = getFace()->onReceiveData.connect(
      [this, enableCommand, encodedParameters] (const Data& response) {
        this->validateControlResponse(response, enableCommand->getName(),
                                      200, "Success", encodedParameters);
      });

  onValidatedFaceRequest(enableCommand);

  BOOST_REQUIRE(didCallbackFire());
  BOOST_REQUIRE(dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
  BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));


  conn.disconnect();
  resetCallbackFired();

  Name disable("/localhost/nfd/faces/disable-local-control");
  disable.append(encodedParameters);

  shared_ptr<Interest> disableCommand(make_shared<Interest>(disable));
  disableCommand->setIncomingFaceId(dummy->getId());

  generateCommand(*disableCommand);

  getFace()->onReceiveData.connect(
      [this, disableCommand, encodedParameters] (const Data& response) {
        this->validateControlResponse(response, disableCommand->getName(),
                                      200, "Success", encodedParameters);
      });

  onValidatedFaceRequest(disableCommand);

  BOOST_REQUIRE(didCallbackFire());
  BOOST_REQUIRE(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
  BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
}

BOOST_FIXTURE_TEST_CASE(LocalControlNextHopFaceIdFaceNotFound,
                        AuthorizedCommandFixture<LocalControlFixture>)
{
  shared_ptr<LocalFace> dummy = make_shared<DummyLocalFace>();
  BOOST_REQUIRE(dummy->isLocal());
  FaceTableFixture::m_faceTable.add(dummy);

  ControlParameters parameters;
  parameters.setLocalControlFeature(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID);

  Block encodedParameters(parameters.wireEncode());

  Name enable("/localhost/nfd/faces/enable-local-control");
  enable.append(encodedParameters);

  shared_ptr<Interest> enableCommand(make_shared<Interest>(enable));
  enableCommand->setIncomingFaceId(dummy->getId() + 100);

  generateCommand(*enableCommand);

  signal::Connection conn = getFace()->onReceiveData.connect(
      [this, enableCommand] (const Data& response) {
        this->validateControlResponse(response, enableCommand->getName(), 410, "Face not found");
      });

  onValidatedFaceRequest(enableCommand);

  BOOST_REQUIRE(didCallbackFire());
  BOOST_REQUIRE(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
  BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));


  conn.disconnect();
  resetCallbackFired();

  Name disable("/localhost/nfd/faces/disable-local-control");
  disable.append(encodedParameters);

  shared_ptr<Interest> disableCommand(make_shared<Interest>(disable));
  disableCommand->setIncomingFaceId(dummy->getId() + 100);

  generateCommand(*disableCommand);

  getFace()->onReceiveData.connect(
      [this, disableCommand] (const Data& response) {
        this->validateControlResponse(response, disableCommand->getName(),
                                      410, "Face not found");
      });

  onValidatedFaceRequest(disableCommand);

  BOOST_REQUIRE(didCallbackFire());
  BOOST_REQUIRE(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID));
  BOOST_CHECK(!dummy->isLocalControlHeaderEnabled(LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID));
}

BOOST_FIXTURE_TEST_CASE(LocalControlNextHopFaceIdNonLocal,
                        AuthorizedCommandFixture<LocalControlFixture>)
{
  shared_ptr<DummyFace> dummy = make_shared<DummyFace>();
  BOOST_REQUIRE(!dummy->isLocal());
  FaceTableFixture::m_faceTable.add(dummy);

  ControlParameters parameters;
  parameters.setLocalControlFeature(LOCAL_CONTROL_FEATURE_NEXT_HOP_FACE_ID);

  Block encodedParameters(parameters.wireEncode());

  Name enable("/localhost/nfd/faces/enable-local-control");
  enable.append(encodedParameters);

  shared_ptr<Interest> enableCommand(make_shared<Interest>(enable));
  enableCommand->setIncomingFaceId(dummy->getId());

  generateCommand(*enableCommand);

  signal::Connection conn = getFace()->onReceiveData.connect(
      [this, enableCommand] (const Data& response) {
        this->validateControlResponse(response, enableCommand->getName(),
                                      412, "Face is non-local");
      });

  onValidatedFaceRequest(enableCommand);

  BOOST_REQUIRE(didCallbackFire());

  conn.disconnect();
  resetCallbackFired();

  Name disable("/localhost/nfd/faces/disable-local-control");
  disable.append(encodedParameters);

  shared_ptr<Interest> disableCommand(make_shared<Interest>(disable));
  disableCommand->setIncomingFaceId(dummy->getId());

  generateCommand(*disableCommand);

  getFace()->onReceiveData.connect(
      [this, disableCommand] (const Data& response) {
        this->validateControlResponse(response, disableCommand->getName(),
                                      412, "Face is non-local");
      });

  onValidatedFaceRequest(disableCommand);

  BOOST_REQUIRE(didCallbackFire());
}

class FaceFixture : public FaceTableFixture,
                    public TestFaceManagerCommon,
                    public FaceManager
{
public:
  FaceFixture()
    : FaceManager(FaceTableFixture::m_faceTable,
                  getFace(),
                  m_testKeyChain)
    , m_receivedNotification(false)
  {

  }

  virtual
  ~FaceFixture()
  {

  }

  void
  callbackDispatch(const Data& response,
                   const Name& expectedName,
                   uint32_t expectedCode,
                   const std::string& expectedText,
                   const Block& expectedBody,
                   const ndn::nfd::FaceEventNotification& expectedFaceEvent)
  {
    Block payload = response.getContent().blockFromValue();
    if (payload.type() == ndn::tlv::nfd::ControlResponse)
      {
        validateControlResponse(response, expectedName, expectedCode,
                                expectedText, expectedBody);
      }
    else if (payload.type() == ndn::tlv::nfd::FaceEventNotification)
      {
        validateFaceEvent(payload, expectedFaceEvent);
      }
    else
      {
        BOOST_FAIL("Received unknown message type: #" << payload.type());
      }
  }

  void
  callbackDispatch(const Data& response,
                   const Name& expectedName,
                   uint32_t expectedCode,
                   const std::string& expectedText,
                   const ndn::nfd::FaceEventNotification& expectedFaceEvent)
  {
    Block payload = response.getContent().blockFromValue();
    if (payload.type() == ndn::tlv::nfd::ControlResponse)
      {
        validateControlResponse(response, expectedName,
                                expectedCode, expectedText);
      }
    else if (payload.type() == ndn::tlv::nfd::FaceEventNotification)
      {
        validateFaceEvent(payload, expectedFaceEvent);
      }
    else
      {
        BOOST_FAIL("Received unknown message type: #" << payload.type());
      }
  }

  void
  validateFaceEvent(const Block& wire,
                    const ndn::nfd::FaceEventNotification& expectedFaceEvent)
  {

    m_receivedNotification = true;

    ndn::nfd::FaceEventNotification notification(wire);

    BOOST_CHECK_EQUAL(notification.getKind(), expectedFaceEvent.getKind());
    BOOST_CHECK_EQUAL(notification.getFaceId(), expectedFaceEvent.getFaceId());
    BOOST_CHECK_EQUAL(notification.getRemoteUri(), expectedFaceEvent.getRemoteUri());
    BOOST_CHECK_EQUAL(notification.getLocalUri(), expectedFaceEvent.getLocalUri());
    BOOST_CHECK_EQUAL(notification.getFaceScope(), expectedFaceEvent.getFaceScope());
    BOOST_CHECK_EQUAL(notification.getFacePersistency(), expectedFaceEvent.getFacePersistency());
    BOOST_CHECK_EQUAL(notification.getLinkType(), expectedFaceEvent.getLinkType());
  }

  bool
  didReceiveNotication() const
  {
    return m_receivedNotification;
  }

protected:
  bool m_receivedNotification;
};

BOOST_FIXTURE_TEST_CASE(CreateFaceBadUri, AuthorizedCommandFixture<FaceFixture>)
{
  ControlParameters parameters;
  parameters.setUri("tcp4:/127.0.0.1:6363");

  Block encodedParameters(parameters.wireEncode());

  Name commandName("/localhost/nfd/faces");
  commandName.append("create");
  commandName.append(encodedParameters);

  shared_ptr<Interest> command(make_shared<Interest>(commandName));
  generateCommand(*command);

  getFace()->onReceiveData.connect([this, command] (const Data& response) {
    this->validateControlResponse(response, command->getName(), 400, "Malformed command");
  });

  createFace(*command, parameters);

  BOOST_REQUIRE(didCallbackFire());
}
BOOST_FIXTURE_TEST_CASE(CreateFaceNoncanonicalUri, AuthorizedCommandFixture<FaceFixture>)
{
  ControlParameters parameters;
  parameters.setUri("tcp://127.0.0.1");

  Block encodedParameters(parameters.wireEncode());

  Name commandName("/localhost/nfd/faces");
  commandName.append("create");
  commandName.append(encodedParameters);

  shared_ptr<Interest> command(make_shared<Interest>(commandName));
  generateCommand(*command);

  getFace()->onReceiveData.connect([this, command] (const Data& response) {
    this->validateControlResponse(response, command->getName(), 400, "Non-canonical URI");
  });

  createFace(*command, parameters);

  BOOST_REQUIRE(didCallbackFire());
}

BOOST_FIXTURE_TEST_CASE(CreateFaceMissingUri, AuthorizedCommandFixture<FaceFixture>)
{
  ControlParameters parameters;

  Block encodedParameters(parameters.wireEncode());

  Name commandName("/localhost/nfd/faces");
  commandName.append("create");
  commandName.append(encodedParameters);

  shared_ptr<Interest> command(make_shared<Interest>(commandName));
  generateCommand(*command);

  getFace()->onReceiveData.connect([this, command] (const Data& response) {
    this->validateControlResponse(response, command->getName(), 400, "Malformed command");
  });

  createFace(*command, parameters);

  BOOST_REQUIRE(didCallbackFire());
}

BOOST_FIXTURE_TEST_CASE(CreateFaceUnknownScheme, AuthorizedCommandFixture<FaceFixture>)
{
  ControlParameters parameters;
  // this will be an unsupported protocol because no factories have been
  // added to the face manager
  parameters.setUri("tcp4://127.0.0.1:6363");

  Block encodedParameters(parameters.wireEncode());

  Name commandName("/localhost/nfd/faces");
  commandName.append("create");
  commandName.append(encodedParameters);

  shared_ptr<Interest> command(make_shared<Interest>(commandName));
  generateCommand(*command);

  getFace()->onReceiveData.connect([this, command] (const Data& response) {
    this->validateControlResponse(response, command->getName(), 501, "Unsupported protocol");
  });

  createFace(*command, parameters);

  BOOST_REQUIRE(didCallbackFire());
}

BOOST_FIXTURE_TEST_CASE(OnCreated, AuthorizedCommandFixture<FaceFixture>)
{
  ControlParameters parameters;
  parameters.setUri("tcp4://127.0.0.1:6363");

  Block encodedParameters(parameters.wireEncode());

  Name commandName("/localhost/nfd/faces");
  commandName.append("create");
  commandName.append(encodedParameters);

  shared_ptr<Interest> command(make_shared<Interest>(commandName));
  generateCommand(*command);

  ControlParameters resultParameters;
  resultParameters.setUri("dummy://");
  resultParameters.setFaceId(FACEID_RESERVED_MAX + 1);

  shared_ptr<DummyFace> dummy(make_shared<DummyFace>());

  ndn::nfd::FaceEventNotification expectedFaceEvent;
  expectedFaceEvent.setKind(ndn::nfd::FACE_EVENT_CREATED)
                   .setFaceId(FACEID_RESERVED_MAX + 1)
                   .setRemoteUri(dummy->getRemoteUri().toString())
                   .setLocalUri(dummy->getLocalUri().toString())
                   .setFaceScope(ndn::nfd::FACE_SCOPE_NON_LOCAL)
                   .setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT);

  Block encodedResultParameters(resultParameters.wireEncode());

  getFace()->onReceiveData.connect(
      [this, command, encodedResultParameters, expectedFaceEvent] (const Data& response) {
        this->callbackDispatch(response,command->getName(), 200, "Success",
                               encodedResultParameters, expectedFaceEvent);
      });

  onCreated(command->getName(), parameters, dummy);

  BOOST_REQUIRE(didCallbackFire());
  BOOST_REQUIRE(didReceiveNotication());
}

BOOST_FIXTURE_TEST_CASE(OnConnectFailed, AuthorizedCommandFixture<FaceFixture>)
{
  ControlParameters parameters;
  parameters.setUri("tcp4://127.0.0.1:6363");

  Block encodedParameters(parameters.wireEncode());

  Name commandName("/localhost/nfd/faces");
  commandName.append("create");
  commandName.append(encodedParameters);

  shared_ptr<Interest> command(make_shared<Interest>(commandName));
  generateCommand(*command);

  getFace()->onReceiveData.connect([this, command] (const Data& response) {
    this->validateControlResponse(response, command->getName(), 408, "unit-test-reason");
  });

  onConnectFailed(command->getName(), "unit-test-reason");

  BOOST_REQUIRE(didCallbackFire());
  BOOST_CHECK_EQUAL(didReceiveNotication(), false);
}


BOOST_FIXTURE_TEST_CASE(DestroyFace, AuthorizedCommandFixture<FaceFixture>)
{
  shared_ptr<DummyFace> dummy(make_shared<DummyFace>());
  FaceTableFixture::m_faceTable.add(dummy);

  ControlParameters parameters;
  parameters.setFaceId(dummy->getId());

  Block encodedParameters(parameters.wireEncode());

  Name commandName("/localhost/nfd/faces");
  commandName.append("destroy");
  commandName.append(encodedParameters);

  shared_ptr<Interest> command(make_shared<Interest>(commandName));
  generateCommand(*command);

  ndn::nfd::FaceEventNotification expectedFaceEvent;
  expectedFaceEvent.setKind(ndn::nfd::FACE_EVENT_DESTROYED)
                   .setFaceId(dummy->getId())
                   .setRemoteUri(dummy->getRemoteUri().toString())
                   .setLocalUri(dummy->getLocalUri().toString())
                   .setFaceScope(ndn::nfd::FACE_SCOPE_NON_LOCAL)
                   .setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERSISTENT);

  getFace()->onReceiveData.connect(
      [this, command, encodedParameters, expectedFaceEvent] (const Data& response) {
        this->callbackDispatch(response,command->getName(), 200, "Success",
                               encodedParameters, expectedFaceEvent);
      });

  destroyFace(*command, parameters);

  BOOST_REQUIRE(didCallbackFire());
  BOOST_REQUIRE(didReceiveNotication());
}

class FaceListFixture : public FaceStatusPublisherFixture
{
public:
  FaceListFixture()
    : m_manager(m_table, m_face, m_testKeyChain)
  {

  }

  virtual
  ~FaceListFixture()
  {

  }

protected:
  FaceManager m_manager;
  ndn::KeyChain m_testKeyChain;
};

BOOST_FIXTURE_TEST_CASE(TestFaceList, FaceListFixture)
{
  Name commandName("/localhost/nfd/faces/list");
  shared_ptr<Interest> command(make_shared<Interest>(commandName));

  // MAX_SEGMENT_SIZE == 4400, FaceStatus size with filler counters is 75
  // use 59 FaceStatuses to force a FaceStatus to span Data packets
  for (int i = 0; i < 59; i++)
    {
      shared_ptr<TestCountersFace> dummy(make_shared<TestCountersFace>());

      uint64_t filler = std::numeric_limits<uint64_t>::max() - 1;
      dummy->setCounters(filler, filler, filler, filler, filler, filler);

      m_referenceFaces.push_back(dummy);

      add(dummy);
    }

  ndn::EncodingBuffer buffer;

  m_face->onReceiveData.connect(bind(&FaceStatusPublisherFixture::decodeFaceStatusBlock,
                                     this, _1));

  m_manager.listFaces(*command);
  BOOST_REQUIRE(m_finished);
}

class ChannelStatusFixture : public FaceManagerFixture
{
public:
  void
  validatePublish(const Data& data, const ndn::nfd::ChannelStatus& expectedEntry)
  {
    m_callbackFired = true;
    Block b = data.getContent().blockFromValue();
    ndn::nfd::ChannelStatus entry(b);
    BOOST_CHECK_EQUAL(entry.getLocalUri(), expectedEntry.getLocalUri());
  }

  virtual shared_ptr<DummyProtocolFactory>
  addProtocolFactory(const std::string& protocol)
  {
    shared_ptr<DummyProtocolFactory> factory(make_shared<DummyProtocolFactory>());
    m_manager.m_factories[protocol] = factory;

    return factory;
  }
};

BOOST_FIXTURE_TEST_CASE(TestChannelStatus, ChannelStatusFixture)
{
  shared_ptr<DummyProtocolFactory> factory(addProtocolFactory("dummy"));
  factory->addChannel("dummy://");

  Name requestName("/localhost/nfd/faces/channels");
  shared_ptr<Interest> request(make_shared<Interest>(requestName));

  ndn::nfd::ChannelStatus expectedEntry;
  expectedEntry.setLocalUri(DummyChannel("dummy://").getUri().toString());

  m_face->onReceiveData.connect(bind(&ChannelStatusFixture::validatePublish,
                                     this, _1, expectedEntry));

  m_manager.listChannels(*request);
  BOOST_REQUIRE(m_callbackFired);
}

class FaceQueryListFixture : public FaceQueryStatusPublisherFixture
{
public:
  FaceQueryListFixture()
    : m_manager(m_table, m_face, m_testKeyChain)
  {

  }

  virtual
  ~FaceQueryListFixture()
  {

  }

protected:
  FaceManager m_manager;
  ndn::KeyChain m_testKeyChain;
};

BOOST_FIXTURE_TEST_CASE(TestValidQueryFilter, FaceQueryListFixture)
{
  Name queryName("/localhost/nfd/faces/query");
  ndn::nfd::FaceQueryFilter queryFilter;
  queryFilter.setUriScheme("dummy");
  queryName.append(queryFilter.wireEncode());

  shared_ptr<Interest> query(make_shared<Interest>(queryName));

  // add expected faces
  shared_ptr<DummyLocalFace> expectedFace1(make_shared<DummyLocalFace>());
  m_referenceFaces.push_back(expectedFace1);
  add(expectedFace1);

  shared_ptr<DummyFace> expectedFace2(make_shared<DummyFace>());
  m_referenceFaces.push_back(expectedFace2);
  add(expectedFace2);

  // add other faces
  shared_ptr<DummyFace> face1(make_shared<DummyFace>("udp://", "udp://"));
  add(face1);
  shared_ptr<DummyLocalFace> face2(make_shared<DummyLocalFace>("tcp://", "tcp://"));
  add(face2);

  m_face->onReceiveData.connect(bind(&FaceQueryStatusPublisherFixture::decodeFaceStatusBlock,
                                     this, _1));

  m_manager.listQueriedFaces(*query);
  BOOST_REQUIRE(m_finished);
}

BOOST_FIXTURE_TEST_CASE(TestInvalidQueryFilter, FaceQueryListFixture)
{
  Name queryName("/localhost/nfd/faces/query");
  ndn::nfd::FaceStatus queryFilter;
  queryName.append(queryFilter.wireEncode());

  shared_ptr<Interest> query(make_shared<Interest>(queryName));

  shared_ptr<DummyLocalFace> face(make_shared<DummyLocalFace>());
  add(face);

  m_face->onReceiveData.connect(bind(&FaceQueryStatusPublisherFixture::decodeNackBlock, this, _1));

  m_manager.listQueriedFaces(*query);
  BOOST_REQUIRE(m_finished);
}

BOOST_AUTO_TEST_SUITE_END()

} // namespace tests
} // namespace nfd
